From a07ee729e50905dc2a1926ad81a95f372ab2d52a Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 29 Oct 2022 10:05:40 +0200 Subject: [PATCH] VideoBackends:D3D12: Defer binding framebuffer in SetAndDiscardFramebuffer BindFramebuffer depends on the pipeline which might not be set yet. That's why the framebuffer dirty flag exists in the first place. I assume BindFramebuffer was called directly here, in order to handle the texture state transitions necessary for DiscardResource. The state is tracked anyway, so we can just issue those transitions there too and defer binding the actual framebuffer. Fixes an issue in Zelda Twilight Princess with EFB depth peeks. Dolphin would bind a frame buffer which doesn't have an integer format descriptor for the color target before binding the new pipeline. So it would accidentally use the 0 descriptor. Debug layer error: D3D12 ERROR: ID3D12CommandList::OMSetRenderTargets: Specified CPU descriptor handle ptr=0x0000000000000000 does not refer to a location in a descriptor heap. pRenderTargetDescriptors[0] is the issue. [ EXECUTION ERROR #646: INVALID_DESCRIPTOR_HANDLE] --- Source/Core/VideoBackends/D3D12/D3D12Renderer.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Core/VideoBackends/D3D12/D3D12Renderer.cpp b/Source/Core/VideoBackends/D3D12/D3D12Renderer.cpp index fc76f8e6f2..f4ef717c07 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12Renderer.cpp +++ b/Source/Core/VideoBackends/D3D12/D3D12Renderer.cpp @@ -236,18 +236,20 @@ void Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer) void Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer) { - BindFramebuffer(static_cast(framebuffer)); + SetFramebuffer(framebuffer); static const D3D12_DISCARD_REGION dr = {0, nullptr, 0, 1}; if (framebuffer->HasColorBuffer()) { - g_dx_context->GetCommandList()->DiscardResource( - static_cast(framebuffer->GetColorAttachment())->GetResource(), &dr); + DXTexture* color_attachment = static_cast(framebuffer->GetColorAttachment()); + color_attachment->TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET); + g_dx_context->GetCommandList()->DiscardResource(color_attachment->GetResource(), &dr); } if (framebuffer->HasDepthBuffer()) { - g_dx_context->GetCommandList()->DiscardResource( - static_cast(framebuffer->GetDepthAttachment())->GetResource(), &dr); + DXTexture* depth_attachment = static_cast(framebuffer->GetDepthAttachment()); + depth_attachment->TransitionToState(D3D12_RESOURCE_STATE_DEPTH_WRITE); + g_dx_context->GetCommandList()->DiscardResource(depth_attachment->GetResource(), &dr); } }