diff --git a/docs/behind_scenes/d3d12_support.rst b/docs/behind_scenes/d3d12_support.rst index a2dff1a630..60c910b074 100644 --- a/docs/behind_scenes/d3d12_support.rst +++ b/docs/behind_scenes/d3d12_support.rst @@ -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 -------- diff --git a/docs/how/how_annotate_capture.rst b/docs/how/how_annotate_capture.rst index ea5ad812e3..4e8680ee49 100644 --- a/docs/how/how_annotate_capture.rst +++ b/docs/how/how_annotate_capture.rst @@ -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 --------- diff --git a/renderdoc/driver/d3d12/d3d12_common.cpp b/renderdoc/driver/d3d12/d3d12_common.cpp index 376e09c815..804f8d2454 100644 --- a/renderdoc/driver/d3d12/d3d12_common.cpp +++ b/renderdoc/driver/d3d12/d3d12_common.cpp @@ -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; } diff --git a/renderdoc/driver/d3d12/d3d12_device.h b/renderdoc/driver/d3d12/d3d12_device.h index 30023f7da8..0bef42478d 100644 --- a/renderdoc/driver/d3d12/d3d12_device.h +++ b/renderdoc/driver/d3d12/d3d12_device.h @@ -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); }; diff --git a/renderdoc/driver/d3d12/d3d12_initstate.cpp b/renderdoc/driver/d3d12/d3d12_initstate.cpp index 5166380caa..2d361bd060 100644 --- a/renderdoc/driver/d3d12/d3d12_initstate.cpp +++ b/renderdoc/driver/d3d12/d3d12_initstate.cpp @@ -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 names = initial ? initial->descriptorNames : rdcarray(); // 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 diff --git a/renderdoc/driver/d3d12/d3d12_manager.h b/renderdoc/driver/d3d12/d3d12_manager.h index 2705b82607..e7c44492b9 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.h +++ b/renderdoc/driver/d3d12/d3d12_manager.h @@ -793,6 +793,7 @@ struct D3D12InitialContents ID3D12DeviceChild *resource; byte *srcData; size_t dataSize; + rdcarray descriptorNames; rdcarray subresources; diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index e74a2f7bd3..aa0ee6a3aa 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -2129,6 +2129,16 @@ rdcarray 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 diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index 87fe91c07f..d2d7a5fbd4 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -469,7 +469,15 @@ class WrappedID3D12CommandSignature : public WrappedDeviceChild12 +MIDL_INTERFACE("52528c37-bfd9-4bbb-99ff-fdb7188619ce") +IRenderDocDescriptorNamer : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE SetName(UINT DescriptorIndex, LPCSTR Name) = 0; +}; + +class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12, + public IRenderDocDescriptorNamer { D3D12_CPU_DESCRIPTOR_HANDLE realCPUBase; D3D12_GPU_DESCRIPTOR_HANDLE realGPUBase; @@ -487,6 +495,9 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12 names; + public: ALLOCATE_WITH_WRAPPED_POOL(WrappedID3D12DescriptorHeap); @@ -499,6 +510,33 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12 &GetNames() + { + SCOPED_LOCK(namesLock); + names.resize(numDescriptors); + return names; + } + D3D12Descriptor *GetDescriptors() { return descriptors; } UINT GetNumDescriptors() { return numDescriptors; } @@ -545,6 +583,23 @@ class WrappedID3D12DescriptorHeap : public WrappedDeviceChild12= 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 diff --git a/util/test/demos/d3d12/d3d12_descriptor_indexing.cpp b/util/test/demos/d3d12/d3d12_descriptor_indexing.cpp index 596a646833..fc77e040b2 100644 --- a/util/test/demos/d3d12/d3d12_descriptor_indexing.cpp +++ b/util/test/demos/d3d12/d3d12_descriptor_indexing.cpp @@ -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;