diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b4cbfa5d0..489b95571 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -66,6 +66,8 @@ Other changes: - 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. - 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 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) diff --git a/examples/example_win32_directx10/main.cpp b/examples/example_win32_directx10/main.cpp index 94d5e02d4..21198da9a 100644 --- a/examples/example_win32_directx10/main.cpp +++ b/examples/example_win32_directx10/main.cpp @@ -16,6 +16,7 @@ // Data static ID3D10Device* g_pd3dDevice = nullptr; static IDXGISwapChain* g_pSwapChain = nullptr; +static bool g_SwapChainOccluded = false; static UINT g_ResizeWidth = 0, g_ResizeHeight = 0; static ID3D10RenderTargetView* g_mainRenderTargetView = nullptr; @@ -100,6 +101,14 @@ int main(int, char**) if (done) 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) if (g_ResizeWidth != 0 && g_ResizeHeight != 0) { @@ -158,10 +167,13 @@ int main(int, char**) g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha); 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_ImplWin32_Shutdown(); ImGui::DestroyContext(); diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp index 19422c152..5285df102 100644 --- a/examples/example_win32_directx11/main.cpp +++ b/examples/example_win32_directx11/main.cpp @@ -16,6 +16,7 @@ static ID3D11Device* g_pd3dDevice = nullptr; static ID3D11DeviceContext* g_pd3dDeviceContext = nullptr; static IDXGISwapChain* g_pSwapChain = nullptr; +static bool g_SwapChainOccluded = false; static UINT g_ResizeWidth = 0, g_ResizeHeight = 0; static ID3D11RenderTargetView* g_mainRenderTargetView = nullptr; @@ -100,6 +101,14 @@ int main(int, char**) if (done) 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) if (g_ResizeWidth != 0 && g_ResizeHeight != 0) { @@ -158,8 +167,10 @@ int main(int, char**) g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, clear_color_with_alpha); 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 diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index b146129ec..57a481c71 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -26,6 +26,8 @@ #pragma comment(lib, "dxguid.lib") #endif +#include "imgui_internal.h" + struct FrameContext { ID3D12CommandAllocator* CommandAllocator; @@ -47,6 +49,7 @@ static ID3D12Fence* g_fence = nullptr; static HANDLE g_fenceEvent = nullptr; static UINT64 g_fenceLastSignaledValue = 0; static IDXGISwapChain3* g_pSwapChain = nullptr; +static bool g_SwapChainOccluded = false; static HANDLE g_hSwapChainWaitableObject = nullptr; static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {}; static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {}; @@ -137,6 +140,14 @@ int main(int, char**) if (done) 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 ImGui_ImplDX12_NewFrame(); ImGui_ImplWin32_NewFrame(); @@ -209,8 +220,10 @@ int main(int, char**) 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; g_pd3dCommandQueue->Signal(g_fence, fenceValue); diff --git a/examples/example_win32_directx9/main.cpp b/examples/example_win32_directx9/main.cpp index f36b3ea58..422248bcb 100644 --- a/examples/example_win32_directx9/main.cpp +++ b/examples/example_win32_directx9/main.cpp @@ -15,6 +15,7 @@ // Data static LPDIRECT3D9 g_pD3D = nullptr; static LPDIRECT3DDEVICE9 g_pd3dDevice = nullptr; +static bool g_DeviceLost = false; static UINT g_ResizeWidth = 0, g_ResizeHeight = 0; static D3DPRESENT_PARAMETERS g_d3dpp = {}; @@ -98,6 +99,20 @@ int main(int, char**) if (done) 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) if (g_ResizeWidth != 0 && g_ResizeHeight != 0) { @@ -163,12 +178,11 @@ int main(int, char**) g_pd3dDevice->EndScene(); } 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_ImplWin32_Shutdown(); ImGui::DestroyContext();