Browse Source

Viewports, Backends: DX12: Fix for crash caused by early resource release. (#3121)

SergeyN 5 năm trước cách đây
mục cha
commit
013013737f
1 tập tin đã thay đổi với 15 bổ sung2 xóa
  1. 15 2
      examples/imgui_impl_dx12.cpp

+ 15 - 2
examples/imgui_impl_dx12.cpp

@@ -815,7 +815,8 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
         desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
         desc.NodeMask = 1;
 
-        IM_ASSERT(g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&data->RtvDescHeap)) == S_OK);
+        HRESULT hr = g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&data->RtvDescHeap));
+        IM_ASSERT(hr == S_OK);
 
         SIZE_T rtv_descriptor_size = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
         D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = data->RtvDescHeap->GetCPUDescriptorHandleForHeapStart();
@@ -847,12 +848,24 @@ static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport)
     // The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it.
     if (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData)
     {
+        // Wait for pending operations to complete to safely release objects below
+        HRESULT hr;
+        if (data->CommandQueue && data->Fence && data->FenceEvent)
+        {
+           hr = data->CommandQueue->Signal(data->Fence, ++data->FenceSignaledValue);
+           IM_ASSERT(hr == S_OK);
+           ::WaitForSingleObject(data->FenceEvent, 0); // Reset any forgotten waits
+           hr = data->Fence->SetEventOnCompletion(data->FenceSignaledValue, data->FenceEvent);
+           IM_ASSERT(hr == S_OK);
+           ::WaitForSingleObject(data->FenceEvent, INFINITE);
+        }
+
         SafeRelease(data->CommandQueue);
         SafeRelease(data->CommandList);
         SafeRelease(data->SwapChain);
         SafeRelease(data->RtvDescHeap);
         SafeRelease(data->Fence);
-        ::CloseHandle(data->FenceEvent); 
+        ::CloseHandle(data->FenceEvent);
         data->FenceEvent = NULL;
 
         for (UINT i = 0; i < g_numFramesInFlight; i++)