diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp index 51b428bcf..0bed5d594 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap.cpp @@ -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; diff --git a/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp b/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp index dfda74a77..68f64965a 100644 --- a/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp +++ b/renderdoc/driver/d3d12/d3d12_device_wrap2.cpp @@ -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; diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 0f42fd860..d748859e9 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -2049,10 +2049,6 @@ rdcarray 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 D3D12Replay::GetDescriptorLocations( for(uint32_t i = 0; i < r.count; i++, rootIndex++, dst++) { - const D3D12RootSignatureParameter ¶m = sig->sig.Parameters[rootIndex]; + const D3D12RootSignatureParameter ¶m = pipe->usedSig.Parameters[rootIndex]; DescriptorLogicalLocation &l = ret[dst]; diff --git a/renderdoc/driver/d3d12/d3d12_resources.cpp b/renderdoc/driver/d3d12/d3d12_resources.cpp index 8369cff3a..2f7d92d96 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.cpp +++ b/renderdoc/driver/d3d12/d3d12_resources.cpp @@ -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 WrappedID3D12Shader::m_Shaders; @@ -603,15 +604,15 @@ void WrappedID3D12PipelineState::ShaderEntry::BuildReflection() m_Details->resourceId = GetResourceID(); } -rdcpair FindMatchingRootParameter(const D3D12RootSignature *sig, +rdcpair 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 ¶m = sig->Parameters[root]; + const D3D12RootSignatureParameter ¶m = sig.Parameters[root]; if(param.ShaderVisibility != visibility && param.ShaderVisibility != D3D12_SHADER_VISIBILITY_ALL) continue; @@ -659,11 +660,11 @@ rdcpair 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 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) diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index d947f82dd..9dc1252ee 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -29,7 +29,7 @@ #include "d3d12_device.h" #include "d3d12_manager.h" -rdcpair FindMatchingRootParameter(const D3D12RootSignature *sig, +rdcpair 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 staticDescriptorAccess; bool m_AccessProcessed = false; + void FetchRootSig(D3D12ShaderCache *shaderCache); + void Fill(D3D12_EXPANDED_PIPELINE_STATE_STREAM_DESC &desc) { if(graphics) diff --git a/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp b/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp index e6e12760f..0dbed640b 100644 --- a/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp +++ b/renderdoc/driver/d3d12/d3d12_shader_feedback.cpp @@ -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; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp index bbc1371d0..599d76e83 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.cpp @@ -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; diff --git a/renderdoc/driver/shaders/dxbc/dxbc_container.h b/renderdoc/driver/shaders/dxbc/dxbc_container.h index e1d29be2f..6fb7fa11a 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_container.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_container.h @@ -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);