From 66a5837ba8f05090c02e12bba8a8e71dce6ddb8e Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 9 Mar 2015 14:51:10 +0000 Subject: [PATCH] Examples: DirectX11 example application handles window resizing. --- .../directx11_example/imgui_impl_dx11.cpp | 141 ++++++++++-------- examples/directx11_example/imgui_impl_dx11.h | 5 +- examples/directx11_example/main.cpp | 59 +++++--- 3 files changed, 119 insertions(+), 86 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index c2e90ae5..ffcb7cdb 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -13,7 +13,6 @@ // Data static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; -static bool g_FontTextureLoaded = false; static HWND g_hWnd = 0; static ID3D11Device* g_pd3dDevice = NULL; @@ -26,6 +25,7 @@ static ID3D11Buffer* g_pVertexConstantBuffer = NULL; static ID3D10Blob * g_pPixelShaderBlob = NULL; static ID3D11PixelShader* g_pPixelShader = NULL; static ID3D11SamplerState* g_pFontSampler = NULL; +static ID3D11ShaderResourceView*g_pFontTextureView = NULL; static ID3D11BlendState* g_blendState = NULL; struct CUSTOMVERTEX @@ -180,7 +180,7 @@ LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM return 0; } -void ImGui_ImplDX11_InitFontsTexture() +static void ImGui_ImplDX11_InitFontsTexture() { ImGuiIO& io = ImGui::GetIO(); @@ -190,55 +190,63 @@ void ImGui_ImplDX11_InitFontsTexture() io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Create DX11 texture - D3D11_TEXTURE2D_DESC texDesc; - ZeroMemory(&texDesc, sizeof(texDesc)); - texDesc.Width = width; - texDesc.Height = height; - texDesc.MipLevels = 1; - texDesc.ArraySize = 1; - texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texDesc.SampleDesc.Count = 1; - texDesc.Usage = D3D11_USAGE_DEFAULT; - texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; + { + D3D11_TEXTURE2D_DESC texDesc; + ZeroMemory(&texDesc, sizeof(texDesc)); + texDesc.Width = width; + texDesc.Height = height; + texDesc.MipLevels = 1; + texDesc.ArraySize = 1; + texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + texDesc.SampleDesc.Count = 1; + texDesc.Usage = D3D11_USAGE_DEFAULT; + texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + texDesc.CPUAccessFlags = 0; - ID3D11Texture2D *pTexture = NULL; - D3D11_SUBRESOURCE_DATA subResource; - subResource.pSysMem = pixels; - subResource.SysMemPitch = texDesc.Width * 4; - subResource.SysMemSlicePitch = 0; - g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); + ID3D11Texture2D *pTexture = NULL; + D3D11_SUBRESOURCE_DATA subResource; + subResource.pSysMem = pixels; + subResource.SysMemPitch = texDesc.Width * 4; + subResource.SysMemSlicePitch = 0; + g_pd3dDevice->CreateTexture2D(&texDesc, &subResource, &pTexture); - // Create texture view - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = texDesc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - ID3D11ShaderResourceView* font_texture_view = NULL; - g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &font_texture_view); - pTexture->Release(); + // Create texture view + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + ZeroMemory(&srvDesc, sizeof(srvDesc)); + srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = texDesc.MipLevels; + srvDesc.Texture2D.MostDetailedMip = 0; + g_pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &g_pFontTextureView); + pTexture->Release(); + } // Store our identifier - io.Fonts->TexID = (void *)font_texture_view; + io.Fonts->TexID = (void *)g_pFontTextureView; // Create texture sampler - D3D11_SAMPLER_DESC samplerDesc; - ZeroMemory(&samplerDesc, sizeof(samplerDesc)); - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - samplerDesc.MipLODBias = 0.f; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - samplerDesc.MinLOD = 0.f; - samplerDesc.MaxLOD = 0.f; - g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + { + D3D11_SAMPLER_DESC samplerDesc; + ZeroMemory(&samplerDesc, sizeof(samplerDesc)); + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; + samplerDesc.MipLODBias = 0.f; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; + samplerDesc.MinLOD = 0.f; + samplerDesc.MaxLOD = 0.f; + g_pd3dDevice->CreateSamplerState(&samplerDesc, &g_pFontSampler); + } } -static bool InitDirect3DState() +bool ImGui_ImplDX11_CreateDeviceObjects() { + if (!g_pd3dDevice) + return false; + if (g_pVB) + ImGui_ImplDX11_InvalidateDeviceObjects(); + // Create the vertex shader { static const char* vertexShader = @@ -351,21 +359,35 @@ static bool InitDirect3DState() return false; } + ImGui_ImplDX11_InitFontsTexture(); + return true; } +void ImGui_ImplDX11_InvalidateDeviceObjects() +{ + if (!g_pd3dDevice) + return; + + if (g_pFontSampler) { g_pFontSampler->Release(); g_pFontSampler = NULL; } + if (g_pFontTextureView) { g_pFontTextureView->Release(); ImGui::GetIO().Fonts->TexID = 0; } + if (g_pVB) { g_pVB->Release(); g_pVB = NULL; } + + if (g_blendState) { g_blendState->Release(); g_blendState = NULL; } + if (g_pPixelShader) { g_pPixelShader->Release(); g_pPixelShader = NULL; } + if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } + if (g_pVertexConstantBuffer) { g_pVertexConstantBuffer->Release(); g_pVertexConstantBuffer = NULL; } + if (g_pInputLayout) { g_pInputLayout->Release(); g_pInputLayout = NULL; } + if (g_pVertexShader) { g_pVertexShader->Release(); g_pVertexShader = NULL; } + if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } +} + bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context) { g_hWnd = (HWND)hwnd; g_pd3dDevice = device; g_pd3dDeviceContext = device_context; - if (!InitDirect3DState()) - { - IM_ASSERT(0); - return false; - } - if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) return false; if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) @@ -398,28 +420,17 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex void ImGui_ImplDX11_Shutdown() { - if (g_pd3dDeviceContext) g_pd3dDeviceContext->ClearState(); - - if (g_pFontSampler) g_pFontSampler->Release(); - if (ID3D11ShaderResourceView* font_texture_view = (ID3D11ShaderResourceView*)ImGui::GetIO().Fonts->TexID) - font_texture_view->Release(); - if (g_pVB) g_pVB->Release(); - - if (g_blendState) g_blendState->Release(); - if (g_pPixelShader) g_pPixelShader->Release(); - if (g_pPixelShaderBlob) g_pPixelShaderBlob->Release(); - if (g_pVertexConstantBuffer) g_pVertexConstantBuffer->Release(); - if (g_pInputLayout) g_pInputLayout->Release(); - if (g_pVertexShader) g_pVertexShader->Release(); - if (g_pVertexShaderBlob) g_pVertexShaderBlob->Release(); - + ImGui_ImplDX11_InvalidateDeviceObjects(); ImGui::Shutdown(); + g_pd3dDevice = NULL; + g_pd3dDeviceContext = NULL; + g_hWnd = (HWND)0; } void ImGui_ImplDX11_NewFrame() { - if (!g_FontTextureLoaded) - ImGui_ImplDX11_InitFontsTexture(); + if (!g_pVB) + ImGui_ImplDX11_CreateDeviceObjects(); ImGuiIO& io = ImGui::GetIO(); diff --git a/examples/directx11_example/imgui_impl_dx11.h b/examples/directx11_example/imgui_impl_dx11.h index aa33edb2..c920d0b9 100644 --- a/examples/directx11_example/imgui_impl_dx11.h +++ b/examples/directx11_example/imgui_impl_dx11.h @@ -5,10 +5,13 @@ struct ID3D11Device; struct ID3D11DeviceContext; bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context); -void ImGui_ImplDX11_InitFontsTexture(); void ImGui_ImplDX11_Shutdown(); void ImGui_ImplDX11_NewFrame(); +// Use if you want to reset your rendering device without losing ImGui state. +void ImGui_ImplDX11_InvalidateDeviceObjects(); +bool ImGui_ImplDX11_CreateDeviceObjects(); + // Handler for Win32 messages, update mouse/keyboard data. // You may or not need this for your implementation, but it can serve as reference for handling inputs. // Commented out to avoid dragging dependencies on types. You can copy the extern declaration in your code. diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 75c77064..0620245b 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -1,5 +1,4 @@ // ImGui - standalone example application for DirectX 11 -// TODO: Allow resizing the application window. #include #include "imgui_impl_dx11.h" @@ -14,7 +13,29 @@ static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; static IDXGISwapChain* g_pSwapChain = NULL; static ID3D11RenderTargetView* g_mainRenderTargetView = NULL; -HRESULT InitDeviceD3D(HWND hWnd) +void CreateRenderTarget() +{ + DXGI_SWAP_CHAIN_DESC sd; + g_pSwapChain->GetDesc(&sd); + + // Create the render target + ID3D11Texture2D* pBackBuffer; + D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc; + ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc)); + render_target_view_desc.Format = sd.BufferDesc.Format; + render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); + pBackBuffer->Release(); +} + +void CleanupRenderTarget() +{ + if (g_mainRenderTargetView) { g_mainRenderTargetView->Release(); g_mainRenderTargetView = NULL; } +} + +HRESULT CreateDeviceD3D(HWND hWnd) { // Setup swap chain DXGI_SWAP_CHAIN_DESC sd; @@ -65,28 +86,17 @@ HRESULT InitDeviceD3D(HWND hWnd) pRState->Release(); } - // Create the render target - { - ID3D11Texture2D* pBackBuffer; - D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc; - ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc)); - render_target_view_desc.Format = sd.BufferDesc.Format; - render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); - g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); - pBackBuffer->Release(); - } + CreateRenderTarget(); return S_OK; } void CleanupDeviceD3D() { - if (g_mainRenderTargetView) g_mainRenderTargetView->Release(); - if (g_pSwapChain) g_pSwapChain->Release(); - if (g_pd3dDeviceContext) g_pd3dDeviceContext->Release(); - if (g_pd3dDevice) g_pd3dDevice->Release(); + CleanupRenderTarget(); + if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; } + if (g_pd3dDeviceContext) { g_pd3dDeviceContext->Release(); g_pd3dDeviceContext = NULL; } + if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } } extern LRESULT ImGui_ImplDX11_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); @@ -97,6 +107,16 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) switch (msg) { + case WM_SIZE: + if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) + { + ImGui_ImplDX11_InvalidateDeviceObjects(); + CleanupRenderTarget(); + g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0); + CreateRenderTarget(); + ImGui_ImplDX11_CreateDeviceObjects(); + } + return 0; case WM_DESTROY: PostQuitMessage(0); return 0; @@ -112,7 +132,7 @@ int main(int argc, char** argv) HWND hwnd = CreateWindow(L"ImGui Example", L"ImGui DirectX11 Example", WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); // Initialize Direct3D - if (InitDeviceD3D(hwnd) < 0) + if (CreateDeviceD3D(hwnd) < 0) { CleanupDeviceD3D(); UnregisterClass(L"ImGui Example", wc.hInstance); @@ -131,7 +151,6 @@ int main(int argc, char** argv) //ImFont* my_font3 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyClean.ttf", 13.0f); my_font3->DisplayOffset.y += 1; //ImFont* my_font4 = io.Fonts->AddFontFromFileTTF("extra_fonts/ProggyTiny.ttf", 10.0f); my_font4->DisplayOffset.y += 1; //ImFont* my_font5 = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, io.Fonts->GetGlyphRangesJapanese()); - ImGui_ImplDX11_InitFontsTexture(); bool show_test_window = true; bool show_another_window = false;