Skip to content

Commit dd89bb1

Browse files
committed
Backends: DirectX11: configure swap chain creation for secondary viewports via undocumented ImGui_ImplDX11_SetSwapChainDescs(). (ocornut#5437, ocornut#7607, ocornut#7286, ocornut#2970)
1 parent 3064e6d commit dd89bb1

File tree

1 file changed

+40
-17
lines changed

1 file changed

+40
-17
lines changed

backends/imgui_impl_dx11.cpp

+40-17
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
// CHANGELOG
1919
// (minor and older changes stripped away, please see git history for details)
2020
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
21+
// 2025-02-24: [Docking] Added undocumented ImGui_ImplDX11_SetSwapChainDescs() to configure swap chain creation for secondary viewports.
2122
// 2025-01-06: DirectX11: Expose VertexConstantBuffer in ImGui_ImplDX11_RenderState. Reset projection matrix in ImDrawCallback_ResetRenderState handler.
2223
// 2024-10-07: DirectX11: Changed default texture sampler to Clamp instead of Repeat/Wrap.
2324
// 2024-10-07: DirectX11: Expose selected render state in ImGui_ImplDX11_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks.
@@ -70,6 +71,7 @@ struct ImGui_ImplDX11_Data
7071
ID3D11DepthStencilState* pDepthStencilState;
7172
int VertexBufferSize;
7273
int IndexBufferSize;
74+
ImVector<DXGI_SWAP_CHAIN_DESC> SwapChainDescsForViewports;
7375

7476
ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; }
7577
};
@@ -652,6 +654,16 @@ struct ImGui_ImplDX11_ViewportData
652654
~ImGui_ImplDX11_ViewportData() { IM_ASSERT(SwapChain == nullptr && RTView == nullptr); }
653655
};
654656

657+
// Multi-Viewports: configure templates used when creating swapchains for secondary viewports. Will try them in order.
658+
// This is intentionally not declared in the .h file yet, so you will need to copy this declaration:
659+
void ImGui_ImplDX11_SetSwapChainDescs(const DXGI_SWAP_CHAIN_DESC* desc_templates, int desc_templates_count);
660+
void ImGui_ImplDX11_SetSwapChainDescs(const DXGI_SWAP_CHAIN_DESC* desc_templates, int desc_templates_count)
661+
{
662+
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
663+
bd->SwapChainDescsForViewports.resize(desc_templates_count);
664+
memcpy(bd->SwapChainDescsForViewports.Data, desc_templates, sizeof(DXGI_SWAP_CHAIN_DESC));
665+
}
666+
655667
static void ImGui_ImplDX11_CreateWindow(ImGuiViewport* viewport)
656668
{
657669
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();
@@ -662,27 +674,25 @@ static void ImGui_ImplDX11_CreateWindow(ImGuiViewport* viewport)
662674
// Some backends will leave PlatformHandleRaw == 0, in which case we assume PlatformHandle will contain the HWND.
663675
HWND hwnd = viewport->PlatformHandleRaw ? (HWND)viewport->PlatformHandleRaw : (HWND)viewport->PlatformHandle;
664676
IM_ASSERT(hwnd != 0);
677+
IM_ASSERT(vd->SwapChain == nullptr && vd->RTView == nullptr);
665678

666679
// Create swap chain
667-
DXGI_SWAP_CHAIN_DESC sd;
668-
ZeroMemory(&sd, sizeof(sd));
669-
sd.BufferDesc.Width = (UINT)viewport->Size.x;
670-
sd.BufferDesc.Height = (UINT)viewport->Size.y;
671-
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
672-
sd.SampleDesc.Count = 1;
673-
sd.SampleDesc.Quality = 0;
674-
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
675-
sd.BufferCount = 1;
676-
sd.OutputWindow = hwnd;
677-
sd.Windowed = TRUE;
678-
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
679-
sd.Flags = 0;
680-
681-
IM_ASSERT(vd->SwapChain == nullptr && vd->RTView == nullptr);
682-
bd->pFactory->CreateSwapChain(bd->pd3dDevice, &sd, &vd->SwapChain);
680+
HRESULT hr = DXGI_ERROR_UNSUPPORTED;
681+
for (const DXGI_SWAP_CHAIN_DESC& sd_template : bd->SwapChainDescsForViewports)
682+
{
683+
IM_ASSERT(sd_template.BufferDesc.Width == 0 && sd_template.BufferDesc.Height == 0 && sd_template.OutputWindow == nullptr);
684+
DXGI_SWAP_CHAIN_DESC sd = sd_template;
685+
sd.BufferDesc.Width = (UINT)viewport->Size.x;
686+
sd.BufferDesc.Height = (UINT)viewport->Size.y;
687+
sd.OutputWindow = hwnd;
688+
hr = bd->pFactory->CreateSwapChain(bd->pd3dDevice, &sd, &vd->SwapChain);
689+
if (SUCCEEDED(hr))
690+
break;
691+
}
692+
IM_ASSERT(SUCCEEDED(hr));
683693

684694
// Create the render target
685-
if (vd->SwapChain)
695+
if (vd->SwapChain != nullptr)
686696
{
687697
ID3D11Texture2D* pBackBuffer;
688698
vd->SwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
@@ -752,6 +762,19 @@ static void ImGui_ImplDX11_InitMultiViewportSupport()
752762
platform_io.Renderer_SetWindowSize = ImGui_ImplDX11_SetWindowSize;
753763
platform_io.Renderer_RenderWindow = ImGui_ImplDX11_RenderWindow;
754764
platform_io.Renderer_SwapBuffers = ImGui_ImplDX11_SwapBuffers;
765+
766+
// Default swapchain format
767+
DXGI_SWAP_CHAIN_DESC sd;
768+
ZeroMemory(&sd, sizeof(sd));
769+
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
770+
sd.SampleDesc.Count = 1;
771+
sd.SampleDesc.Quality = 0;
772+
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
773+
sd.BufferCount = 1;
774+
sd.Windowed = TRUE;
775+
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
776+
sd.Flags = 0;
777+
ImGui_ImplDX11_SetSwapChainDescs(&sd, 1);
755778
}
756779

757780
static void ImGui_ImplDX11_ShutdownMultiViewportSupport()

0 commit comments

Comments
 (0)