Add custom D3D12 interface for per-heap descriptor naming by index

This commit is contained in:
baldurk
2024-12-13 21:19:38 +00:00
parent cd603f07dc
commit 7fe2749b38
9 changed files with 141 additions and 4 deletions
+17 -1
View File
@@ -19,7 +19,23 @@ RenderDoc has initial support for D3D12, but it contains some caveats. In additi
* RenderDoc assumes that even if multiple GPUs are present, that only one will be used - i.e. NodeMask is always 0. Multiple queues are supported.
* RenderDoc captures may not be portable between different systems, only currently supporting capture and replay on the same or similar enough machines.
* Shader debugging is not supported for DXIL shaders.
RenderDoc extensions
--------------------
On D3D12 there is a RenderDoc extension provided with this interface, queried from an ``ID3D12DescriptorHeap``:
.. highlight:: c++
.. code:: c++
MIDL_INTERFACE("52528c37-bfd9-4bbb-99ff-fdb7188619ce")
IRenderDocDescriptorNamer : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetName(UINT DescriptorIndex, LPCSTR Name) = 0;
};
This interface allows you to set a custom name for descriptors, if using SM6.6 style ``ResourceDescriptorHeap[]`` access for better debugging.
See Also
--------
+16
View File
@@ -168,6 +168,22 @@ In Vulkan you can enable the ``VK_EXT_debug_utils`` extension, which is provided
nameInfo.pObjectName = "Off-screen color framebuffer";
vkSetDebugUtilsObjectNameEXT(device, &nameInfo);
On D3D12 there is a RenderDoc extension provided with this interface, queried from an ``ID3D12DescriptorHeap``:
.. highlight:: c++
.. code:: c++
MIDL_INTERFACE("52528c37-bfd9-4bbb-99ff-fdb7188619ce")
IRenderDocDescriptorNamer : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetName(UINT DescriptorIndex, LPCSTR Name) = 0;
};
This interface allows you to set a custom name for descriptors, if using SM6.6 style ``ResourceDescriptorHeap[]`` access for better debugging.
Bookmarks
---------
+4
View File
@@ -506,6 +506,10 @@ bool D3D12InitParams::IsSupportedVersion(uint64_t ver)
if(ver == 0x11)
return true;
// 0x12 -> 0x13 - Descriptor heap initial states contain optional user names for descriptors
if(ver == 0x12)
return true;
return false;
}
+1 -1
View File
@@ -64,7 +64,7 @@ struct D3D12InitParams
UINT SDKVersion = 0;
// check if a frame capture section version is supported
static const uint64_t CurrentVersion = 0x12;
static const uint64_t CurrentVersion = 0x13;
static bool IsSupportedVersion(uint64_t ver);
};
+15 -1
View File
@@ -94,7 +94,12 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res)
D3D12Descriptor *descs = new D3D12Descriptor[numElems];
memcpy(descs, heap->GetDescriptors(), sizeof(D3D12Descriptor) * numElems);
SetInitialContents(heap->GetResourceID(), D3D12InitialContents(descs, numElems));
D3D12InitialContents initContents(descs, numElems);
if(heap->HasNames())
initContents.descriptorNames = heap->GetNames();
SetInitialContents(heap->GetResourceID(), initContents);
return true;
}
else if(type == Resource_Resource)
@@ -768,6 +773,7 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
{
D3D12Descriptor *Descriptors = initial ? initial->descriptors : NULL;
uint32_t numElems = initial ? initial->numDescriptors : 0;
rdcarray<rdcstr> names = initial ? initial->descriptorNames : rdcarray<rdcstr>();
// there's no point in setting up a lazy array when we're structured exporting because we KNOW
// we're going to need all the data anyway.
@@ -777,6 +783,11 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
SERIALISE_ELEMENT_ARRAY(Descriptors, numElems);
SERIALISE_ELEMENT(numElems).Named("NumDescriptors"_lit).Important();
if(ser.VersionAtLeast(0x13))
{
SERIALISE_ELEMENT(names).Hidden();
}
ser.SetLazyThreshold(0);
SERIALISE_CHECK_READ_ERRORS();
@@ -785,6 +796,9 @@ bool D3D12ResourceManager::Serialise_InitialState(SerialiserType &ser, ResourceI
{
WrappedID3D12DescriptorHeap *heap = (WrappedID3D12DescriptorHeap *)GetLiveResource(id);
if(!names.empty())
heap->GetNames() = names;
D3D12_DESCRIPTOR_HEAP_DESC desc = heap->GetDesc();
// this heap doesn't have to be shader visible, we just use it to copy from
+1
View File
@@ -793,6 +793,7 @@ struct D3D12InitialContents
ID3D12DeviceChild *resource;
byte *srcData;
size_t dataSize;
rdcarray<rdcstr> descriptorNames;
rdcarray<uint32_t> subresources;
+10
View File
@@ -2129,6 +2129,16 @@ rdcarray<DescriptorLogicalLocation> D3D12Replay::GetDescriptorLocations(
{
// can't set anything except the "bind number" which we just set as the offset.
ret[dst].fixedBindNumber = descriptorId;
if(heap->HasNames())
{
rdcstr name = heap->GetNames()[descriptorId];
if(!name.empty())
{
ret[dst].logicalBindName = StringFormat::Fmt("%s[%u]", name.c_str(), descriptorId);
continue;
}
}
if(sampler)
ret[dst].logicalBindName = StringFormat::Fmt("SamplerDescriptorHeap[%u]", descriptorId);
else
+56 -1
View File
@@ -469,7 +469,15 @@ public:
struct D3D12Descriptor;
class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12<ID3D12DescriptorHeap>
MIDL_INTERFACE("52528c37-bfd9-4bbb-99ff-fdb7188619ce")
IRenderDocDescriptorNamer : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetName(UINT DescriptorIndex, LPCSTR Name) = 0;
};
class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12<ID3D12DescriptorHeap>,
public IRenderDocDescriptorNamer
{
D3D12_CPU_DESCRIPTOR_HANDLE realCPUBase;
D3D12_GPU_DESCRIPTOR_HANDLE realGPUBase;
@@ -487,6 +495,9 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12<ID3D12Descriptor
// (which applications then queried and passed to the GPU) which is used for GPU-unwrapping handles
uint64_t m_OriginalWrappedGPUBase;
Threading::CriticalSection namesLock;
rdcarray<rdcstr> names;
public:
ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12DescriptorHeap);
@@ -499,6 +510,33 @@ public:
const D3D12_DESCRIPTOR_HEAP_DESC &desc, UINT UnpatchedNumDescriptors);
virtual ~WrappedID3D12DescriptorHeap();
ULONG STDMETHODCALLTYPE AddRef() { return WrappedDeviceChild12::AddRef(); }
ULONG STDMETHODCALLTYPE Release() { return WrappedDeviceChild12::Release(); }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
if(riid == __uuidof(IRenderDocDescriptorNamer))
{
*ppvObject = (IRenderDocDescriptorNamer *)this;
// allocate names array now
GetNames();
AddRef();
return S_OK;
}
return WrappedDeviceChild12::QueryInterface(riid, ppvObject);
}
bool HasNames()
{
SCOPED_LOCK(namesLock);
return !names.empty();
}
rdcarray<rdcstr> &GetNames()
{
SCOPED_LOCK(namesLock);
names.resize(numDescriptors);
return names;
}
D3D12Descriptor *GetDescriptors() { return descriptors; }
UINT GetNumDescriptors() { return numDescriptors; }
@@ -545,6 +583,23 @@ public:
}
uint32_t GetUnwrappedIncrement() const { return increment; }
//////////////////////////////
// implement IRenderDocDescriptorNamer
virtual HRESULT STDMETHODCALLTYPE SetName(UINT DescriptorIndex, LPCSTR Name)
{
if(DescriptorIndex >= numDescriptors)
return E_INVALIDARG;
SCOPED_LOCK(namesLock);
if(!Name || !Name[0])
names[DescriptorIndex].clear();
else
names[DescriptorIndex] = Name;
return S_OK;
}
};
class WrappedID3D12Fence : public WrappedDeviceChild12<ID3D12Fence, ID3D12Fence1>
@@ -24,6 +24,15 @@
#include "d3d12_test.h"
MIDL_INTERFACE("52528c37-bfd9-4bbb-99ff-fdb7188619ce")
IRenderDocDescriptorNamer : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE SetName(UINT DescriptorIndex, LPCSTR Name) = 0;
};
COM_SMARTPTR(IRenderDocDescriptorNamer);
RD_TEST(D3D12_Descriptor_Indexing, D3D12GraphicsTest)
{
static constexpr const char *Description =
@@ -464,9 +473,17 @@ float4 main(v2f IN) : SV_Target0
MakeSRV(alias1Buf).StructureStride(3 * sizeof(Vec4f)).CreateGPU(150 + 6);
MakeSRV(alias2Buf).StructureStride(3 * sizeof(Vec4f)).CreateGPU(150 + 12);
IRenderDocDescriptorNamerPtr namer = m_CBVUAVSRV;
MakeSRV(smiley).CreateGPU(12);
if(namer)
namer->SetName(12, "smiley");
MakeSRV(smiley).CreateGPU(19);
if(namer)
namer->SetName(19, "another_smiley");
MakeSRV(smiley).CreateGPU(20);
if(namer)
namer->SetName(20, "more_smileys???");
MakeSRV(smiley).CreateGPU(21);
MakeSRV(smiley).CreateGPU(49);
MakeSRV(smiley).CreateGPU(59);
@@ -474,7 +491,11 @@ float4 main(v2f IN) : SV_Target0
MakeSRV(smiley).CreateGPU(99);
MakeSRV(smiley).CreateGPU(103);
MakeCBV(constBuf).SizeBytes(256).CreateGPU(9);
if(namer)
namer->SetName(9, "constBuf");
MakeUAV(outUAV).Format(DXGI_FORMAT_R32_UINT).CreateGPU(10);
if(namer)
namer->SetName(10, "outUAV");
D3D12_SAMPLER_DESC samplerDesc = {};
samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;