mirror of
https://github.com/ocornut/imgui.git
synced 2026-01-09 23:54:20 +00:00
Merge b4cfad50cb into 396b33d0d0
This commit is contained in:
commit
ed7b3ea606
3 changed files with 48 additions and 30 deletions
|
|
@ -23,6 +23,7 @@
|
|||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
||||
// 2025-10-25: [Docking] DirectX12: Let user specifies viewports backbuffer count by setting ImGui_ImplDX12_InitInfo::BackBuffer and add support for a single frame in flight.
|
||||
// 2025-10-23: [Docking] DirectX12: Fixed an issue in synchronization logic improving rendering throughput for secondary viewports. (#8961, #9025)
|
||||
// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002)
|
||||
// 2025-09-29: DirectX12: Rework synchronization logic. (#8961)
|
||||
|
|
@ -107,6 +108,7 @@ struct ImGui_ImplDX12_Data
|
|||
ID3D12Fence* Fence;
|
||||
UINT64 FenceLastSignaledValue;
|
||||
HANDLE FenceEvent;
|
||||
UINT numBackbuffer;
|
||||
UINT numFramesInFlight;
|
||||
bool tearingSupport;
|
||||
bool LegacySingleDescriptorUsed;
|
||||
|
|
@ -136,13 +138,18 @@ struct ImGui_ImplDX12_RenderBuffers
|
|||
int VertexBufferSize;
|
||||
};
|
||||
|
||||
// Backbuffers used for secondary viewports created by the multi-viewports systems
|
||||
struct ImGui_ImplDX12_Backbuffer
|
||||
{
|
||||
ID3D12Resource* RenderTarget;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetCpuDescriptors;
|
||||
};
|
||||
|
||||
// Buffers used for secondary viewports created by the multi-viewports systems
|
||||
struct ImGui_ImplDX12_FrameContext
|
||||
{
|
||||
UINT64 FenceValue;
|
||||
ID3D12CommandAllocator* CommandAllocator;
|
||||
ID3D12Resource* RenderTarget;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE RenderTargetCpuDescriptors;
|
||||
};
|
||||
|
||||
// Helper structure we store in the void* RendererUserData field of each ImGuiViewport to easily retrieve our backend data.
|
||||
|
|
@ -156,30 +163,35 @@ struct ImGui_ImplDX12_ViewportData
|
|||
ID3D12DescriptorHeap* RtvDescHeap;
|
||||
IDXGISwapChain3* SwapChain;
|
||||
HANDLE SwapChainWaitableObject;
|
||||
UINT NumBackBuffer;
|
||||
ImGui_ImplDX12_Backbuffer* BackBuffer;
|
||||
UINT NumFramesInFlight;
|
||||
ImGui_ImplDX12_FrameContext* FrameCtx;
|
||||
|
||||
// Render buffers
|
||||
UINT FrameIndex;
|
||||
ImGui_ImplDX12_RenderBuffers* FrameRenderBuffers;
|
||||
|
||||
ImGui_ImplDX12_ViewportData(UINT num_frames_in_flight)
|
||||
ImGui_ImplDX12_ViewportData(UINT num_backbuffer, UINT num_frames_in_flight)
|
||||
{
|
||||
CommandQueue = nullptr;
|
||||
CommandList = nullptr;
|
||||
RtvDescHeap = nullptr;
|
||||
SwapChain = nullptr;
|
||||
SwapChainWaitableObject = nullptr;
|
||||
NumBackBuffer = num_backbuffer;
|
||||
BackBuffer = new ImGui_ImplDX12_Backbuffer[num_backbuffer];
|
||||
NumFramesInFlight = num_frames_in_flight;
|
||||
FrameCtx = new ImGui_ImplDX12_FrameContext[NumFramesInFlight];
|
||||
FrameIndex = 0;
|
||||
FrameRenderBuffers = new ImGui_ImplDX12_RenderBuffers[NumFramesInFlight];
|
||||
|
||||
for (UINT i = 0; i < NumBackBuffer; ++i)
|
||||
BackBuffer[i].RenderTarget = nullptr;
|
||||
|
||||
for (UINT i = 0; i < NumFramesInFlight; ++i)
|
||||
{
|
||||
FrameCtx[i].FenceValue = 0;
|
||||
FrameCtx[i].CommandAllocator = nullptr;
|
||||
FrameCtx[i].RenderTarget = nullptr;
|
||||
|
||||
// Create buffers with a default size (they will later be grown as needed)
|
||||
FrameRenderBuffers[i].IndexBuffer = nullptr;
|
||||
|
|
@ -195,12 +207,16 @@ struct ImGui_ImplDX12_ViewportData
|
|||
IM_ASSERT(SwapChain == nullptr);
|
||||
IM_ASSERT(SwapChainWaitableObject == nullptr);
|
||||
|
||||
for (UINT i = 0; i < NumBackBuffer; ++i)
|
||||
IM_ASSERT(BackBuffer[i].RenderTarget == nullptr);
|
||||
|
||||
for (UINT i = 0; i < NumFramesInFlight; ++i)
|
||||
{
|
||||
IM_ASSERT(FrameCtx[i].CommandAllocator == nullptr && FrameCtx[i].RenderTarget == nullptr);
|
||||
IM_ASSERT(FrameCtx[i].CommandAllocator == nullptr);
|
||||
IM_ASSERT(FrameRenderBuffers[i].IndexBuffer == nullptr && FrameRenderBuffers[i].VertexBuffer == nullptr);
|
||||
}
|
||||
|
||||
delete[] BackBuffer; BackBuffer = nullptr;
|
||||
delete[] FrameCtx; FrameCtx = nullptr;
|
||||
delete[] FrameRenderBuffers; FrameRenderBuffers = nullptr;
|
||||
}
|
||||
|
|
@ -955,6 +971,7 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
|
|||
bd->pCommandQueue = init_info->CommandQueue;
|
||||
bd->RTVFormat = init_info->RTVFormat;
|
||||
bd->DSVFormat = init_info->DSVFormat;
|
||||
bd->numBackbuffer = init_info->NumBackBuffer >= 2 ? init_info->NumBackBuffer : 2;
|
||||
bd->numFramesInFlight = init_info->NumFramesInFlight;
|
||||
bd->pd3dSrvDescHeap = init_info->SrvDescriptorHeap;
|
||||
bd->tearingSupport = false;
|
||||
|
|
@ -971,7 +988,7 @@ bool ImGui_ImplDX12_Init(ImGui_ImplDX12_InitInfo* init_info)
|
|||
// Create a dummy ImGui_ImplDX12_ViewportData holder for the main viewport,
|
||||
// Since this is created and managed by the application, we will only use the ->Resources[] fields.
|
||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||
main_viewport->RendererUserData = IM_NEW(ImGui_ImplDX12_ViewportData)(bd->numFramesInFlight);
|
||||
main_viewport->RendererUserData = IM_NEW(ImGui_ImplDX12_ViewportData)(0, bd->numFramesInFlight);
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
if (init_info->SrvDescriptorAllocFn == nullptr)
|
||||
|
|
@ -1059,7 +1076,7 @@ void ImGui_ImplDX12_NewFrame()
|
|||
static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
|
||||
{
|
||||
ImGui_ImplDX12_Data* bd = ImGui_ImplDX12_GetBackendData();
|
||||
ImGui_ImplDX12_ViewportData* vd = IM_NEW(ImGui_ImplDX12_ViewportData)(bd->numFramesInFlight);
|
||||
ImGui_ImplDX12_ViewportData* vd = IM_NEW(ImGui_ImplDX12_ViewportData)(bd->numBackbuffer, bd->numFramesInFlight);
|
||||
viewport->RendererUserData = vd;
|
||||
|
||||
// PlatformHandleRaw should always be a HWND, whereas PlatformHandle might be a higher-level handle (e.g. GLFWWindow*, SDL's WindowID).
|
||||
|
|
@ -1088,7 +1105,7 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
|
|||
// FIXME-VIEWPORT: May want to copy/inherit swap chain settings from the user/application.
|
||||
DXGI_SWAP_CHAIN_DESC1 sd1;
|
||||
ZeroMemory(&sd1, sizeof(sd1));
|
||||
sd1.BufferCount = bd->numFramesInFlight;
|
||||
sd1.BufferCount = bd->numBackbuffer;
|
||||
sd1.Width = (UINT)viewport->Size.x;
|
||||
sd1.Height = (UINT)viewport->Size.y;
|
||||
sd1.Format = bd->RTVFormat;
|
||||
|
|
@ -1120,7 +1137,7 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
|
|||
{
|
||||
D3D12_DESCRIPTOR_HEAP_DESC desc = {};
|
||||
desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
desc.NumDescriptors = bd->numFramesInFlight;
|
||||
desc.NumDescriptors = bd->numBackbuffer;
|
||||
desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
desc.NodeMask = 1;
|
||||
|
||||
|
|
@ -1129,19 +1146,16 @@ static void ImGui_ImplDX12_CreateWindow(ImGuiViewport* viewport)
|
|||
|
||||
SIZE_T rtv_descriptor_size = bd->pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = vd->RtvDescHeap->GetCPUDescriptorHandleForHeapStart();
|
||||
for (UINT i = 0; i < bd->numFramesInFlight; i++)
|
||||
{
|
||||
vd->FrameCtx[i].RenderTargetCpuDescriptors = rtv_handle;
|
||||
rtv_handle.ptr += rtv_descriptor_size;
|
||||
}
|
||||
|
||||
ID3D12Resource* back_buffer;
|
||||
for (UINT i = 0; i < bd->numFramesInFlight; i++)
|
||||
for (UINT i = 0; i < bd->numBackbuffer; i++)
|
||||
{
|
||||
IM_ASSERT(vd->FrameCtx[i].RenderTarget == nullptr);
|
||||
vd->BackBuffer[i].RenderTargetCpuDescriptors = rtv_handle;
|
||||
rtv_handle.ptr += rtv_descriptor_size;
|
||||
|
||||
IM_ASSERT(vd->BackBuffer[i].RenderTarget == nullptr);
|
||||
vd->SwapChain->GetBuffer(i, IID_PPV_ARGS(&back_buffer));
|
||||
bd->pd3dDevice->CreateRenderTargetView(back_buffer, nullptr, vd->FrameCtx[i].RenderTargetCpuDescriptors);
|
||||
vd->FrameCtx[i].RenderTarget = back_buffer;
|
||||
bd->pd3dDevice->CreateRenderTargetView(back_buffer, nullptr, vd->BackBuffer[i].RenderTargetCpuDescriptors);
|
||||
vd->BackBuffer[i].RenderTarget = back_buffer;
|
||||
}
|
||||
|
||||
hr = vd->SwapChain->SetMaximumFrameLatency(bd->numFramesInFlight);
|
||||
|
|
@ -1197,9 +1211,11 @@ static void ImGui_ImplDX12_DestroyWindow(ImGuiViewport* viewport)
|
|||
SafeRelease(vd->SwapChain);
|
||||
SafeRelease(vd->RtvDescHeap);
|
||||
|
||||
for (UINT i = 0; i < bd->numBackbuffer; i++)
|
||||
SafeRelease(vd->BackBuffer[i].RenderTarget);
|
||||
|
||||
for (UINT i = 0; i < bd->numFramesInFlight; i++)
|
||||
{
|
||||
SafeRelease(vd->FrameCtx[i].RenderTarget);
|
||||
SafeRelease(vd->FrameCtx[i].CommandAllocator);
|
||||
ImGui_ImplDX12_DestroyRenderBuffers(&vd->FrameRenderBuffers[i]);
|
||||
}
|
||||
|
|
@ -1215,8 +1231,8 @@ static void ImGui_ImplDX12_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
|
|||
|
||||
ImGui_WaitForPendingOperations(vd);
|
||||
|
||||
for (UINT i = 0; i < bd->numFramesInFlight; i++)
|
||||
SafeRelease(vd->FrameCtx[i].RenderTarget);
|
||||
for (UINT i = 0; i < bd->numBackbuffer; i++)
|
||||
SafeRelease(vd->BackBuffer[i].RenderTarget);
|
||||
|
||||
if (vd->SwapChain)
|
||||
{
|
||||
|
|
@ -1224,11 +1240,11 @@ static void ImGui_ImplDX12_SetWindowSize(ImGuiViewport* viewport, ImVec2 size)
|
|||
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
||||
vd->SwapChain->GetDesc1(&desc);
|
||||
vd->SwapChain->ResizeBuffers(0, (UINT)size.x, (UINT)size.y, desc.Format, desc.Flags);
|
||||
for (UINT i = 0; i < bd->numFramesInFlight; i++)
|
||||
for (UINT i = 0; i < bd->numBackbuffer; i++)
|
||||
{
|
||||
vd->SwapChain->GetBuffer(i, IID_PPV_ARGS(&back_buffer));
|
||||
bd->pd3dDevice->CreateRenderTargetView(back_buffer, nullptr, vd->FrameCtx[i].RenderTargetCpuDescriptors);
|
||||
vd->FrameCtx[i].RenderTarget = back_buffer;
|
||||
bd->pd3dDevice->CreateRenderTargetView(back_buffer, nullptr, vd->BackBuffer[i].RenderTargetCpuDescriptors);
|
||||
vd->BackBuffer[i].RenderTarget = back_buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1245,7 +1261,7 @@ static void ImGui_ImplDX12_RenderWindow(ImGuiViewport* viewport, void*)
|
|||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = vd->FrameCtx[back_buffer_idx].RenderTarget;
|
||||
barrier.Transition.pResource = vd->BackBuffer[back_buffer_idx].RenderTarget;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
|
|
@ -1256,9 +1272,9 @@ static void ImGui_ImplDX12_RenderWindow(ImGuiViewport* viewport, void*)
|
|||
frame_context->CommandAllocator->Reset();
|
||||
cmd_list->Reset(frame_context->CommandAllocator, nullptr);
|
||||
cmd_list->ResourceBarrier(1, &barrier);
|
||||
cmd_list->OMSetRenderTargets(1, &vd->FrameCtx[back_buffer_idx].RenderTargetCpuDescriptors, FALSE, nullptr);
|
||||
cmd_list->OMSetRenderTargets(1, &vd->BackBuffer[back_buffer_idx].RenderTargetCpuDescriptors, FALSE, nullptr);
|
||||
if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
|
||||
cmd_list->ClearRenderTargetView(vd->FrameCtx[back_buffer_idx].RenderTargetCpuDescriptors, (const float*)&clear_color, 0, nullptr);
|
||||
cmd_list->ClearRenderTargetView(vd->BackBuffer[back_buffer_idx].RenderTargetCpuDescriptors, (const float*)&clear_color, 0, nullptr);
|
||||
cmd_list->SetDescriptorHeaps(1, &bd->pd3dSrvDescHeap);
|
||||
|
||||
ImGui_ImplDX12_RenderDrawData(viewport->DrawData, cmd_list);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ struct ImGui_ImplDX12_InitInfo
|
|||
{
|
||||
ID3D12Device* Device;
|
||||
ID3D12CommandQueue* CommandQueue; // Command queue used for queuing texture uploads.
|
||||
int NumBackBuffer;
|
||||
int NumFramesInFlight;
|
||||
DXGI_FORMAT RTVFormat; // RenderTarget format.
|
||||
DXGI_FORMAT DSVFormat; // DepthStencilView format.
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ int main(int, char**)
|
|||
ImGui_ImplDX12_InitInfo init_info = {};
|
||||
init_info.Device = g_pd3dDevice;
|
||||
init_info.CommandQueue = g_pd3dCommandQueue;
|
||||
init_info.NumBackBuffer = APP_NUM_BACK_BUFFERS;
|
||||
init_info.NumFramesInFlight = APP_NUM_FRAMES_IN_FLIGHT;
|
||||
init_info.RTVFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
init_info.DSVFormat = DXGI_FORMAT_UNKNOWN;
|
||||
|
|
@ -460,7 +461,7 @@ bool CreateDeviceD3D(HWND hWnd)
|
|||
|
||||
swapChain1->Release();
|
||||
dxgiFactory->Release();
|
||||
g_pSwapChain->SetMaximumFrameLatency(APP_NUM_BACK_BUFFERS);
|
||||
g_pSwapChain->SetMaximumFrameLatency(APP_NUM_FRAMES_IN_FLIGHT);
|
||||
g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue