mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-12 21:10:42 +00:00
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.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user