From d0fe1fb56fd82de7c83b0b0807960d71cbac808f Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 23 Sep 2016 13:28:54 +0200 Subject: [PATCH] Implement GetBufferData() for D3D12 --- renderdoc/driver/d3d12/d3d12_debug.cpp | 96 +++++++++++++++++++++++++ renderdoc/driver/d3d12/d3d12_debug.h | 5 +- renderdoc/driver/d3d12/d3d12_replay.cpp | 31 ++++---- 3 files changed, 116 insertions(+), 16 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_debug.cpp b/renderdoc/driver/d3d12/d3d12_debug.cpp index 420ccee81..268205018 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.cpp +++ b/renderdoc/driver/d3d12/d3d12_debug.cpp @@ -1391,6 +1391,102 @@ void D3D12DebugManager::PickPixel(ResourceId texture, uint32_t x, uint32_t y, ui m_ReadbackBuffer->Unmap(0, &range); } +void D3D12DebugManager::GetBufferData(ResourceId buff, uint64_t offset, uint64_t length, + vector &retData) +{ + auto it = WrappedID3D12Resource::m_List.find(buff); + + if(it == WrappedID3D12Resource::m_List.end()) + { + RDCERR("Getting buffer data for unknown buffer %llu!", buff); + return; + } + + WrappedID3D12Resource *buffer = it->second; + + RDCASSERT(buffer); + + GetBufferData(buffer, offset, length, retData); +} + +void D3D12DebugManager::GetBufferData(ID3D12Resource *buffer, uint64_t offset, uint64_t length, + vector &ret) +{ + if(buffer == NULL) + return; + + D3D12_RESOURCE_DESC desc = buffer->GetDesc(); + + if(offset >= desc.Width) + { + // can't read past the end of the buffer, return empty + return; + } + + if(length == 0) + { + length = desc.Width - offset; + } + + if(length > 0 && offset + length > desc.Width) + { + RDCWARN("Attempting to read off the end of the buffer (%llu %llu). Will be clamped (%llu)", + offset, length, desc.Width); + length = RDCMIN(length, desc.Width - offset); + } + + uint64_t outOffs = 0; + + ret.resize(length); + + ID3D12GraphicsCommandList *list = m_WrappedDevice->GetNewList(); + + D3D12_RESOURCE_BARRIER barrier = {}; + + barrier.Transition.pResource = buffer; + barrier.Transition.StateBefore = m_WrappedDevice->GetSubresourceStates(GetResID(buffer))[0]; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_SOURCE; + + list->ResourceBarrier(1, &barrier); + + while(length > 0) + { + uint64_t chunkSize = RDCMIN(length, m_ReadbackSize); + + list->CopyBufferRegion(m_ReadbackBuffer, 0, buffer, offset, chunkSize); + + list->Close(); + + m_WrappedDevice->ExecuteLists(); + m_WrappedDevice->FlushLists(); + + D3D12_RANGE range = {0, chunkSize}; + + void *data; + HRESULT hr = m_ReadbackBuffer->Map(0, &range, &data); + + if(FAILED(hr)) + { + RDCERR("Failed to map bufferdata buffer %08x", hr); + return; + } + else + { + memcpy(&ret[outOffs], data, chunkSize); + + range.End = 0; + + m_ReadbackBuffer->Unmap(0, &range); + } + + outOffs += chunkSize; + length -= chunkSize; + + if(length > 0) + list = m_WrappedDevice->GetNewList(); + } +} + void D3D12DebugManager::RenderCheckerboard(Vec3f light, Vec3f dark) { DebugVertexCBuffer vertexData; diff --git a/renderdoc/driver/d3d12/d3d12_debug.h b/renderdoc/driver/d3d12/d3d12_debug.h index 87555591d..aa211f795 100644 --- a/renderdoc/driver/d3d12/d3d12_debug.h +++ b/renderdoc/driver/d3d12/d3d12_debug.h @@ -73,6 +73,9 @@ public: void PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, FormatComponentType typeHint, float pixel[4]); + void GetBufferData(ResourceId buff, uint64_t offset, uint64_t length, vector &retData); + void GetBufferData(ID3D12Resource *buff, uint64_t offset, uint64_t length, vector &retData); + D3D12_CPU_DESCRIPTOR_HANDLE AllocRTV(); void FreeRTV(D3D12_CPU_DESCRIPTOR_HANDLE handle); @@ -179,7 +182,7 @@ private: ID3D12Resource *m_ReadbackBuffer; - static const uint32_t m_ReadbackSize = 8 * 1024 * 1024; + static const uint64_t m_ReadbackSize = 16 * 1024 * 1024; static const uint32_t m_ShaderCacheMagic = 0xbaafd1d1; static const uint32_t m_ShaderCacheVersion = 1; diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 948b11e4f..f9e81b8f0 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -57,6 +57,17 @@ void D3D12Replay::ReadLogInitialisation() m_pDevice->ReadLogInitialisation(); } +APIProperties D3D12Replay::GetAPIProperties() +{ + APIProperties ret; + + ret.pipelineType = eGraphicsAPI_D3D12; + ret.localRenderer = eGraphicsAPI_D3D12; + ret.degraded = false; + + return ret; +} + void D3D12Replay::ReplayLog(uint32_t endEventID, ReplayLogType replayType) { m_pDevice->ReplayLog(0, endEventID, replayType); @@ -1135,6 +1146,11 @@ bool D3D12Replay::RenderTexture(TextureDisplay cfg) return m_pDevice->GetDebugManager()->RenderTexture(cfg, true); } +void D3D12Replay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &retData) +{ + m_pDevice->GetDebugManager()->GetBufferData(buff, offset, len, retData); +} + void D3D12Replay::PickPixel(ResourceId texture, uint32_t x, uint32_t y, uint32_t sliceFace, uint32_t mip, uint32_t sample, FormatComponentType typeHint, float pixel[4]) @@ -1214,17 +1230,6 @@ Callstack::StackResolver *D3D12Replay::GetCallstackResolver() #pragma region not yet implemented -APIProperties D3D12Replay::GetAPIProperties() -{ - APIProperties ret; - - ret.pipelineType = eGraphicsAPI_D3D12; - ret.localRenderer = eGraphicsAPI_D3D12; - ret.degraded = false; - - return ret; -} - vector D3D12Replay::GetDebugMessages() { return vector(); @@ -1266,10 +1271,6 @@ MeshFormat D3D12Replay::GetPostVSBuffers(uint32_t eventID, uint32_t instID, Mesh return MeshFormat(); } -void D3D12Replay::GetBufferData(ResourceId buff, uint64_t offset, uint64_t len, vector &retData) -{ -} - byte *D3D12Replay::GetTextureData(ResourceId tex, uint32_t arrayIdx, uint32_t mip, bool forDiskSave, FormatComponentType typeHint, bool resolve, bool forceRGBA8unorm, float blackPoint, float whitePoint, size_t &dataSize)