From d06f31e953d70ba98a1ec8defa4128e2e951e4da Mon Sep 17 00:00:00 2001 From: Michael Robles <40410952+dashdogy@users.noreply.github.com> Date: Wed, 21 Oct 2026 21:47:34 +1100 Subject: [PATCH] Fix DX12 menu crash on swapchains with more than 8 buffers Size the menu's per-buffer arrays and the blur's descriptor slots for 16 back buffers, the DXGI maximum, refuse larger chains in CreateRenderTargetDx12 and skip frames with an out-of-range back buffer index. --- OptiScaler/menu/menu_overlay_dx.cpp | 19 ++++++++++++++++--- OptiScaler/shaders/menu_blur/MenuBlur_Dx12.h | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/OptiScaler/menu/menu_overlay_dx.cpp b/OptiScaler/menu/menu_overlay_dx.cpp index 27dbb92b..5db71843 100644 --- a/OptiScaler/menu/menu_overlay_dx.cpp +++ b/OptiScaler/menu/menu_overlay_dx.cpp @@ -15,7 +15,8 @@ #include // menu -static int const NUM_BACK_BUFFERS = 8; +// Sized for the largest swapchain DXGI allows, the menu can draw on chains created by other layers +static int const NUM_BACK_BUFFERS = 16; // DXGI_MAX_SWAP_CHAIN_BUFFERS static int const SRV_HEAP_SIZE = 64; static bool _dx11Device = false; static bool _dx12Device = false; @@ -101,6 +102,12 @@ static void CreateRenderTargetDx12(ID3D12Device* device, IDXGISwapChain* pSwapCh return; } + if (sd.BufferCount > NUM_BACK_BUFFERS) + { + LOG_ERROR("Swapchain has {} buffers, menu supports {}", sd.BufferCount, NUM_BACK_BUFFERS); + return; + } + for (UINT i = 0; i < sd.BufferCount; ++i) { ID3D12Resource* pBackBuffer = nullptr; @@ -500,10 +507,16 @@ static void RenderImGui_DX12(IDXGISwapChain* pSwapChainPlain) { _showRenderImGuiDebugOnce = true; - ImGui_ImplDX12_NewFrame(); - UINT backBufferIdx = pSwapChain->GetCurrentBackBufferIndex(); + if (backBufferIdx >= NUM_BACK_BUFFERS || !g_mainRenderTargetResource[backBufferIdx]) + { + pSwapChain->Release(); + return; + } + + ImGui_ImplDX12_NewFrame(); + // Blur textures are only created once the menu is opened, menu decides if they are used bool blurReady = false; if (g_menuBlur || MenuOverlayBase::IsVisible()) diff --git a/OptiScaler/shaders/menu_blur/MenuBlur_Dx12.h b/OptiScaler/shaders/menu_blur/MenuBlur_Dx12.h index 512b0db0..d70f957e 100644 --- a/OptiScaler/shaders/menu_blur/MenuBlur_Dx12.h +++ b/OptiScaler/shaders/menu_blur/MenuBlur_Dx12.h @@ -10,7 +10,7 @@ class MenuBlur_Dx12 : public Shader_Dx12, public MenuBlur_Common { private: - static constexpr UINT MaxBackBuffers = 8; + static constexpr UINT MaxBackBuffers = 16; // DXGI_MAX_SWAP_CHAIN_BUFFERS // Descriptor layout, every pass uses a SRV + UAV pair // [2 * i]: back buffer i SRV, [2 * i + 1]: blur A UAV