Browse Source

Examples: DirectX11 example application handles window resizing.

ocornut 10 years ago
parent
commit
66a5837ba8

+ 78 - 67
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;
-
-    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();
+    {
+        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);
+
+        // 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();
 

+ 4 - 1
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 <windows.h> types. You can copy the extern declaration in your code.

+ 39 - 20
examples/directx11_example/main.cpp

@@ -1,5 +1,4 @@
 // ImGui - standalone example application for DirectX 11
-// TODO: Allow resizing the application window.
 
 #include <imgui.h>
 #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;