diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index 86f1180ab..4a29cf529 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-27: DirectX12: Reuse a command list and allocator for texture uploads instead of recreating them each time. // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-06-19: Fixed build on MinGW. (#8702, #4594) // 2025-06-11: DirectX12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. @@ -97,6 +98,9 @@ struct ImGui_ImplDX12_Data ID3D12DescriptorHeap* pd3dSrvDescHeap; UINT numFramesInFlight; + ID3D12CommandAllocator* pTexCmdAllocator; + ID3D12GraphicsCommandList* pTexCmdList; + ImGui_ImplDX12_RenderBuffers* pFrameResources; UINT frameIndex; @@ -448,13 +452,12 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - // FIXME-OPT: Can upload buffer be reused? + // FIXME-OPT: Could upload buffer be kept around, reused, and grown only when needed? Would that be worth it? ID3D12Resource* uploadBuffer = nullptr; HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer)); IM_ASSERT(SUCCEEDED(hr)); - // Create temporary command list and execute immediately ID3D12Fence* fence = nullptr; hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); IM_ASSERT(SUCCEEDED(hr)); @@ -462,15 +465,9 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) HANDLE event = ::CreateEvent(0, 0, 0, 0); IM_ASSERT(event != nullptr); - // FIXME-OPT: Create once and reuse? - ID3D12CommandAllocator* cmdAlloc = nullptr; - hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); - IM_ASSERT(SUCCEEDED(hr)); - - // FIXME-OPT: Can be use the one from user? (pass ID3D12GraphicsCommandList* to ImGui_ImplDX12_UpdateTextures) - ID3D12GraphicsCommandList* cmdList = nullptr; - hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, nullptr, IID_PPV_ARGS(&cmdList)); - IM_ASSERT(SUCCEEDED(hr)); + bd->pTexCmdAllocator->Reset(); + bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr); + ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList; // Copy to upload buffer void* mapped = nullptr; @@ -535,8 +532,6 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex) fence->SetEventOnCompletion(1, event); ::WaitForSingleObject(event, INFINITE); - cmdList->Release(); - cmdAlloc->Release(); ::CloseHandle(event); fence->Release(); uploadBuffer->Release(); @@ -776,6 +771,14 @@ bool ImGui_ImplDX12_CreateDeviceObjects() if (result_pipeline_state != S_OK) return false; + // Create command allocator and command list for ImGui_ImplDX12_UpdateTexture() + HRESULT hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&bd->pTexCmdAllocator)); + IM_ASSERT(SUCCEEDED(hr)); + hr = bd->pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, bd->pTexCmdAllocator, nullptr, IID_PPV_ARGS(&bd->pTexCmdList)); + IM_ASSERT(SUCCEEDED(hr)); + hr = bd->pTexCmdList->Close(); + IM_ASSERT(SUCCEEDED(hr)); + return true; } @@ -790,6 +793,8 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() bd->commandQueueOwned = false; SafeRelease(bd->pRootSignature); SafeRelease(bd->pPipelineState); + SafeRelease(bd->pTexCmdList); + SafeRelease(bd->pTexCmdAllocator); // Destroy all textures for (ImTextureData* tex : ImGui::GetPlatformIO().Textures) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d51981138..146f1de76 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -73,6 +73,8 @@ Other Changes: - Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and ClearRendererHandlers() on shutdown, so as not to leave function pointers which may be dangling when using backend in e.g. DLL. (#8945, #2769) +- Backends: DirectX12: reuse a command list and allocator for texture uploads instead + of recreating them each time. (#8963, #8465) [@RT2Code] - Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] - Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our