Handle root signatures not being specified on pipeline create

* If the root signature is embedded in a shader somewhere we need to pull it out
  for access.
This commit is contained in:
baldurk
2024-06-06 15:49:06 +01:00
parent 80f49ea8e4
commit 9aa57e5aaa
8 changed files with 111 additions and 24 deletions
@@ -490,6 +490,8 @@ bool WrappedID3D12Device::Serialise_CreateGraphicsPipelineState(
wrapped->graphics = new D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC(Descriptor);
wrapped->FetchRootSig(GetShaderCache());
D3D12_SHADER_BYTECODE *shaders[] = {
&wrapped->graphics->VS, &wrapped->graphics->HS, &wrapped->graphics->DS,
&wrapped->graphics->GS, &wrapped->graphics->PS,
@@ -637,6 +639,8 @@ void WrappedID3D12Device::ProcessCreatedGraphicsPSO(ID3D12PipelineState *real,
wrapped->graphics = new D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC(*pDesc);
wrapped->FetchRootSig(GetShaderCache());
D3D12_SHADER_BYTECODE *shaders[] = {
&wrapped->graphics->VS, &wrapped->graphics->HS, &wrapped->graphics->DS,
&wrapped->graphics->GS, &wrapped->graphics->PS, &wrapped->graphics->AS,
@@ -778,6 +782,8 @@ bool WrappedID3D12Device::Serialise_CreateComputePipelineState(
wrapped->compute = new D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC(Descriptor);
wrapped->FetchRootSig(GetShaderCache());
WrappedID3D12Shader *entry = WrappedID3D12Shader::AddShader(wrapped->compute->CS, this);
entry->AddRef();
@@ -860,6 +866,8 @@ void WrappedID3D12Device::ProcessCreatedComputePSO(ID3D12PipelineState *real, ui
wrapped->compute = new D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC(*pDesc);
wrapped->FetchRootSig(GetShaderCache());
WrappedID3D12Shader *sh = WrappedID3D12Shader::AddShader(wrapped->compute->CS, this);
sh->AddRef();
wrapped->compute->CS.pShaderBytecode = sh;
@@ -190,6 +190,8 @@ bool WrappedID3D12Device::Serialise_CreatePipelineState(SerialiserType &ser,
}
}
wrapped->FetchRootSig(GetShaderCache());
// if this shader was initialised with nvidia's dynamic UAV, pull in that chunk as one of ours
// and unset it (there will be one for each create that actually used vendor extensions)
if(m_VendorEXT == GPUVendor::nVidia && m_GlobalEXTUAV != ~0U)
@@ -382,6 +384,8 @@ HRESULT WrappedID3D12Device::CreatePipelineState(const D3D12_PIPELINE_STATE_STRE
wrapped->graphics->ViewInstancing.pViewInstanceLocations = NULL;
}
}
wrapped->FetchRootSig(GetShaderCache());
}
*ppPipelineState = (ID3D12PipelineState *)wrapped;
+1 -5
View File
@@ -2049,10 +2049,6 @@ rdcarray<DescriptorLogicalLocation> D3D12Replay::GetDescriptorLocations(
{
WrappedID3D12PipelineState *pipe = (WrappedID3D12PipelineState *)res;
WrappedID3D12RootSignature *sig =
(WrappedID3D12RootSignature *)(pipe->IsGraphics() ? pipe->graphics->pRootSignature
: pipe->compute->pRootSignature);
// root constants
size_t dst = 0;
for(const DescriptorRange &r : ranges)
@@ -2061,7 +2057,7 @@ rdcarray<DescriptorLogicalLocation> D3D12Replay::GetDescriptorLocations(
for(uint32_t i = 0; i < r.count; i++, rootIndex++, dst++)
{
const D3D12RootSignatureParameter &param = sig->sig.Parameters[rootIndex];
const D3D12RootSignatureParameter &param = pipe->usedSig.Parameters[rootIndex];
DescriptorLogicalLocation &l = ret[dst];
+61 -17
View File
@@ -26,6 +26,7 @@
#include "driver/shaders/dxbc/dxbc_reflect.h"
#include "d3d12_command_list.h"
#include "d3d12_command_queue.h"
#include "d3d12_shader_cache.h"
GPUAddressRangeTracker WrappedID3D12Resource::m_Addresses;
std::map<WrappedID3D12PipelineState::DXBCKey, WrappedID3D12Shader *> WrappedID3D12Shader::m_Shaders;
@@ -603,15 +604,15 @@ void WrappedID3D12PipelineState::ShaderEntry::BuildReflection()
m_Details->resourceId = GetResourceID();
}
rdcpair<uint32_t, uint32_t> FindMatchingRootParameter(const D3D12RootSignature *sig,
rdcpair<uint32_t, uint32_t> FindMatchingRootParameter(const D3D12RootSignature &sig,
D3D12_SHADER_VISIBILITY visibility,
D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
uint32_t space, uint32_t bind)
{
// search the root signature to find the matching entry and figure out the offset from the root binding
for(uint32_t root = 0; root < sig->Parameters.size(); root++)
for(uint32_t root = 0; root < sig.Parameters.size(); root++)
{
const D3D12RootSignatureParameter &param = sig->Parameters[root];
const D3D12RootSignatureParameter &param = sig.Parameters[root];
if(param.ShaderVisibility != visibility && param.ShaderVisibility != D3D12_SHADER_VISIBILITY_ALL)
continue;
@@ -659,11 +660,11 @@ rdcpair<uint32_t, uint32_t> FindMatchingRootParameter(const D3D12RootSignature *
if(rangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER)
{
// indicate that we're looking up static samplers
uint32_t numRoots = (uint32_t)sig->Parameters.size();
for(uint32_t samp = 0; samp < sig->StaticSamplers.size(); samp++)
uint32_t numRoots = (uint32_t)sig.Parameters.size();
for(uint32_t samp = 0; samp < sig.StaticSamplers.size(); samp++)
{
if(sig->StaticSamplers[samp].RegisterSpace == space &&
sig->StaticSamplers[samp].ShaderRegister == bind)
if(sig.StaticSamplers[samp].RegisterSpace == space &&
sig.StaticSamplers[samp].ShaderRegister == bind)
{
return {numRoots, samp};
}
@@ -673,18 +674,61 @@ rdcpair<uint32_t, uint32_t> FindMatchingRootParameter(const D3D12RootSignature *
return {~0U, 0};
}
void WrappedID3D12PipelineState::FetchRootSig(D3D12ShaderCache *shaderCache)
{
if(compute)
{
if(compute->pRootSignature)
{
usedSig = ((WrappedID3D12RootSignature *)compute->pRootSignature)->sig;
}
else
{
D3D12_SHADER_BYTECODE desc = CS()->GetDesc();
if(DXBC::DXBCContainer::CheckForRootSig(desc.pShaderBytecode, desc.BytecodeLength))
{
usedSig = shaderCache->GetRootSig(desc.pShaderBytecode, desc.BytecodeLength);
}
else
{
RDCWARN("Couldn't find root signature in either desc or compute shader");
}
}
}
else if(graphics)
{
if(graphics->pRootSignature)
{
usedSig = ((WrappedID3D12RootSignature *)graphics->pRootSignature)->sig;
}
else
{
// if there is any root signature it must match in all shaders, so we just have to find the first one.
for(ShaderEntry *shad : {PS(), VS(), HS(), DS(), GS(), AS(), MS()})
{
if(shad)
{
D3D12_SHADER_BYTECODE desc = shad->GetDesc();
if(DXBC::DXBCContainer::CheckForRootSig(desc.pShaderBytecode, desc.BytecodeLength))
{
usedSig = shaderCache->GetRootSig(desc.pShaderBytecode, desc.BytecodeLength);
return;
}
}
}
RDCWARN("Couldn't find root signature in either desc or any bound shader");
}
}
}
void WrappedID3D12PipelineState::ProcessDescriptorAccess()
{
if(m_AccessProcessed)
return;
m_AccessProcessed = true;
const D3D12RootSignature *sig = NULL;
if(graphics)
sig = &((WrappedID3D12RootSignature *)graphics->pRootSignature)->sig;
else if(compute)
sig = &((WrappedID3D12RootSignature *)compute->pRootSignature)->sig;
for(ShaderEntry *shad : {VS(), HS(), DS(), GS(), PS(), AS(), MS(), CS()})
{
if(!shad)
@@ -727,7 +771,7 @@ void WrappedID3D12PipelineState::ProcessDescriptorAccess()
access.type = DescriptorType::ConstantBuffer;
access.index = i;
rdctie(access.byteSize, access.byteOffset) =
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
FindMatchingRootParameter(usedSig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_CBV,
bind.fixedBindSetOrSpace, bind.fixedBindNumber);
if(access.byteSize != ~0U)
@@ -746,7 +790,7 @@ void WrappedID3D12PipelineState::ProcessDescriptorAccess()
access.type = DescriptorType::Sampler;
access.index = i;
rdctie(access.byteSize, access.byteOffset) =
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
FindMatchingRootParameter(usedSig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
bind.fixedBindSetOrSpace, bind.fixedBindNumber);
if(access.byteSize != ~0U)
@@ -765,7 +809,7 @@ void WrappedID3D12PipelineState::ProcessDescriptorAccess()
access.type = refl.readOnlyResources[i].descriptorType;
access.index = i;
rdctie(access.byteSize, access.byteOffset) =
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
FindMatchingRootParameter(usedSig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
bind.fixedBindSetOrSpace, bind.fixedBindNumber);
if(access.byteSize != ~0U)
@@ -784,7 +828,7 @@ void WrappedID3D12PipelineState::ProcessDescriptorAccess()
access.type = refl.readWriteResources[i].descriptorType;
access.index = i;
rdctie(access.byteSize, access.byteOffset) =
FindMatchingRootParameter(sig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
FindMatchingRootParameter(usedSig, visibility, D3D12_DESCRIPTOR_RANGE_TYPE_UAV,
bind.fixedBindSetOrSpace, bind.fixedBindNumber);
if(access.byteSize != ~0U)
+7 -1
View File
@@ -29,7 +29,7 @@
#include "d3d12_device.h"
#include "d3d12_manager.h"
rdcpair<uint32_t, uint32_t> FindMatchingRootParameter(const D3D12RootSignature *sig,
rdcpair<uint32_t, uint32_t> FindMatchingRootParameter(const D3D12RootSignature &sig,
D3D12_SHADER_VISIBILITY visibility,
D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
uint32_t space, uint32_t bind);
@@ -642,9 +642,15 @@ public:
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC *graphics = NULL;
D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC *compute = NULL;
// either the signature from graphics/compute above, or else an extracted signature from the
// shader blobs inside valid only on replay
D3D12RootSignature usedSig;
rdcarray<DescriptorAccess> staticDescriptorAccess;
bool m_AccessProcessed = false;
void FetchRootSig(D3D12ShaderCache *shaderCache);
void Fill(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &desc)
{
if(graphics)
@@ -1520,7 +1520,7 @@ bool D3D12Replay::FetchShaderFeedback(uint32_t eventId)
{
access.arrayElement = i;
rdctie(access.byteSize, access.byteOffset) = FindMatchingRootParameter(
&modsig, visibility, rangeType, it->first.space, it->first.bind);
modsig, visibility, rangeType, it->first.space, it->first.bind);
access.byteOffset += access.arrayElement;
@@ -1109,6 +1109,34 @@ bool DXBCContainer::CheckForDXIL(const void *ByteCode, size_t ByteCodeLength)
return false;
}
bool DXBCContainer::CheckForRootSig(const void *ByteCode, size_t ByteCodeLength)
{
FileHeader *header = (FileHeader *)ByteCode;
char *data = (char *)ByteCode; // just for convenience
if(ByteCode == NULL || ByteCodeLength == 0)
return false;
if(header->fourcc != FOURCC_DXBC)
return false;
if(header->fileLength != (uint32_t)ByteCodeLength)
return false;
uint32_t *chunkOffsets = (uint32_t *)(header + 1); // right after the header
for(uint32_t chunkIdx = 0; chunkIdx < header->numChunks; chunkIdx++)
{
uint32_t *fourcc = (uint32_t *)(data + chunkOffsets[chunkIdx]);
if(*fourcc == FOURCC_RTS0)
return true;
}
return false;
}
rdcstr DXBCContainer::GetDebugBinaryPath(const void *ByteCode, size_t ByteCodeLength)
{
rdcstr debugPath;
@@ -233,6 +233,7 @@ public:
static bool CheckForDebugInfo(const void *ByteCode, size_t ByteCodeLength);
static bool CheckForDXIL(const void *ByteCode, size_t ByteCodeLength);
static bool CheckForRootSig(const void *ByteCode, size_t ByteCodeLength);
static rdcstr GetDebugBinaryPath(const void *ByteCode, size_t ByteCodeLength);
static D3D_PRIMITIVE_TOPOLOGY GetOutputTopology(const void *ByteCode, size_t ByteCodeLength);