Backends: DirectX12: reuse a command list and allocator for texture uploads. (#8963, #8465)

This commit is contained in:
Rémy Tassoux
2025-09-27 00:45:10 +02:00
committed by ocornut
parent 1c87024840
commit 217bc445ff
2 changed files with 20 additions and 13 deletions

View File

@@ -20,6 +20,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (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-09-18: Call platform_io.ClearRendererHandlers() on shutdown.
// 2025-06-19: Fixed build on MinGW. (#8702, #4594) // 2025-06-19: Fixed build on MinGW. (#8702, #4594)
// 2025-06-11: DirectX12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas. // 2025-06-11: DirectX12: Added support for ImGuiBackendFlags_RendererHasTextures, for dynamic font atlas.
@@ -97,6 +98,9 @@ struct ImGui_ImplDX12_Data
ID3D12DescriptorHeap* pd3dSrvDescHeap; ID3D12DescriptorHeap* pd3dSrvDescHeap;
UINT numFramesInFlight; UINT numFramesInFlight;
ID3D12CommandAllocator* pTexCmdAllocator;
ID3D12GraphicsCommandList* pTexCmdList;
ImGui_ImplDX12_RenderBuffers* pFrameResources; ImGui_ImplDX12_RenderBuffers* pFrameResources;
UINT frameIndex; UINT frameIndex;
@@ -448,13 +452,12 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
props.MemoryPoolPreference = D3D12_MEMORY_POOL_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; ID3D12Resource* uploadBuffer = nullptr;
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer)); D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer));
IM_ASSERT(SUCCEEDED(hr)); IM_ASSERT(SUCCEEDED(hr));
// Create temporary command list and execute immediately
ID3D12Fence* fence = nullptr; ID3D12Fence* fence = nullptr;
hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); hr = bd->pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
IM_ASSERT(SUCCEEDED(hr)); IM_ASSERT(SUCCEEDED(hr));
@@ -462,15 +465,9 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
HANDLE event = ::CreateEvent(0, 0, 0, 0); HANDLE event = ::CreateEvent(0, 0, 0, 0);
IM_ASSERT(event != nullptr); IM_ASSERT(event != nullptr);
// FIXME-OPT: Create once and reuse? bd->pTexCmdAllocator->Reset();
ID3D12CommandAllocator* cmdAlloc = nullptr; bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr);
hr = bd->pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList;
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));
// Copy to upload buffer // Copy to upload buffer
void* mapped = nullptr; void* mapped = nullptr;
@@ -535,8 +532,6 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
fence->SetEventOnCompletion(1, event); fence->SetEventOnCompletion(1, event);
::WaitForSingleObject(event, INFINITE); ::WaitForSingleObject(event, INFINITE);
cmdList->Release();
cmdAlloc->Release();
::CloseHandle(event); ::CloseHandle(event);
fence->Release(); fence->Release();
uploadBuffer->Release(); uploadBuffer->Release();
@@ -776,6 +771,14 @@ bool ImGui_ImplDX12_CreateDeviceObjects()
if (result_pipeline_state != S_OK) if (result_pipeline_state != S_OK)
return false; 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; return true;
} }
@@ -790,6 +793,8 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
bd->commandQueueOwned = false; bd->commandQueueOwned = false;
SafeRelease(bd->pRootSignature); SafeRelease(bd->pRootSignature);
SafeRelease(bd->pPipelineState); SafeRelease(bd->pPipelineState);
SafeRelease(bd->pTexCmdList);
SafeRelease(bd->pTexCmdAllocator);
// Destroy all textures // Destroy all textures
for (ImTextureData* tex : ImGui::GetPlatformIO().Textures) for (ImTextureData* tex : ImGui::GetPlatformIO().Textures)

View File

@@ -73,6 +73,8 @@ Other Changes:
- Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and - Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and
ClearRendererHandlers() on shutdown, so as not to leave function pointers ClearRendererHandlers() on shutdown, so as not to leave function pointers
which may be dangling when using backend in e.g. DLL. (#8945, #2769) 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 - Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support
`RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes] `RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes]
- Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our - Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our