From 5777fe1f6675abeef33a3538423ae55ed517ea47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Thu, 17 Sep 2026 07:14:56 -0700 Subject: [PATCH] D3D11/12/WGPU: Retried refused swap chain resize. D3D12/MTL/VK/WGPU: Fatal on failed pipeline creation. (#3985) --- src/renderer_d3d11.cpp | 25 +++++++++++++++++++++++-- src/renderer_d3d11.h | 4 ++++ src/renderer_d3d12.cpp | 38 ++++++++++++++++++++++++++++---------- src/renderer_d3d12.h | 4 ++++ src/renderer_mtl.cpp | 4 ++++ src/renderer_vk.cpp | 26 +++++++++++++++++++++----- src/renderer_webgpu.cpp | 26 +++++++++++++++++++++++--- src/renderer_webgpu.h | 4 ++++ 8 files changed, 111 insertions(+), 20 deletions(-) diff --git a/src/renderer_d3d11.cpp b/src/renderer_d3d11.cpp index 3e8aa8b1b..cbcb76237 100644 --- a/src/renderer_d3d11.cpp +++ b/src/renderer_d3d11.cpp @@ -5700,6 +5700,8 @@ namespace bgfx { namespace d3d11 return; } + const SwapChain prev = m_desc; + m_desc = _desc; m_nwh = _desc.nwh; @@ -5713,11 +5715,20 @@ namespace bgfx { namespace d3d11 if (FAILED(hr) ) { BX_TRACE("Failed to resize swap chain, hr 0x%08x.", hr); - DX_RELEASE(m_swapChain, 0); - m_num = 0; + + m_descPending = _desc; + m_needToRecreateSwapChain = true; + + m_desc = prev; + m_desc.depth = _desc.depth; + + createSwapChainViews(); + return; } + m_needToRecreateSwapChain = false; + createSwapChainViews(); } @@ -6772,6 +6783,16 @@ namespace bgfx { namespace d3d11 renderDocTriggerCapture(); } + for (uint32_t ii = 1, num = m_numWindows; ii < num; ++ii) + { + FrameBufferD3D11& frameBuffer = m_frameBuffers[m_windows[ii].idx]; + + if (frameBuffer.m_needToRecreateSwapChain) + { + frameBuffer.update(frameBuffer.m_descPending); + } + } + BGFX_D3D11_PROFILER_BEGIN_LITERAL("rendererSubmit", kColorView); ID3D11DeviceContext* deviceCtx = m_deviceCtx; diff --git a/src/renderer_d3d11.h b/src/renderer_d3d11.h index e2e59c6f0..609057cca 100644 --- a/src/renderer_d3d11.h +++ b/src/renderer_d3d11.h @@ -418,11 +418,13 @@ namespace bgfx { namespace d3d11 , m_numTh(0) , m_numUav(0) , m_needPresent(false) + , m_needToRecreateSwapChain(false) , m_needsQuadClear(false) , m_needsQuadClearZero(false) , m_intColor(false) { bx::memSet(&m_desc, 0, sizeof(m_desc) ); + bx::memSet(&m_descPending, 0, sizeof(m_descPending) ); bx::memSet(m_rtv, 0, sizeof(m_rtv) ); bx::memSet(m_uav, 0, sizeof(m_uav) ); bx::memSet(m_srv, 0, sizeof(m_srv) ); @@ -454,6 +456,7 @@ namespace bgfx { namespace d3d11 Dxgi::SwapChainI* m_swapChain; ID3D11Texture2D* m_msaaRt; SwapChain m_desc; + SwapChain m_descPending; void* m_nwh; uint32_t m_width; uint32_t m_height; @@ -464,6 +467,7 @@ namespace bgfx { namespace d3d11 uint8_t m_numTh; uint8_t m_numUav; bool m_needPresent; + bool m_needToRecreateSwapChain; bool m_needsQuadClear; bool m_needsQuadClearZero; bool m_intColor; diff --git a/src/renderer_d3d12.cpp b/src/renderer_d3d12.cpp index eb9143f28..b1d12e5f7 100644 --- a/src/renderer_d3d12.cpp +++ b/src/renderer_d3d12.cpp @@ -3784,6 +3784,8 @@ namespace bgfx { namespace d3d12 ) ); } + BGFX_FATAL(NULL != pso, Fatal::InvalidShader, "Failed to create compute PSO!"); + m_pipelineStateCache.add(hash, pso); ID3DBlob* blob; @@ -7734,6 +7736,8 @@ namespace bgfx { namespace d3d12 return; } + const SwapChain prev = m_desc; + m_desc = _desc; m_nwh = _desc.nwh; @@ -7760,20 +7764,22 @@ namespace bgfx { namespace d3d12 { BX_TRACE("Failed to resize swap chain, hr 0x%08x.", hr); -#if !BX_PLATFORM_LINUX - if (NULL != m_frameLatencyWaitableObject) - { - CloseHandle( (HANDLE)m_frameLatencyWaitableObject); - m_frameLatencyWaitableObject = NULL; - } -#endif // !BX_PLATFORM_LINUX + m_descPending = _desc; + m_needToRecreateSwapChain = true; + + m_desc = prev; + m_desc.depth = _desc.depth; + + m_state = D3D12_RESOURCE_STATE_PRESENT; + m_swapChainFormat = getSwapChainDesc().format; + + createSwapChainViews(); - DX_RELEASE(m_swapChain, 0); - m_swapChainFormat = DXGI_FORMAT_UNKNOWN; - m_num = 0; return; } + m_needToRecreateSwapChain = false; + m_state = D3D12_RESOURCE_STATE_PRESENT; m_swapChainFormat = scd.format; @@ -9276,6 +9282,18 @@ namespace bgfx { namespace d3d12 renderDocTriggerCapture(); } +#if BX_PLATFORM_WINDOWS + for (uint32_t ii = 1, num = m_numWindows; ii < num; ++ii) + { + FrameBufferD3D12& frameBuffer = m_frameBuffers[m_windows[ii].idx]; + + if (frameBuffer.m_needToRecreateSwapChain) + { + frameBuffer.update(frameBuffer.m_descPending); + } + } +#endif // BX_PLATFORM_WINDOWS + BGFX_D3D12_PROFILER_BEGIN_LITERAL("rendererSubmit", kColorFrame); int64_t timeBegin = bx::getHPCounter(); diff --git a/src/renderer_d3d12.h b/src/renderer_d3d12.h index 47922de18..6bda20b90 100644 --- a/src/renderer_d3d12.h +++ b/src/renderer_d3d12.h @@ -516,10 +516,12 @@ namespace bgfx { namespace d3d12 , m_numTh(0) , m_state(D3D12_RESOURCE_STATE_PRESENT) , m_needPresent(false) + , m_needToRecreateSwapChain(false) , m_frameLatencyWaitableObject(NULL) { m_depth.idx = bgfx::kInvalidHandle; bx::memSet(&m_desc, 0, sizeof(m_desc) ); + bx::memSet(&m_descPending, 0, sizeof(m_descPending) ); bx::memSet(m_backBufferColor, 0, sizeof(m_backBufferColor) ); } @@ -548,6 +550,7 @@ namespace bgfx { namespace d3d12 Dxgi::SwapChainI* m_swapChain; DXGI_FORMAT m_swapChainFormat; SwapChain m_desc; + SwapChain m_descPending; ID3D12Resource* m_backBufferColor[BGFX_CONFIG_MAX_BACK_BUFFERS]; ID3D12Resource* m_msaaRt; ID3D12Resource* m_backBufferDepthStencil; @@ -561,6 +564,7 @@ namespace bgfx { namespace d3d12 Attachment m_attachment[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS]; D3D12_RESOURCE_STATES m_state; bool m_needPresent; + bool m_needToRecreateSwapChain; void* m_frameLatencyWaitableObject; }; diff --git a/src/renderer_mtl.cpp b/src/renderer_mtl.cpp index 19b0d00b6..3f7cef368 100644 --- a/src/renderer_mtl.cpp +++ b/src/renderer_mtl.cpp @@ -3323,6 +3323,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames MTL::RenderPipelineReflection* reflection = NULL; pso->m_rps = newRenderPipelineStateWithDescriptor(m_device, pd, MTL::PipelineOptionBufferTypeInfo, &reflection); + BGFX_FATAL(NULL != pso->m_rps, Fatal::InvalidShader, "Failed to create graphics PSO!"); + if (NULL != reflection) { if (m_usesMTLBindings) @@ -3381,6 +3383,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames , &reflection ); + BGFX_FATAL(NULL != pso->m_cps, Fatal::InvalidShader, "Failed to create compute PSO!"); + if (m_usesMTLBindings) { processArguments(pso, reflection->bindings(), NULL); diff --git a/src/renderer_vk.cpp b/src/renderer_vk.cpp index f882cdb18..853e65055 100644 --- a/src/renderer_vk.cpp +++ b/src/renderer_vk.cpp @@ -4141,7 +4141,14 @@ VK_IMPORT_DEVICE cpci.basePipelineHandle = VK_NULL_HANDLE; cpci.basePipelineIndex = 0; - VK_CHECK(vkCreateComputePipelines(m_device, m_pipelineCache, 1, &cpci, m_allocatorCb, &pipeline) ); + const VkResult result = vkCreateComputePipelines(m_device, m_pipelineCache, 1, &cpci, m_allocatorCb, &pipeline); + + BGFX_FATAL(VK_SUCCESS == result && VK_NULL_HANDLE != pipeline + , Fatal::InvalidShader + , "Failed to create compute PSO! vkCreateComputePipelines failed %d: %s." + , result + , getName(result) + ); m_pipelineStateCache.add(hash, pipeline); @@ -4380,14 +4387,22 @@ VK_IMPORT_DEVICE VkPipelineCache cache; VK_CHECK(vkCreatePipelineCache(m_device, &pcci, m_allocatorCb, &cache) ); - VK_CHECK(vkCreateGraphicsPipelines( + const VkResult result = vkCreateGraphicsPipelines( m_device , cache , 1 , &graphicsPipeline , m_allocatorCb , &pipeline - ) ); + ); + + BGFX_FATAL(VK_SUCCESS == result && VK_NULL_HANDLE != pipeline + , Fatal::InvalidShader + , "Failed to create graphics PSO! vkCreateGraphicsPipelines failed %d: %s." + , result + , getName(result) + ); + m_pipelineStateCache.add(hash, pipeline); size_t dataSize; @@ -6900,7 +6915,8 @@ VK_DESTROY ici.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; ici.pNext = NULL; ici.flags = 0 - | (VK_IMAGE_VIEW_TYPE_CUBE == m_type + | (VK_IMAGE_VIEW_TYPE_CUBE == m_type + || VK_IMAGE_VIEW_TYPE_CUBE_ARRAY == m_type ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0 ) @@ -7999,7 +8015,7 @@ VK_DESTROY if (VK_IMAGE_VIEW_TYPE_CUBE == _type || VK_IMAGE_VIEW_TYPE_CUBE_ARRAY == _type) { - BX_ASSERT(_numLayers % 6 == 0, ""); + BX_ASSERT(0 < _numLayers, ""); BX_ASSERT(false || VK_IMAGE_VIEW_TYPE_3D != m_type , "3D image can't be aliased as a cube texture" diff --git a/src/renderer_webgpu.cpp b/src/renderer_webgpu.cpp index 900defdba..4fb260c70 100644 --- a/src/renderer_webgpu.cpp +++ b/src/renderer_webgpu.cpp @@ -3125,11 +3125,15 @@ WGPU_IMPORT }, }; + const WGPUComputePipeline pipeline = wgpuDeviceCreateComputePipeline(m_device, &computePipelineDesc); + + BGFX_FATAL(NULL != pipeline, Fatal::InvalidShader, "Failed to create compute PSO!"); + computePipeline = m_computePipelineCache.add( hash , { .bindGroupLayout = bindGroupLayout, - .pipeline = wgpuDeviceCreateComputePipeline(m_device, &computePipelineDesc), + .pipeline = pipeline, } , 0 ); @@ -3508,11 +3512,15 @@ WGPU_IMPORT .fragment = hasFragmentShader ? &fragmentState : NULL, }; + const WGPURenderPipeline pipeline = wgpuDeviceCreateRenderPipeline(m_device, &renderPipelineDesc); + + BGFX_FATAL(NULL != pipeline, Fatal::InvalidShader, "Failed to create graphics PSO!"); + renderPipeline = m_renderPipelineCache.add( hash , { .bindGroupLayout = bindGroupLayout, - .pipeline = wgpuDeviceCreateRenderPipeline(m_device, &renderPipelineDesc), + .pipeline = pipeline, } , 0 ); @@ -5460,7 +5468,9 @@ WGPU_IMPORT wgpuRelease(m_textureView); wgpuRelease(m_msaaTextureView); wgpuRelease(m_depthStencilView); - configure(_desc); + + m_descPending = _desc; + m_needToRecreateSwapChain = !configure(_desc); } #if BX_PLATFORM_OSX || BX_PLATFORM_IOS || BX_PLATFORM_VISIONOS @@ -6801,6 +6811,16 @@ WGPU_IMPORT renderDocTriggerCapture(); } + for (uint32_t ii = 1, num = m_numWindows; ii < num; ++ii) + { + FrameBufferWGPU& frameBuffer = getFrameBuffer(m_windows[ii]); + + if (frameBuffer.m_swapChain.m_needToRecreateSwapChain) + { + frameBuffer.update(frameBuffer.m_swapChain.m_descPending); + } + } + BGFX_WGPU_PROFILER_BEGIN_LITERAL("rendererSubmit", kColorFrame); const int64_t timeBegin = bx::getHPCounter(); diff --git a/src/renderer_webgpu.h b/src/renderer_webgpu.h index bf370afa1..feb8d83a1 100644 --- a/src/renderer_webgpu.h +++ b/src/renderer_webgpu.h @@ -681,7 +681,9 @@ namespace wgpu { , m_viewFormat(WGPUTextureFormat_Undefined) , m_formatDepthStencil(uint8_t(TextureFormat::Count) ) , m_readable(false) + , m_needToRecreateSwapChain(false) { + bx::memSet(&m_descPending, 0, sizeof(m_descPending) ); } bool create(void* _nwh, const SwapChain& _desc); @@ -696,6 +698,7 @@ namespace wgpu { void* m_nwh; SwapChain m_desc; + SwapChain m_descPending; WGPUSurfaceConfiguration m_surfaceConfig; WGPUSurface m_surface; @@ -708,6 +711,7 @@ namespace wgpu { uint8_t m_formatDepthStencil; bool m_readable; + bool m_needToRecreateSwapChain; }; struct FrameBufferWGPU