From fe6b702ff44433f8b9005ff1e73b463c4cac1c81 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 22 Sep 2023 14:47:37 +0100 Subject: [PATCH] Allow out of bounds GPU addresses when serialising * Worst case this is just as invalid as an application, if it uses a totally bogus VA. However in D3D12 it is apparently valid to refer to VAs out of bounds of any resource as long as it's within bounds of an underlying heap. To handle this without serialising VAs as Heap+offset we instead just allow the address lookup to run out of bounds and pick the next lowest buffer. If the offset is greater than the buffer size then we're probably no worse than the application. --- renderdoc/driver/d3d12/d3d12_manager.cpp | 29 ++++++++++++++++++++++ renderdoc/driver/d3d12/d3d12_manager.h | 1 + renderdoc/driver/d3d12/d3d12_resources.h | 6 +++++ renderdoc/driver/d3d12/d3d12_serialise.cpp | 2 +- 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/renderdoc/driver/d3d12/d3d12_manager.cpp b/renderdoc/driver/d3d12/d3d12_manager.cpp index 99726dc39..13598546a 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.cpp +++ b/renderdoc/driver/d3d12/d3d12_manager.cpp @@ -1037,3 +1037,32 @@ void GPUAddressRangeTracker::GetResIDFromAddr(D3D12_GPU_VIRTUAL_ADDRESS addr, Re id = range.id; offs = addr - range.start; } + +void GPUAddressRangeTracker::GetResIDFromAddrAllowOutOfBounds(D3D12_GPU_VIRTUAL_ADDRESS addr, + ResourceId &id, UINT64 &offs) +{ + id = ResourceId(); + offs = 0; + + if(addr == 0) + return; + + GPUAddressRange range; + + // this should really be a read-write lock + { + SCOPED_READLOCK(addressLock); + + auto it = std::lower_bound(addresses.begin(), addresses.end(), addr); + if(it == addresses.end()) + return; + + range = *it; + } + + if(addr < range.start) + return; + + id = range.id; + offs = addr - range.start; +} diff --git a/renderdoc/driver/d3d12/d3d12_manager.h b/renderdoc/driver/d3d12/d3d12_manager.h index 3e059f04c..73d2a4af5 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.h +++ b/renderdoc/driver/d3d12/d3d12_manager.h @@ -529,6 +529,7 @@ struct GPUAddressRangeTracker void AddTo(const GPUAddressRange &range); void RemoveFrom(const GPUAddressRange &range); void GetResIDFromAddr(D3D12_GPU_VIRTUAL_ADDRESS addr, ResourceId &id, UINT64 &offs); + void GetResIDFromAddrAllowOutOfBounds(D3D12_GPU_VIRTUAL_ADDRESS addr, ResourceId &id, UINT64 &offs); }; struct MapState diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index 89a5fe0c1..a41b427b7 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -969,6 +969,12 @@ public: m_Addresses.GetResIDFromAddr(addr, id, offs); } + static void GetResIDFromAddrAllowOutOfBounds(D3D12_GPU_VIRTUAL_ADDRESS addr, ResourceId &id, + UINT64 &offs) + { + m_Addresses.GetResIDFromAddrAllowOutOfBounds(addr, id, offs); + } + // overload to just return the id in case the offset isn't needed static ResourceId GetResIDFromAddr(D3D12_GPU_VIRTUAL_ADDRESS addr) { diff --git a/renderdoc/driver/d3d12/d3d12_serialise.cpp b/renderdoc/driver/d3d12/d3d12_serialise.cpp index a30f70538..32cef7b5e 100644 --- a/renderdoc/driver/d3d12/d3d12_serialise.cpp +++ b/renderdoc/driver/d3d12/d3d12_serialise.cpp @@ -334,7 +334,7 @@ void DoSerialise(SerialiserType &ser, D3D12BufferLocation &el) UINT64 offs = 0; if(ser.IsWriting() || ser.IsStructurising()) - WrappedID3D12Resource::GetResIDFromAddr(el.Location, buffer, offs); + WrappedID3D12Resource::GetResIDFromAddrAllowOutOfBounds(el.Location, buffer, offs); if(ser.IsStructurising() && rm) buffer = rm->GetOriginalID(buffer);