From 22fecb41fc85f3c2ef6a3f1e1d422dd6b6e9a76b Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 29 Oct 2022 09:49:03 +0200 Subject: [PATCH 1/3] VideoBackends:D3D12: Don't query GPU descriptor handle for non-shader visible heap Fixes the following error in the D3D12 debug layer: D3D12 ERROR: ID3D12DescriptorHeap::GetGPUDescriptorHandleForHeapStart: GetGPUDescriptorHandleForHeapStart is invalid to call on a descriptor heap that does not have DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE set. If the heap is not supposed to be shader visible, then GetCPUDescriptorHandleForHeapStart would be the appropriate method to call. That call is valid both for shader visible and non shader visible descriptor heaps. [ STATE_GETTING ERROR #1315: DESCRIPTOR_HEAP_NOT_SHADER_VISIBLE] --- Source/Core/VideoBackends/D3D12/DescriptorHeapManager.cpp | 3 +-- Source/Core/VideoBackends/D3D12/DescriptorHeapManager.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.cpp b/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.cpp index 97d0c8ce2e..9827057626 100644 --- a/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.cpp +++ b/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.cpp @@ -25,7 +25,6 @@ bool DescriptorHeapManager::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_T return false; m_heap_base_cpu = m_descriptor_heap->GetCPUDescriptorHandleForHeapStart(); - m_heap_base_gpu = m_descriptor_heap->GetGPUDescriptorHandleForHeapStart(); m_num_descriptors = num_descriptors; m_descriptor_increment_size = device->GetDescriptorHandleIncrementSize(type); @@ -60,7 +59,7 @@ bool DescriptorHeapManager::Allocate(DescriptorHandle* handle) handle->index = index; handle->cpu_handle.ptr = m_heap_base_cpu.ptr + index * m_descriptor_increment_size; - handle->gpu_handle.ptr = m_heap_base_gpu.ptr + index * m_descriptor_increment_size; + handle->gpu_handle.ptr = 0; return true; } diff --git a/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.h b/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.h index 7ff42c8e5b..c7c00d518f 100644 --- a/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.h +++ b/Source/Core/VideoBackends/D3D12/DescriptorHeapManager.h @@ -41,7 +41,6 @@ private: u32 m_descriptor_increment_size = 0; D3D12_CPU_DESCRIPTOR_HANDLE m_heap_base_cpu = {}; - D3D12_GPU_DESCRIPTOR_HANDLE m_heap_base_gpu = {}; static constexpr u32 BITSET_SIZE = 1024; using BitSetType = std::bitset; From a6aa6512917d5ff33c8c864445e55d47a9176ead Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 29 Oct 2022 09:49:52 +0200 Subject: [PATCH 2/3] VideoBackends:D3D12: Use COMMON as initial state for default heap buffer Fixes the following error in the D3D12 debug layer: D3D12 WARNING: ID3D12Device::CreateCommittedResource: Ignoring InitialState D3D12_RESOURCE_STATE_UNORDERED_ACCESS. Buffers are effectively created in state D3D12_RESOURCE_STATE_COMMON. [ STATE_CREATION WARNING #1328: CREATERESOURCE_STATE_IGNORED] --- Source/Core/VideoBackends/D3D12/D3D12BoundingBox.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D12/D3D12BoundingBox.cpp b/Source/Core/VideoBackends/D3D12/D3D12BoundingBox.cpp index 75b3f6064a..4eec9f2e22 100644 --- a/Source/Core/VideoBackends/D3D12/D3D12BoundingBox.cpp +++ b/Source/Core/VideoBackends/D3D12/D3D12BoundingBox.cpp @@ -101,8 +101,8 @@ bool D3D12BoundingBox::CreateBuffers() D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS}; HRESULT hr = g_dx_context->GetDevice()->CreateCommittedResource( - &gpu_heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, - D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&m_gpu_buffer)); + &gpu_heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_COMMON, + nullptr, IID_PPV_ARGS(&m_gpu_buffer)); ASSERT_MSG(VIDEO, SUCCEEDED(hr), "Creating bounding box GPU buffer failed: {}", DX12HRWrap(hr)); if (FAILED(hr) || !g_dx_context->GetDescriptorHeapManager().Allocate(&m_gpu_descriptor)) return false; From a07ee729e50905dc2a1926ad81a95f372ab2d52a Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Sat, 29 Oct 2022 10:05:40 +0200 Subject: [PATCH 3/3] 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); } }