mirror of
https://github.com/ocornut/imgui.git
synced 2025-10-02 16:18:33 +00:00
Backends: DX12: Rework synchronization logic. (master) (#8961)
This commit is contained in:
@@ -91,6 +91,7 @@ Other Changes:
|
||||
- Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is
|
||||
not available. (#5924, #5562)
|
||||
- Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
|
||||
- Examples: Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
|
||||
- Examples: made examples's main.cpp consistent with returning 1 on error.
|
||||
|
||||
|
||||
|
@@ -102,8 +102,8 @@ bool CreateDeviceD3D(HWND hWnd);
|
||||
void CleanupDeviceD3D();
|
||||
void CreateRenderTarget();
|
||||
void CleanupRenderTarget();
|
||||
void WaitForLastSubmittedFrame();
|
||||
FrameContext* WaitForNextFrameResources();
|
||||
void WaitForPendingOperations();
|
||||
FrameContext* WaitForNextFrameContext();
|
||||
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
// Main code
|
||||
@@ -256,7 +256,7 @@ int main(int, char**)
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
FrameContext* frameCtx = WaitForNextFrameResources();
|
||||
FrameContext* frameCtx = WaitForNextFrameContext();
|
||||
UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex();
|
||||
frameCtx->CommandAllocator->Reset();
|
||||
|
||||
@@ -282,19 +282,17 @@ int main(int, char**)
|
||||
g_pd3dCommandList->Close();
|
||||
|
||||
g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList);
|
||||
g_pd3dCommandQueue->Signal(g_fence, ++g_fenceLastSignaledValue);
|
||||
frameCtx->FenceValue = g_fenceLastSignaledValue;
|
||||
|
||||
// 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);
|
||||
g_fenceLastSignaledValue = fenceValue;
|
||||
frameCtx->FenceValue = fenceValue;
|
||||
g_frameIndex++;
|
||||
}
|
||||
|
||||
WaitForLastSubmittedFrame();
|
||||
WaitForPendingOperations();
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplDX12_Shutdown();
|
||||
@@ -465,49 +463,33 @@ void CreateRenderTarget()
|
||||
|
||||
void CleanupRenderTarget()
|
||||
{
|
||||
WaitForLastSubmittedFrame();
|
||||
WaitForPendingOperations();
|
||||
|
||||
for (UINT i = 0; i < APP_NUM_BACK_BUFFERS; i++)
|
||||
if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = nullptr; }
|
||||
}
|
||||
|
||||
void WaitForLastSubmittedFrame()
|
||||
void WaitForPendingOperations()
|
||||
{
|
||||
FrameContext* frameCtx = &g_frameContext[g_frameIndex % APP_NUM_FRAMES_IN_FLIGHT];
|
||||
g_pd3dCommandQueue->Signal(g_fence, ++g_fenceLastSignaledValue);
|
||||
|
||||
UINT64 fenceValue = frameCtx->FenceValue;
|
||||
if (fenceValue == 0)
|
||||
return; // No fence was signaled
|
||||
|
||||
frameCtx->FenceValue = 0;
|
||||
if (g_fence->GetCompletedValue() >= fenceValue)
|
||||
return;
|
||||
|
||||
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
WaitForSingleObject(g_fenceEvent, INFINITE);
|
||||
g_fence->SetEventOnCompletion(g_fenceLastSignaledValue, g_fenceEvent);
|
||||
::WaitForSingleObject(g_fenceEvent, INFINITE);
|
||||
}
|
||||
|
||||
FrameContext* WaitForNextFrameResources()
|
||||
FrameContext* WaitForNextFrameContext()
|
||||
{
|
||||
UINT nextFrameIndex = g_frameIndex + 1;
|
||||
g_frameIndex = nextFrameIndex;
|
||||
|
||||
HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, nullptr };
|
||||
DWORD numWaitableObjects = 1;
|
||||
|
||||
FrameContext* frameCtx = &g_frameContext[nextFrameIndex % APP_NUM_FRAMES_IN_FLIGHT];
|
||||
UINT64 fenceValue = frameCtx->FenceValue;
|
||||
if (fenceValue != 0) // means no fence was signaled
|
||||
FrameContext* frame_context = &g_frameContext[g_frameIndex % APP_NUM_FRAMES_IN_FLIGHT];
|
||||
if (g_fence->GetCompletedValue() < frame_context->FenceValue)
|
||||
{
|
||||
frameCtx->FenceValue = 0;
|
||||
g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent);
|
||||
waitableObjects[1] = g_fenceEvent;
|
||||
numWaitableObjects = 2;
|
||||
g_fence->SetEventOnCompletion(frame_context->FenceValue, g_fenceEvent);
|
||||
HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, g_fenceEvent };
|
||||
::WaitForMultipleObjects(2, waitableObjects, TRUE, INFINITE);
|
||||
}
|
||||
else
|
||||
::WaitForSingleObject(g_hSwapChainWaitableObject, INFINITE);
|
||||
|
||||
WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE);
|
||||
|
||||
return frameCtx;
|
||||
return frame_context;
|
||||
}
|
||||
|
||||
// Forward declare message handler from imgui_impl_win32.cpp
|
||||
@@ -528,7 +510,6 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
case WM_SIZE:
|
||||
if (g_pd3dDevice != nullptr && wParam != SIZE_MINIMIZED)
|
||||
{
|
||||
WaitForLastSubmittedFrame();
|
||||
CleanupRenderTarget();
|
||||
HRESULT result = g_pSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT);
|
||||
assert(SUCCEEDED(result) && "Failed to resize swapchain.");
|
||||
|
Reference in New Issue
Block a user