I do not call it from the WindowProc. I specifically call a function that shuts down the renderer and other sub-systems from WinMain(), after the message loop has been canceled (which happens once a WM_QUIT message has been called)
MSG msg;
memset(&msg, 0, sizeof(msg));
// this must be called by the main application thread
rdk::engine_client::IEngineClient* pEngine = rdk::engine_client::GetEngineClientInterface();
if(!pEngine->Initiate())
return 0;
bool bContinue = true;
while(bContinue)
{
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if(msg.message == WM_QUIT)
bContinue = false;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
pEngine->Update();
}
pEngine->ShutDown();
return static_cast<int>(msg.wParam);
The only other code that could possibly be relevant is my start up code. I am in the process of rewriting my engine and stopped to take care of this bug before I finish writing the full renderer. My renderer is literally just start up and shut down code right now. Here is the code I use to start it up (hopefully one of you can catch something that I may be over looking):
if(!DirectX::XMVerifyCPUSupport())
{
if(Params.pErrorLog != nullptr)
Params.pErrorLog->Print(L"[rdk::render::CRenderD3D::Initiate] DirectX::XMVerifyCPUSupport() failed\n");
return false;
};
if((m_pErrorLog != nullptr) ||
(m_pGenericLog != nullptr) ||
(m_pWindow != nullptr))
{
if(Params.pErrorLog != nullptr)
Params.pErrorLog->Print(L"[rdk::render::CRenderD3D::Initiate] already initiated\n");
return false;
}
m_pErrorLog = Params.pErrorLog;
m_pGenericLog = Params.pGenericLog;
m_pWindow = Params.pWindow;
assert(m_pErrorLog != nullptr);
assert(m_pGenericLog != nullptr);
assert(m_pWindow != nullptr);
{
std::wostringstream stream(L"Direct3D ");
stream << D3D11_MAJOR_VERSION << "." << D3D11_MINOR_VERSION << " (SDK version " << D3D11_SDK_VERSION << ")\n";
m_pGenericLog->Print(stream.str());
}
HRESULT hr;
hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&m_pFactory));
if(FAILED(hr))
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::CreateDXGIFactory] ") + str + L"\n");
ShutDown();
return false;
}
hr = m_pFactory->EnumAdapters(0, &m_pAdapter);
if(hr == DXGI_ERROR_NOT_FOUND)
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::m_pFactory->EnumAdapters] ") + str + L"\n");
ShutDown();
return false;
}
DXGI_ADAPTER_DESC Desc;
hr = m_pAdapter->GetDesc(&Desc);
if(FAILED(hr))
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::m_pAdapter->GetDesc] ") + str + L"\n");
ShutDown();
return false;
}
{
std::wostringstream stream;
stream << Desc.Description;
stream << "\n Dedicated video memory: " << (static_cast<float>(Desc.DedicatedVideoMemory) / (1024 * 1024));
stream << "\n Dedicated system memory: " << (static_cast<float>(Desc.DedicatedSystemMemory) / (1024 * 1024));
stream << "\n Shared system memory: " << (static_cast<float>(Desc.SharedSystemMemory) / (1024 * 1024)) << L"\n";
m_pGenericLog->Print(stream.str());
}
D3D_FEATURE_LEVEL featurelevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
D3D_FEATURE_LEVEL featurelevelcreated;
UINT flags = 0;
#ifdef _DEBUG
flags |= D3D11_CREATE_DEVICE_DEBUG;
if(m_pGenericLog != nullptr)
m_pGenericLog->Print(L"D3D11_CREATE_DEVICE_DEBUG\n");
#endif
long lWindowHeight = 0;
long lWindowWidth = 0;
if(!m_pWindow->GetClientSize(lWindowHeight, lWindowWidth))
{
m_pErrorLog->Print(L"[rdk::render::CRenderD3D::Initiate] m_pWindow->GetClientSize() failed\n");
ShutDown();
return false;
}
DXGI_SWAP_CHAIN_DESC scd;
memset(&scd, 0, sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount = 1;
scd.BufferDesc.Width = lWindowWidth;
scd.BufferDesc.Height = lWindowHeight;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
scd.BufferDesc.RefreshRate.Numerator = 60;
scd.BufferDesc.RefreshRate.Denominator = 1;
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
scd.OutputWindow = m_pWindow->GetHWND();
scd.SampleDesc.Count = 1;
scd.SampleDesc.Quality = 0;
scd.Windowed = Params.bWindowed;
hr = D3D11CreateDeviceAndSwapChain(m_pAdapter,
D3D_DRIVER_TYPE_UNKNOWN,
NULL,
flags,
featurelevels,
sizeof(featurelevels) / sizeof(featurelevels[0]),
D3D11_SDK_VERSION,
&scd,
&m_pSwapChain,
&m_pDevice,
&featurelevelcreated,
&m_pImmediateContext);
if(FAILED(hr))
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::D3D11CreateDeviceAndSwapChain] ") + str + L"\n");
ShutDown();
return false;
}
// check which version was created
switch(featurelevelcreated)
{
case D3D_FEATURE_LEVEL_11_0:
m_pGenericLog->Print(L"D3D_FEATURE_LEVEL_11_0\n");
break;
case D3D_FEATURE_LEVEL_10_1:
m_pGenericLog->Print(L"D3D_FEATURE_LEVEL_10_1\n");
break;
case D3D_FEATURE_LEVEL_10_0:
m_pGenericLog->Print(L"D3D_FEATURE_LEVEL_10_0\n");
break;
default: // unsupported version created
m_pErrorLog->Print(L"[rdk::render::CRenderD3D::Initiate] failed to create a supported freature level\n");
return false;
}
// create the back buffer
ID3D11Texture2D *pBuffer = nullptr;
hr = m_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&pBuffer));
if(FAILED(hr))
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::m_pSwapChain->GetBuffer] ") + str + L"\n");
ShutDown();
return false;
}
hr = m_pDevice->CreateRenderTargetView(pBuffer, NULL, &m_pRenderTargetView);
pBuffer->Release();
if(FAILED(hr))
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::m_pDevice->CreateRenderTargetView] ") + str + L"\n");
ShutDown();
return false;
}
// create the depth stencil texture
D3D11_TEXTURE2D_DESC td;
memset(&td, 0, sizeof(td));
td.Width = lWindowWidth;
td.Height = lWindowHeight;
td.MipLevels = 1;
td.ArraySize = 1;
td.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
td.SampleDesc.Count = 1;
td.SampleDesc.Quality = 0;
td.Usage = D3D11_USAGE_DEFAULT;
td.BindFlags = D3D11_BIND_DEPTH_STENCIL;
td.CPUAccessFlags = 0;
td.MiscFlags = 0;
hr = m_pDevice->CreateTexture2D(&td, NULL, &m_pDepthStencilTexture);
if(FAILED(hr))
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::m_pDevice->CreateTexture2D] ") + str + L"\n");
ShutDown();
return false;
}
// create the depth stencil view
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
memset(&dsvd, 0, sizeof(dsvd));
dsvd.Format = td.Format;
dsvd.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
dsvd.Texture2D.MipSlice = 0;
hr = m_pDevice->CreateDepthStencilView(m_pDepthStencilTexture, &dsvd, &m_pDepthStencilView);
if(FAILED(hr))
{
std::wstring str;
LastDXError(hr, str);
m_pErrorLog->Print(std::wstring(L"[rdk::render::CRenderD3D::Initiate::m_pDevice->CreateDepthStencilView] ") + str + L"\n");
ShutDown();
return false;
}
m_pImmediateContext->OMSetRenderTargets(1, &m_pRenderTargetView, m_pDepthStencilView);
// set the viewport
D3D11_VIEWPORT vp;
vp.Width = static_cast<float>(lWindowWidth);
vp.Height = static_cast<float>(lWindowHeight);
vp.MinDepth = D3D11_MIN_DEPTH; // 0.0f;
vp.MaxDepth = D3D11_MAX_DEPTH; // 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
m_pImmediateContext->RSSetViewports(1, &vp);
// create rasterize states
if(!CreateRasterizerStates())
{
m_pErrorLog->Print(L"[rdk::render::CRenderD3D::Initiate] CreateRasterizerStates() failed\n");
ShutDown();
return false;
}
m_pImmediateContext->RSSetState(m_RasterizerStates[DefaultRasterizerState]);
// create the constant buffers
if(!CreateConstantBuffers())
{
m_pErrorLog->Print(L"[rdk::render::CRenderD3D::Initiate] CreateConstantBuffers() failed\n");
ShutDown();
return false;
}
// create all sampler states
if(!CreateSamplerStates())
{
m_pErrorLog->Print(L"[rdk::render::CRender::Initiate] CreateSamplerStates() failed\n");
ShutDown();
return false;
}
// load vertex shaders
if(!LoadVertexShaders())
{
m_pErrorLog->Print(L"[rdk::render::CRender::Initiate] LoadVertexShaders() failed\n");
ShutDown();
return false;
}
// load pixel shaders
if(!LoadPixelShaders())
{
m_pErrorLog->Print(L"[rdk::render::CRender::Initiate] LoadPixelShaders() failed\n");
ShutDown();
return false;
}
// set the default world transformation matrix
SetWorldMatrix(DirectX::XMMatrixIdentity());
// attach window callbacks
if(!m_pWindow->AddCallback(WM_SIZE, Size))
{
m_pErrorLog->Print(L"[rdk::render::CRenderD3D::Initiate] Window.AddCallback(WM_SIZE) failed\n");
ShutDown();
return false;
}
return true;