浏览代码

Examples: Win32+DX9,DX10,DX11,DX12: rework main loop to handle minimization and screen locking. (#2496, #3907, #6308, #7615)

ocornut 1 年之前
父节点
当前提交
ec1d2be96f

+ 2 - 0
docs/CHANGELOG.txt

@@ -66,6 +66,8 @@ Other changes:
 - Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed.
 - Nav: fixed holding Ctrl or gamepad L1 from not slowing down keyboard/gamepad tweak speed.
   Broken during a refactor refactor for 1.89. Holding Shift/R1 to speed up wasn't broken.
   Broken during a refactor refactor for 1.89. Holding Shift/R1 to speed up wasn't broken.
 - Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041) [@prabuinet]
 - Tables: fixed cell background of fully clipped row overlapping with header. (#7575, #7041) [@prabuinet]
+- Examples: Win32+DX9,DX10,DX11,DX12: rework main loop to handle minimization and screen
+  locking without burning resources by running unthrottled code. (#2496, #3907, #6308, #7615)
 - Backends: all backends + demo now call IMGUI_CHECKVERSION() to verify ABI compatibility between caller
 - Backends: all backends + demo now call IMGUI_CHECKVERSION() to verify ABI compatibility between caller
   code and compiled version of Dear ImGui. If you get an assert it most likely mean you have a build issue,
   code and compiled version of Dear ImGui. If you get an assert it most likely mean you have a build issue,
   read comments near the assert. (#7568)
   read comments near the assert. (#7568)

+ 14 - 2
examples/example_win32_directx10/main.cpp

@@ -16,6 +16,7 @@
 // Data
 // Data
 static ID3D10Device*            g_pd3dDevice = nullptr;
 static ID3D10Device*            g_pd3dDevice = nullptr;
 static IDXGISwapChain*          g_pSwapChain = nullptr;
 static IDXGISwapChain*          g_pSwapChain = nullptr;
+static bool                     g_SwapChainOccluded = false;
 static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
 static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
 static ID3D10RenderTargetView*  g_mainRenderTargetView = nullptr;
 static ID3D10RenderTargetView*  g_mainRenderTargetView = nullptr;
 
 
@@ -100,6 +101,14 @@ int main(int, char**)
         if (done)
         if (done)
             break;
             break;
 
 
+        // Handle window being minimized or screen locked
+        if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
+        {
+            ::Sleep(10);
+            continue;
+        }
+        g_SwapChainOccluded = false;
+
         // Handle window resize (we don't resize directly in the WM_SIZE handler)
         // Handle window resize (we don't resize directly in the WM_SIZE handler)
         if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
         if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
         {
         {
@@ -158,10 +167,13 @@ int main(int, char**)
         g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
         g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
         ImGui_ImplDX10_RenderDrawData(ImGui::GetDrawData());
         ImGui_ImplDX10_RenderDrawData(ImGui::GetDrawData());
 
 
-        g_pSwapChain->Present(1, 0); // Present with vsync
-        //g_pSwapChain->Present(0, 0); // Present without vsync
+        // Present
+        HRESULT hr = g_pSwapChain->Present(1, 0);   // Present with vsync
+        //HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
+        g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
     }
     }
 
 
+    // Cleanup
     ImGui_ImplDX10_Shutdown();
     ImGui_ImplDX10_Shutdown();
     ImGui_ImplWin32_Shutdown();
     ImGui_ImplWin32_Shutdown();
     ImGui::DestroyContext();
     ImGui::DestroyContext();

+ 13 - 2
examples/example_win32_directx11/main.cpp

@@ -16,6 +16,7 @@
 static ID3D11Device*            g_pd3dDevice = nullptr;
 static ID3D11Device*            g_pd3dDevice = nullptr;
 static ID3D11DeviceContext*     g_pd3dDeviceContext = nullptr;
 static ID3D11DeviceContext*     g_pd3dDeviceContext = nullptr;
 static IDXGISwapChain*          g_pSwapChain = nullptr;
 static IDXGISwapChain*          g_pSwapChain = nullptr;
+static bool                     g_SwapChainOccluded = false;
 static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
 static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
 static ID3D11RenderTargetView*  g_mainRenderTargetView = nullptr;
 static ID3D11RenderTargetView*  g_mainRenderTargetView = nullptr;
 
 
@@ -100,6 +101,14 @@ int main(int, char**)
         if (done)
         if (done)
             break;
             break;
 
 
+        // Handle window being minimized or screen locked
+        if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
+        {
+            ::Sleep(10);
+            continue;
+        }
+        g_SwapChainOccluded = false;
+
         // Handle window resize (we don't resize directly in the WM_SIZE handler)
         // Handle window resize (we don't resize directly in the WM_SIZE handler)
         if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
         if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
         {
         {
@@ -158,8 +167,10 @@ int main(int, char**)
         g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
         g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha);
         ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
         ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
 
 
-        g_pSwapChain->Present(1, 0); // Present with vsync
-        //g_pSwapChain->Present(0, 0); // Present without vsync
+        // Present
+        HRESULT hr = g_pSwapChain->Present(1, 0);   // Present with vsync
+        //HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
+        g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
     }
     }
 
 
     // Cleanup
     // Cleanup

+ 15 - 2
examples/example_win32_directx12/main.cpp

@@ -26,6 +26,8 @@
 #pragma comment(lib, "dxguid.lib")
 #pragma comment(lib, "dxguid.lib")
 #endif
 #endif
 
 
+#include "imgui_internal.h"
+
 struct FrameContext
 struct FrameContext
 {
 {
     ID3D12CommandAllocator* CommandAllocator;
     ID3D12CommandAllocator* CommandAllocator;
@@ -47,6 +49,7 @@ static ID3D12Fence*                 g_fence = nullptr;
 static HANDLE                       g_fenceEvent = nullptr;
 static HANDLE                       g_fenceEvent = nullptr;
 static UINT64                       g_fenceLastSignaledValue = 0;
 static UINT64                       g_fenceLastSignaledValue = 0;
 static IDXGISwapChain3*             g_pSwapChain = nullptr;
 static IDXGISwapChain3*             g_pSwapChain = nullptr;
+static bool                         g_SwapChainOccluded = false;
 static HANDLE                       g_hSwapChainWaitableObject = nullptr;
 static HANDLE                       g_hSwapChainWaitableObject = nullptr;
 static ID3D12Resource*              g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
 static ID3D12Resource*              g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {};
 static D3D12_CPU_DESCRIPTOR_HANDLE  g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
 static D3D12_CPU_DESCRIPTOR_HANDLE  g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {};
@@ -137,6 +140,14 @@ int main(int, char**)
         if (done)
         if (done)
             break;
             break;
 
 
+        // Handle window screen locked
+        if (g_SwapChainOccluded && g_pSwapChain->Present(0, DXGI_PRESENT_TEST) == DXGI_STATUS_OCCLUDED)
+        {
+            ::Sleep(10);
+            continue;
+        }
+        g_SwapChainOccluded = false;
+
         // Start the Dear ImGui frame
         // Start the Dear ImGui frame
         ImGui_ImplDX12_NewFrame();
         ImGui_ImplDX12_NewFrame();
         ImGui_ImplWin32_NewFrame();
         ImGui_ImplWin32_NewFrame();
@@ -209,8 +220,10 @@ int main(int, char**)
 
 
         g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
         g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
 
 
-        g_pSwapChain->Present(1, 0); // Present with vsync
-        //g_pSwapChain->Present(0, 0); // Present without vsync
+        // Present
+        HRESULT hr = g_pSwapChain->Present(1, 0);   // Present with vsync
+        //HRESULT hr = g_pSwapChain->Present(0, 0); // Present without vsync
+        g_SwapChainOccluded = (hr == DXGI_STATUS_OCCLUDED);
 
 
         UINT64 fenceValue = g_fenceLastSignaledValue + 1;
         UINT64 fenceValue = g_fenceLastSignaledValue + 1;
         g_pd3dCommandQueue->Signal(g_fence, fenceValue);
         g_pd3dCommandQueue->Signal(g_fence, fenceValue);

+ 18 - 4
examples/example_win32_directx9/main.cpp

@@ -15,6 +15,7 @@
 // Data
 // Data
 static LPDIRECT3D9              g_pD3D = nullptr;
 static LPDIRECT3D9              g_pD3D = nullptr;
 static LPDIRECT3DDEVICE9        g_pd3dDevice = nullptr;
 static LPDIRECT3DDEVICE9        g_pd3dDevice = nullptr;
+static bool                     g_DeviceLost = false;
 static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
 static UINT                     g_ResizeWidth = 0, g_ResizeHeight = 0;
 static D3DPRESENT_PARAMETERS    g_d3dpp = {};
 static D3DPRESENT_PARAMETERS    g_d3dpp = {};
 
 
@@ -98,6 +99,20 @@ int main(int, char**)
         if (done)
         if (done)
             break;
             break;
 
 
+        // Handle lost D3D9 device
+        if (g_DeviceLost)
+        {
+            HRESULT hr = g_pd3dDevice->TestCooperativeLevel();
+            if (hr == D3DERR_DEVICELOST)
+            {
+                ::Sleep(10);
+                continue;
+            }
+            if (hr == D3DERR_DEVICENOTRESET)
+                ResetDevice();
+            g_DeviceLost = false;
+        }
+
         // Handle window resize (we don't resize directly in the WM_SIZE handler)
         // Handle window resize (we don't resize directly in the WM_SIZE handler)
         if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
         if (g_ResizeWidth != 0 && g_ResizeHeight != 0)
         {
         {
@@ -163,12 +178,11 @@ int main(int, char**)
             g_pd3dDevice->EndScene();
             g_pd3dDevice->EndScene();
         }
         }
         HRESULT result = g_pd3dDevice->Present(nullptr, nullptr, nullptr, nullptr);
         HRESULT result = g_pd3dDevice->Present(nullptr, nullptr, nullptr, nullptr);
-
-        // Handle loss of D3D9 device
-        if (result == D3DERR_DEVICELOST && g_pd3dDevice->TestCooperativeLevel() == D3DERR_DEVICENOTRESET)
-            ResetDevice();
+        if (result == D3DERR_DEVICELOST)
+            g_DeviceLost = true;
     }
     }
 
 
+    // Cleanup
     ImGui_ImplDX9_Shutdown();
     ImGui_ImplDX9_Shutdown();
     ImGui_ImplWin32_Shutdown();
     ImGui_ImplWin32_Shutdown();
     ImGui::DestroyContext();
     ImGui::DestroyContext();