From 60ef67686aafd7c4557971ac6c2749940a24fb12 Mon Sep 17 00:00:00 2001 From: jackun Date: Tue, 28 Jul 2020 04:08:50 +0300 Subject: [PATCH] Deal with resizing and wrap things in ComPtr Still leaks objects though :( --- src/kiero/d3d12_impl.cpp | 109 +++++++++++++++++----------------- src/kiero/imgui_impl_dx12.cpp | 24 ++++++++ src/kiero/imgui_impl_dx12.h | 1 + 3 files changed, 81 insertions(+), 53 deletions(-) diff --git a/src/kiero/d3d12_impl.cpp b/src/kiero/d3d12_impl.cpp index b21f733..1f004a0 100644 --- a/src/kiero/d3d12_impl.cpp +++ b/src/kiero/d3d12_impl.cpp @@ -14,79 +14,78 @@ #include "dx_shared.h" #include -long(__stdcall* oPresent)(IDXGISwapChain3*, UINT, UINT) = nullptr; +using namespace Microsoft::WRL; + +decltype(&IDXGISwapChain3::Present) oPresent = nullptr; void(*oExecuteCommandListsD3D12)(ID3D12CommandQueue*, UINT, ID3D12CommandList*); HRESULT(*oSignalD3D12)(ID3D12CommandQueue*, ID3D12Fence*, UINT64) = nullptr; PresentD3D12 oPresentD3D12; tResizeBuffers oResizeBuffers; -ID3D12Device* d3d12Device = nullptr; -IDXGISwapChain* pSwapChain_; - -ID3D12DescriptorHeap* d3d12DescriptorHeapBackBuffers = nullptr; -ID3D12DescriptorHeap* d3d12DescriptorHeapImGuiRender = nullptr; -ID3D12GraphicsCommandList* d3d12CommandList = nullptr; -ID3D12Fence* d3d12Fence = nullptr; -UINT64 d3d12FenceValue = 0; -ID3D12CommandQueue* d3d12CommandQueue = nullptr; -using namespace Microsoft::WRL; -Microsoft::WRL::ComPtr queue; -Microsoft::WRL::ComPtr swapchain_; + +ComPtr d3d12DescriptorHeapBackBuffers; +ComPtr d3d12DescriptorHeapImGuiRender; +ComPtr d3d12CommandList; +ComPtr d3d12Fence; +UINT64 d3d12FenceValue = 0; +ComPtr d3d12CommandQueue; +ComPtr d3d12Device; bool initDX12 = false; + struct FrameContext { ID3D12CommandAllocator* commandAllocator = nullptr; ID3D12Resource* main_render_target_resource = nullptr; D3D12_CPU_DESCRIPTOR_HANDLE main_render_target_descriptor; }; -uint32_t buffersCounts = -1; -FrameContext* frameContext; +std::vector frameContext; bool DX12Init(IDXGISwapChain* pSwapChain) { - if (SUCCEEDED(pSwapChain->GetDevice(__uuidof(ID3D12Device), (void**)&d3d12Device))) { + if (SUCCEEDED(pSwapChain->GetDevice(IID_PPV_ARGS(&d3d12Device)))) { - pSwapChain_ = pSwapChain; - imgui_create(pSwapChain, d3d12Device); + imgui_create(pSwapChain, d3d12Device.Get()); ImGui::SetCurrentContext(state.imgui_ctx); - CreateEvent(nullptr, false, false, nullptr); + //CreateEvent(nullptr, false, false, nullptr); DXGI_SWAP_CHAIN_DESC sdesc; pSwapChain->GetDesc(&sdesc); - buffersCounts = sdesc.BufferCount; - frameContext = new FrameContext[buffersCounts]; + frameContext.resize(sdesc.BufferCount); D3D12_DESCRIPTOR_HEAP_DESC descriptorImGuiRender = {}; descriptorImGuiRender.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - descriptorImGuiRender.NumDescriptors = buffersCounts; + descriptorImGuiRender.NumDescriptors = sdesc.BufferCount; descriptorImGuiRender.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - if (d3d12Device->CreateDescriptorHeap(&descriptorImGuiRender, __uuidof(ID3D12DescriptorHeap), (void**)&d3d12DescriptorHeapImGuiRender)) + if (FAILED(d3d12Device->CreateDescriptorHeap(&descriptorImGuiRender, IID_PPV_ARGS(&d3d12DescriptorHeapImGuiRender)))) return false; ID3D12CommandAllocator* allocator; - if (d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&allocator) < 0) + if (FAILED(d3d12Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&allocator)))) return false; - for (size_t i = 0; i < buffersCounts; i++) { + for (size_t i = 0; i < frameContext.size(); i++) { frameContext[i].commandAllocator = allocator; } - if (d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator, NULL, __uuidof(ID3D12GraphicsCommandList), (void**)&d3d12CommandList) < 0) + if (d3d12Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, allocator, NULL, IID_PPV_ARGS(&d3d12CommandList)) < 0) return false; + // Reset() expects it to be closed, so close it now. + d3d12CommandList->Close(); + D3D12_DESCRIPTOR_HEAP_DESC descriptorBackBuffers; descriptorBackBuffers.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - descriptorBackBuffers.NumDescriptors = buffersCounts; + descriptorBackBuffers.NumDescriptors = sdesc.BufferCount; descriptorBackBuffers.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; descriptorBackBuffers.NodeMask = 1; - if (d3d12Device->CreateDescriptorHeap(&descriptorBackBuffers, __uuidof(ID3D12DescriptorHeap), (void**)&d3d12DescriptorHeapBackBuffers) != S_OK) + if (d3d12Device->CreateDescriptorHeap(&descriptorBackBuffers, IID_PPV_ARGS(&d3d12DescriptorHeapBackBuffers)) != S_OK) return false; const auto rtvDescriptorSize = d3d12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = d3d12DescriptorHeapBackBuffers->GetCPUDescriptorHandleForHeapStart(); - for (size_t i = 0; i < buffersCounts; i++) { + for (size_t i = 0; i < frameContext.size(); i++) { ID3D12Resource* pBackBuffer = nullptr; frameContext[i].main_render_target_descriptor = rtvHandle; @@ -97,8 +96,8 @@ bool DX12Init(IDXGISwapChain* pSwapChain) } auto mainWindow = sdesc.OutputWindow; ImGui_ImplWin32_Init(sdesc.OutputWindow); - ImGui_ImplDX12_Init(d3d12Device, buffersCounts, - DXGI_FORMAT_R8G8B8A8_UNORM, d3d12DescriptorHeapImGuiRender, + ImGui_ImplDX12_Init(d3d12Device.Get(), frameContext.size(), + DXGI_FORMAT_R8G8B8A8_UNORM, d3d12DescriptorHeapImGuiRender.Get(), d3d12DescriptorHeapImGuiRender->GetCPUDescriptorHandleForHeapStart(), d3d12DescriptorHeapImGuiRender->GetGPUDescriptorHandleForHeapStart()); @@ -113,8 +112,7 @@ long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT if (!initDX12) { - DX12Init(pSwapChain); - initDX12 = true; + initDX12 = DX12Init(pSwapChain); } ImGui::SetCurrentContext(state.imgui_ctx); @@ -140,10 +138,10 @@ long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT d3d12CommandList->Reset(currentFrameContext.commandAllocator, nullptr); d3d12CommandList->ResourceBarrier(1, &barrier); d3d12CommandList->OMSetRenderTargets(1, ¤tFrameContext.main_render_target_descriptor, FALSE, nullptr); - d3d12CommandList->SetDescriptorHeaps(1, &d3d12DescriptorHeapImGuiRender); + d3d12CommandList->SetDescriptorHeaps(1, d3d12DescriptorHeapImGuiRender.GetAddressOf()); // printf("imgui/d3d12 render\n"); ImGui::Render(); - ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), d3d12CommandList); + ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), d3d12CommandList.Get()); barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; @@ -151,10 +149,10 @@ long __fastcall hkPresent12(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT d3d12CommandList->ResourceBarrier(1, &barrier); d3d12CommandList->Close(); - d3d12CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&d3d12CommandList); + d3d12CommandQueue->ExecuteCommandLists(1, (ID3D12CommandList * const *)d3d12CommandList.GetAddressOf()); //ImGui::SetCurrentContext(prev_ctx); - return oPresent(pSwapChain, SyncInterval, Flags); + return std::invoke(oPresent, pSwapChain, SyncInterval, Flags); } void hookExecuteCommandListsD3D12(ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* ppCommandLists) { @@ -165,7 +163,7 @@ void hookExecuteCommandListsD3D12(ID3D12CommandQueue* queue, UINT NumCommandList } HRESULT hookSignalD3D12(ID3D12CommandQueue* queue, ID3D12Fence* fence, UINT64 value) { - if (d3d12CommandQueue != nullptr && queue == d3d12CommandQueue) { + if (d3d12CommandQueue != nullptr && queue == d3d12CommandQueue.Get()) { d3d12Fence = fence; d3d12FenceValue = value; } @@ -175,25 +173,30 @@ HRESULT hookSignalD3D12(ID3D12CommandQueue* queue, ID3D12Fence* fence, UINT64 va HRESULT __stdcall hkResizeBuffers(IDXGISwapChain* pThis, UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) { - //if (pSwapChain_) { pSwapChain_->Release(); pSwapChain_ = nullptr; } - if (d3d12CommandQueue) { d3d12CommandQueue->Release(); d3d12CommandQueue = nullptr; } - if (d3d12CommandList) { d3d12CommandList->Release(); d3d12CommandList = nullptr; } - if (d3d12Fence) { d3d12Fence->Release(); d3d12Fence = nullptr; } - if (d3d12DescriptorHeapBackBuffers) { d3d12DescriptorHeapBackBuffers->Release(); d3d12DescriptorHeapBackBuffers = nullptr; } - if (d3d12DescriptorHeapImGuiRender) { d3d12DescriptorHeapImGuiRender->Release(); d3d12DescriptorHeapImGuiRender = nullptr; } - for (uint32_t i = 0; i < sizeof(FrameContext); ++i) - { - frameContext[i] = {}; + auto allocator = frameContext[0].commandAllocator; + auto rtvHandle = frameContext[0].main_render_target_descriptor; + for (size_t i = 0; i < frameContext.size(); i++) { + frameContext[i].main_render_target_resource->Release(); } - //if (d3d12Device) { d3d12Device->Release(); d3d12Device = nullptr; } - ImGui_ImplDX12_Shutdown(); - initDX12 = false; + auto hr = oResizeBuffers(pThis, BufferCount, Width, Height, NewFormat, SwapChainFlags); if (hr != S_OK) printf("ResizeBuffers Failed\n"); - pSwapChain_ = pThis; - d3d12CommandQueue = queue.Get(); - pSwapChain_->GetDevice(__uuidof(ID3D12Device), (void**)&d3d12Device); + + frameContext.resize(BufferCount); + + const auto rtvDescriptorSize = d3d12Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + for (size_t i = 0; i < frameContext.size(); i++) { + ID3D12Resource* pBackBuffer = nullptr; + + frameContext[i].main_render_target_descriptor = rtvHandle; + pThis->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer)); + d3d12Device->CreateRenderTargetView(pBackBuffer, nullptr, rtvHandle); + frameContext[i].main_render_target_resource = pBackBuffer; + rtvHandle.ptr += rtvDescriptorSize; + } + + ImGui_ImplDX12_Resize(BufferCount); return hr; } diff --git a/src/kiero/imgui_impl_dx12.cpp b/src/kiero/imgui_impl_dx12.cpp index e7bb5e9..8281865 100644 --- a/src/kiero/imgui_impl_dx12.cpp +++ b/src/kiero/imgui_impl_dx12.cpp @@ -613,6 +613,30 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() } } +void ImGui_ImplDX12_Resize(int num_frames_in_flight) +{ + for (UINT i = 0; i < g_numFramesInFlight; i++) + { + FrameResources* fr = &g_pFrameResources[i]; + SafeRelease(fr->IndexBuffer); + SafeRelease(fr->VertexBuffer); + } + + delete[] g_pFrameResources; + g_pFrameResources = new FrameResources[num_frames_in_flight]; + g_numFramesInFlight = num_frames_in_flight; + g_frameIndex = UINT_MAX; + + for (int i = 0; i < num_frames_in_flight; i++) + { + FrameResources* fr = &g_pFrameResources[i]; + fr->IndexBuffer = NULL; + fr->VertexBuffer = NULL; + fr->IndexBufferSize = 10000; + fr->VertexBufferSize = 5000; + } +} + bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames_in_flight, DXGI_FORMAT rtv_format, ID3D12DescriptorHeap* cbv_srv_heap, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) { diff --git a/src/kiero/imgui_impl_dx12.h b/src/kiero/imgui_impl_dx12.h index 52dab0b..ba49251 100644 --- a/src/kiero/imgui_impl_dx12.h +++ b/src/kiero/imgui_impl_dx12.h @@ -30,6 +30,7 @@ IMGUI_IMPL_API bool ImGui_ImplDX12_Init(ID3D12Device* device, int num_frames IMGUI_IMPL_API void ImGui_ImplDX12_Shutdown(); IMGUI_IMPL_API void ImGui_ImplDX12_NewFrame(); IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandList* graphics_command_list); +IMGUI_IMPL_API void ImGui_ImplDX12_Resize(int num_frames_in_flight); // Use if you want to reset your rendering device without losing Dear ImGui state. IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects();