From 58cc331e2797a96f2e5f7b2a2825794fe8343d39 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 23 Feb 2024 13:09:34 +0000 Subject: [PATCH] Use a dedicated transfer queue for D3D12 GPU readbacks * This prevents a potential deadlock/failed readback situation if the queue we're submitting on at the time memory needs to be read is currently blocked by a pending wait and can't execute more code. --- .../driver/d3d12/d3d12_command_queue_wrap.cpp | 45 ++++++------------- renderdoc/driver/d3d12/d3d12_device.cpp | 35 +++++++++------ renderdoc/driver/d3d12/d3d12_device.h | 8 ++-- 3 files changed, 39 insertions(+), 49 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp index fa0fc7e56..6e5dfe548 100644 --- a/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_command_queue_wrap.cpp @@ -908,45 +908,26 @@ void WrappedID3D12CommandQueue::ExecuteCommandListsInternal(UINT NumCommandLists { QueueReadbackData &queueReadback = m_pDevice->GetQueueReadbackData(); - D3D12_COMMAND_LIST_TYPE type = GetDesc().Type; + D3D12_HEAP_PROPERTIES heapProps; + res->GetHeapProperties(&heapProps, NULL); - if(type >= ARRAY_COUNT(queueReadback.lists)) + if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD || + heapProps.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE) { - RDCERR("Unexpected invalid queue type %s", ToStr(type).c_str()); - } - else - { - ID3D12GraphicsCommandList *list = queueReadback.lists[type]; - ID3D12CommandAllocator *alloc = queueReadback.allocs[type]; - RDCLOG("Doing GPU readback of mapped memory"); - D3D12_HEAP_PROPERTIES heapProps; - res->GetHeapProperties(&heapProps, NULL); + queueReadback.lock.Lock(); - if(heapProps.Type == D3D12_HEAP_TYPE_UPLOAD || - heapProps.CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE) - { - if(!list) - { - RDCERR("No readback list prepared for queue type %s", ToStr(type).c_str()); - } - else - { - queueReadback.lock.Lock(); + queueReadback.Resize(size); - queueReadback.Resize(size); + queueReadback.list->Reset(queueReadback.alloc, NULL); + queueReadback.list->CopyBufferRegion(queueReadback.readbackBuf, 0, res, 0, size); + queueReadback.list->Close(); + ID3D12CommandList *listptr = Unwrap(queueReadback.list); + queueReadback.unwrappedQueue->ExecuteCommandLists(1, &listptr); + m_pDevice->GPUSync(queueReadback.unwrappedQueue, Unwrap(queueReadback.fence)); - list->Reset(alloc, NULL); - list->CopyBufferRegion(queueReadback.readbackBuf, 0, res, 0, size); - list->Close(); - ID3D12CommandList *listptr = Unwrap(list); - m_pReal->ExecuteCommandLists(1, &listptr); - m_pDevice->GPUSync(this); - - data = queueReadback.readbackMapped; - } - } + data = queueReadback.readbackMapped; } if(ref) diff --git a/renderdoc/driver/d3d12/d3d12_device.cpp b/renderdoc/driver/d3d12/d3d12_device.cpp index 470d4f6b5..47b73c938 100644 --- a/renderdoc/driver/d3d12/d3d12_device.cpp +++ b/renderdoc/driver/d3d12/d3d12_device.cpp @@ -3825,18 +3825,26 @@ void WrappedID3D12Device::CreateInternalResources() m_QueueReadbackData.Resize(4 * 1024 * 1024); InternalRef(); - for(D3D12_COMMAND_LIST_TYPE type : - {D3D12_COMMAND_LIST_TYPE_DIRECT, D3D12_COMMAND_LIST_TYPE_COMPUTE, - D3D12_COMMAND_LIST_TYPE_COPY}) { - CreateCommandAllocator(type, __uuidof(ID3D12CommandAllocator), - (void **)&m_QueueReadbackData.allocs[type]); + D3D12_COMMAND_QUEUE_DESC desc = {}; + desc.Type = D3D12_COMMAND_LIST_TYPE_COPY; + // make this queue as unwrapped so that it doesn't get included in captures + GetReal()->CreateCommandQueue(&desc, __uuidof(ID3D12CommandQueue), + (void **)&m_QueueReadbackData.unwrappedQueue); InternalRef(); - CreateCommandList(0, type, m_QueueReadbackData.allocs[type], NULL, - __uuidof(ID3D12GraphicsCommandList), - (void **)&m_QueueReadbackData.lists[type]); + m_QueueReadbackData.unwrappedQueue->SetName(L"m_QueueReadbackData.queue"); + CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, __uuidof(ID3D12CommandAllocator), + (void **)&m_QueueReadbackData.alloc); + m_QueueReadbackData.alloc->SetName(L"m_QueueReadbackData.alloc"); + InternalRef(); + CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, m_QueueReadbackData.alloc, NULL, + __uuidof(ID3D12GraphicsCommandList), (void **)&m_QueueReadbackData.list); + InternalRef(); + m_QueueReadbackData.list->Close(); + CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), + (void **)&m_QueueReadbackData.fence); + m_QueueReadbackData.fence->SetName(L"m_QueueReadbackData.fence"); InternalRef(); - m_QueueReadbackData.lists[type]->Close(); } } @@ -3844,6 +3852,7 @@ void WrappedID3D12Device::CreateInternalResources() (void **)&m_Alloc); InternalRef(); CreateFence(0, D3D12_FENCE_FLAG_NONE, __uuidof(ID3D12Fence), (void **)&m_GPUSyncFence); + m_GPUSyncFence->SetName(L"m_GPUSyncFence"); InternalRef(); m_GPUSyncHandle = ::CreateEvent(NULL, FALSE, FALSE, NULL); @@ -3929,10 +3938,10 @@ void WrappedID3D12Device::DestroyInternalResources() SAFE_RELEASE(m_DataUploadList[i]); SAFE_RELEASE(m_DataUploadAlloc); - for(size_t i = 0; i < ARRAY_COUNT(m_QueueReadbackData.allocs); i++) - SAFE_RELEASE(m_QueueReadbackData.allocs[i]); - for(size_t i = 0; i < ARRAY_COUNT(m_QueueReadbackData.lists); i++) - SAFE_RELEASE(m_QueueReadbackData.lists[i]); + SAFE_RELEASE(m_QueueReadbackData.unwrappedQueue); + SAFE_RELEASE(m_QueueReadbackData.alloc); + SAFE_RELEASE(m_QueueReadbackData.list); + SAFE_RELEASE(m_QueueReadbackData.fence); m_QueueReadbackData.Resize(0); SAFE_RELEASE(m_Alloc); diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index cfaa9d1f5..11ab2558d 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -68,10 +68,10 @@ struct QueueReadbackData byte *readbackMapped = NULL; uint64_t readbackSize = 0; - static const uint32_t NumCommandTypes = 7; - - ID3D12GraphicsCommandList *lists[NumCommandTypes] = {}; - ID3D12CommandAllocator *allocs[NumCommandTypes] = {}; + ID3D12CommandQueue *unwrappedQueue = NULL; + ID3D12GraphicsCommandList *list = NULL; + ID3D12CommandAllocator *alloc = NULL; + ID3D12Fence *fence = NULL; void Resize(uint64_t size);