From 06e6677616515fad032977f455c0af8257346cd6 Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 23 Sep 2016 11:41:16 +0200 Subject: [PATCH] Divide up register spaces by shader stage (namespacing same as DX11) --- renderdoc/api/replay/d3d12_pipestate.h | 38 +- renderdoc/driver/d3d12/d3d12_replay.cpp | 627 ++++++++++-------- renderdoc/driver/d3d12/d3d12_replay.h | 4 + renderdocui/Code/CommonPipelineState.cs | 82 ++- renderdocui/Interop/D3D12PipelineState.cs | 53 +- .../PipelineState/D3D12PipelineStateViewer.cs | 267 ++++---- 6 files changed, 578 insertions(+), 493 deletions(-) diff --git a/renderdoc/api/replay/d3d12_pipestate.h b/renderdoc/api/replay/d3d12_pipestate.h index 4dfb2b48e..e0263c2ee 100644 --- a/renderdoc/api/replay/d3d12_pipestate.h +++ b/renderdoc/api/replay/d3d12_pipestate.h @@ -33,6 +33,8 @@ struct D3D12PipelineState bool32 customName; rdctype::str PipelineName; + ResourceId rootSig; + struct InputAssembler { InputAssembler() : indexStripCutValue(0) {} @@ -73,25 +75,14 @@ struct D3D12PipelineState uint32_t indexStripCutValue; } m_IA; - struct ShaderStage - { - ShaderStage() : ShaderDetails(NULL), stage(eShaderStage_Vertex) {} - ResourceId Shader; - ShaderReflection *ShaderDetails; - ShaderBindpointMapping BindpointMapping; - - ShaderStageType stage; - } m_VS, m_HS, m_DS, m_GS, m_PS, m_CS; - // Immediate indicates either a root parameter (not in a table), or static samplers // RootElement is the index in the original root signature that this descriptor came from. struct ResourceView { ResourceView() - : VisibilityMask(), - Immediate(0), - RootElement(0), + : Immediate(0), + RootElement(~0U), Resource(), Format(), BufferFlags(0), @@ -113,7 +104,6 @@ struct D3D12PipelineState } // parameters from descriptor - ShaderStageBits VisibilityMask; bool32 Immediate; uint32_t RootElement; @@ -146,9 +136,8 @@ struct D3D12PipelineState struct Sampler { Sampler() - : VisibilityMask(), - Immediate(0), - RootElement(0), + : Immediate(0), + RootElement(~0U), UseBorder(false), UseComparison(false), MaxAniso(0), @@ -160,7 +149,6 @@ struct D3D12PipelineState } // parameters from descriptor - ShaderStageBits VisibilityMask; bool32 Immediate; uint32_t RootElement; @@ -179,9 +167,8 @@ struct D3D12PipelineState struct CBuffer { - CBuffer() : VisibilityMask(), Immediate(0), RootElement(0), Buffer(), Offset(0), ByteSize(0) {} + CBuffer() : Immediate(0), RootElement(~0U), Buffer(), Offset(0), ByteSize(0) {} // parameters from descriptor - ShaderStageBits VisibilityMask; bool32 Immediate; uint32_t RootElement; @@ -193,9 +180,14 @@ struct D3D12PipelineState rdctype::array RootValues; }; - struct RootSignature + struct ShaderStage { - ResourceId obj; + ShaderStage() : ShaderDetails(NULL), stage(eShaderStage_Vertex) {} + ResourceId Shader; + ShaderReflection *ShaderDetails; + ShaderBindpointMapping BindpointMapping; + + ShaderStageType stage; struct RegisterSpace { @@ -205,7 +197,7 @@ struct D3D12PipelineState rdctype::array UAVs; }; rdctype::array Spaces; - } m_RootSig; + } m_VS, m_HS, m_DS, m_GS, m_PS, m_CS; struct Streamout { diff --git a/renderdoc/driver/d3d12/d3d12_replay.cpp b/renderdoc/driver/d3d12/d3d12_replay.cpp index 60583a650..6004f57c3 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.cpp +++ b/renderdoc/driver/d3d12/d3d12_replay.cpp @@ -476,6 +476,342 @@ void D3D12Replay::FillResourceView(D3D12PipelineState::ResourceView &view, D3D12 } } +void D3D12Replay::FillRegisterSpaces( + const D3D12RenderState::RootSignature &rootSig, + rdctype::array &dstSpaces, + D3D12_SHADER_VISIBILITY visibility) +{ + D3D12ResourceManager *rm = m_pDevice->GetResourceManager(); + + WrappedID3D12RootSignature *sig = + m_pDevice->GetResourceManager()->GetCurrentAs(rootSig.rootsig); + + struct Space + { + vector cbuffers; + vector samplers; + vector srvs; + vector uavs; + }; + + Space *spaces = new Space[sig->sig.numSpaces]; + create_array_uninit(dstSpaces, sig->sig.numSpaces); + + for(size_t rootEl = 0; rootEl < sig->sig.params.size(); rootEl++) + { + const D3D12RootSignatureParameter &p = sig->sig.params[rootEl]; + + if(p.ShaderVisibility != D3D12_SHADER_VISIBILITY_ALL && p.ShaderVisibility != visibility) + continue; + + if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS) + { + D3D12PipelineState::CBuffer &cb = + resize_and_add(spaces[p.Constants.RegisterSpace].cbuffers, p.Constants.ShaderRegister); + cb.Immediate = true; + cb.RootElement = (uint32_t)rootEl; + cb.ByteSize = uint32_t(sizeof(uint32_t) * p.Constants.Num32BitValues); + + if(rootEl < rootSig.sigelems.size()) + { + const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; + if(e.type == eRootConst) + create_array_init(cb.RootValues, RDCMIN(e.constants.size(), (size_t)cb.ByteSize), + &e.constants[0]); + } + + if(cb.RootValues.count == 0) + create_array(cb.RootValues, p.Constants.Num32BitValues); + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV) + { + D3D12PipelineState::CBuffer &cb = + resize_and_add(spaces[p.Constants.RegisterSpace].cbuffers, p.Constants.ShaderRegister); + cb.Immediate = true; + cb.RootElement = (uint32_t)rootEl; + + if(rootEl < rootSig.sigelems.size()) + { + const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; + if(e.type == eRootCBV) + { + ID3D12Resource *res = rm->GetCurrentAs(e.id); + + cb.Buffer = rm->GetOriginalID(e.id); + cb.Offset = e.offset; + cb.ByteSize = uint32_t(res->GetDesc().Width - cb.Offset); + } + } + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV) + { + D3D12PipelineState::ResourceView &view = + resize_and_add(spaces[p.Constants.RegisterSpace].srvs, p.Constants.ShaderRegister); + view.Immediate = true; + view.RootElement = (uint32_t)rootEl; + + if(rootEl < rootSig.sigelems.size()) + { + const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; + if(e.type == eRootSRV) + { + ID3D12Resource *res = rm->GetCurrentAs(e.id); + + // parameters from resource/view + view.Resource = rm->GetOriginalID(e.id); + view.Type = ToStr::Get(D3D12_SRV_DIMENSION_BUFFER); + view.Format = MakeResourceFormat(DXGI_FORMAT_R32_UINT); + + view.ElementSize = sizeof(uint32_t); + view.FirstElement = e.offset / sizeof(uint32_t); + view.NumElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); + } + } + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV) + { + D3D12PipelineState::ResourceView &view = + resize_and_add(spaces[p.Constants.RegisterSpace].uavs, p.Constants.ShaderRegister); + view.Immediate = true; + view.RootElement = (uint32_t)rootEl; + + if(rootEl < rootSig.sigelems.size()) + { + const D3D12RenderState::SignatureElement &e = rootSig.sigelems[rootEl]; + if(e.type == eRootUAV) + { + ID3D12Resource *res = rm->GetCurrentAs(e.id); + + // parameters from resource/view + view.Resource = rm->GetOriginalID(e.id); + view.Type = ToStr::Get(D3D12_UAV_DIMENSION_BUFFER); + view.Format = MakeResourceFormat(DXGI_FORMAT_R32_UINT); + + view.ElementSize = sizeof(uint32_t); + view.FirstElement = e.offset / sizeof(uint32_t); + view.NumElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); + } + } + } + else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE) + { + const D3D12RenderState::SignatureElement *e = NULL; + WrappedID3D12DescriptorHeap *heap = NULL; + + if(rootEl < rootSig.sigelems.size() && rootSig.sigelems[rootEl].type == eRootTable) + { + e = &rootSig.sigelems[rootEl]; + + heap = rm->GetCurrentAs(e->id); + } + + UINT prevTableOffset = 0; + + for(size_t r = 0; r < p.ranges.size(); r++) + { + const D3D12_DESCRIPTOR_RANGE &range = p.ranges[r]; + + UINT shaderReg = range.BaseShaderRegister; + UINT regSpace = range.RegisterSpace; + + D3D12Descriptor *desc = NULL; + + UINT offset = range.OffsetInDescriptorsFromTableStart; + + if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) + offset = prevTableOffset; + + if(heap) + { + desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr; + desc += e->offset; + desc += offset; + } + + prevTableOffset = offset + range.NumDescriptors; + + if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].samplers.size()) + spaces[regSpace].samplers.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, shaderReg++) + { + D3D12PipelineState::Sampler &samp = spaces[regSpace].samplers[shaderReg]; + samp.Immediate = false; + samp.RootElement = (uint32_t)rootEl; + + if(desc) + { + D3D12_SAMPLER_DESC &sampDesc = desc->samp.desc; + + samp.AddressU = ToStr::Get(sampDesc.AddressU); + samp.AddressV = ToStr::Get(sampDesc.AddressV); + samp.AddressW = ToStr::Get(sampDesc.AddressW); + + memcpy(samp.BorderColor, sampDesc.BorderColor, sizeof(FLOAT) * 4); + + samp.Comparison = ToStr::Get(sampDesc.ComparisonFunc); + samp.Filter = ToStr::Get(sampDesc.Filter); + samp.MaxAniso = 0; + if(sampDesc.Filter == D3D12_FILTER_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_COMPARISON_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MINIMUM_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MAXIMUM_ANISOTROPIC) + samp.MaxAniso = sampDesc.MaxAnisotropy; + samp.MaxLOD = sampDesc.MaxLOD; + samp.MinLOD = sampDesc.MinLOD; + samp.MipLODBias = sampDesc.MipLODBias; + samp.UseComparison = (sampDesc.Filter >= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT && + sampDesc.Filter <= D3D12_FILTER_COMPARISON_ANISOTROPIC); + samp.UseBorder = (sampDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER); + + desc++; + } + } + } + else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].cbuffers.size()) + spaces[regSpace].cbuffers.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, shaderReg++) + { + D3D12PipelineState::CBuffer &cb = spaces[regSpace].cbuffers[shaderReg]; + cb.Immediate = false; + cb.RootElement = (uint32_t)rootEl; + + if(desc) + { + WrappedID3D12Resource::GetResIDFromAddr(desc->nonsamp.cbv.BufferLocation, cb.Buffer, + cb.Offset); + cb.Buffer = rm->GetOriginalID(cb.Buffer); + cb.ByteSize = desc->nonsamp.cbv.SizeInBytes; + + desc++; + } + } + } + else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].srvs.size()) + spaces[regSpace].srvs.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, shaderReg++) + { + D3D12PipelineState::ResourceView &view = spaces[regSpace].srvs[shaderReg]; + view.Immediate = false; + view.RootElement = (uint32_t)rootEl; + + if(desc) + { + FillResourceView(view, desc); + + desc++; + } + } + } + else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) + { + UINT maxReg = shaderReg + range.NumDescriptors - 1; + if(maxReg >= spaces[regSpace].uavs.size()) + spaces[regSpace].uavs.resize(maxReg + 1); + + for(UINT i = 0; i < range.NumDescriptors; i++, shaderReg++) + { + D3D12PipelineState::ResourceView &view = spaces[regSpace].uavs[shaderReg]; + view.Immediate = false; + view.RootElement = (uint32_t)rootEl; + + if(desc) + { + FillResourceView(view, desc); + + desc++; + } + } + } + } + } + } + + for(size_t i = 0; i < sig->sig.samplers.size(); i++) + { + D3D12_STATIC_SAMPLER_DESC &sampDesc = sig->sig.samplers[i]; + + if(sampDesc.ShaderVisibility != D3D12_SHADER_VISIBILITY_ALL && + sampDesc.ShaderVisibility != visibility) + continue; + + D3D12PipelineState::Sampler &samp = + resize_and_add(spaces[sampDesc.RegisterSpace].samplers, sampDesc.ShaderRegister); + samp.Immediate = true; + samp.RootElement = (uint32_t)i; + + samp.AddressU = ToStr::Get(sampDesc.AddressU); + samp.AddressV = ToStr::Get(sampDesc.AddressV); + samp.AddressW = ToStr::Get(sampDesc.AddressW); + + if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK) + { + samp.BorderColor[0] = 0.0f; + samp.BorderColor[1] = 0.0f; + samp.BorderColor[2] = 0.0f; + samp.BorderColor[3] = 0.0f; + } + else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK) + { + samp.BorderColor[0] = 0.0f; + samp.BorderColor[1] = 0.0f; + samp.BorderColor[2] = 0.0f; + samp.BorderColor[3] = 1.0f; + } + else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE) + { + samp.BorderColor[0] = 1.0f; + samp.BorderColor[1] = 1.0f; + samp.BorderColor[2] = 1.0f; + samp.BorderColor[3] = 1.0f; + } + else + { + RDCERR("Unexpected static border colour: %u", sampDesc.BorderColor); + } + + samp.Comparison = ToStr::Get(sampDesc.ComparisonFunc); + samp.Filter = ToStr::Get(sampDesc.Filter); + samp.MaxAniso = 0; + if(sampDesc.Filter == D3D12_FILTER_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_COMPARISON_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MINIMUM_ANISOTROPIC || + sampDesc.Filter == D3D12_FILTER_MAXIMUM_ANISOTROPIC) + samp.MaxAniso = sampDesc.MaxAnisotropy; + samp.MaxLOD = sampDesc.MaxLOD; + samp.MinLOD = sampDesc.MinLOD; + samp.MipLODBias = sampDesc.MipLODBias; + samp.UseComparison = (sampDesc.Filter >= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT && + sampDesc.Filter <= D3D12_FILTER_COMPARISON_ANISOTROPIC); + samp.UseBorder = (sampDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER || + sampDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER); + } + + for(uint32_t i = 0; i < sig->sig.numSpaces; i++) + { + dstSpaces[i].ConstantBuffers = spaces[i].cbuffers; + dstSpaces[i].Samplers = spaces[i].samplers; + dstSpaces[i].SRVs = spaces[i].srvs; + dstSpaces[i].UAVs = spaces[i].uavs; + } + + SAFE_DELETE_ARRAY(spaces); +} + void D3D12Replay::MakePipelineState() { const D3D12RenderState &rs = m_pDevice->GetQueue()->GetCommandData()->m_RenderState; @@ -560,8 +896,6 @@ void D3D12Replay::MakePipelineState() // Shaders ///////////////////////////////////////////////// - const D3D12RenderState::RootSignature *rootSig = NULL; - if(pipe && pipe->IsCompute()) { WrappedID3D12PipelineState::ShaderEntry *sh = @@ -571,7 +905,9 @@ void D3D12Replay::MakePipelineState() state.m_CS.stage = eShaderStage_Compute; state.m_CS.BindpointMapping = sh->GetMapping(); - rootSig = &rs.compute; + state.rootSig = rm->GetOriginalID(rs.compute.rootsig); + + FillRegisterSpaces(rs.compute, state.m_CS.Spaces, D3D12_SHADER_VISIBILITY_ALL); } else if(pipe) { @@ -581,6 +917,10 @@ void D3D12Replay::MakePipelineState() D3D12_SHADER_BYTECODE *srcArr[] = {&pipe->graphics->VS, &pipe->graphics->HS, &pipe->graphics->DS, &pipe->graphics->GS, &pipe->graphics->PS}; + D3D12_SHADER_VISIBILITY visibility[] = { + D3D12_SHADER_VISIBILITY_VERTEX, D3D12_SHADER_VISIBILITY_HULL, D3D12_SHADER_VISIBILITY_DOMAIN, + D3D12_SHADER_VISIBILITY_GEOMETRY, D3D12_SHADER_VISIBILITY_PIXEL}; + for(size_t stage = 0; stage < 5; stage++) { D3D12PipelineState::ShaderStage &dst = *dstArr[stage]; @@ -596,284 +936,11 @@ void D3D12Replay::MakePipelineState() dst.Shader = sh->GetResourceID(); dst.BindpointMapping = sh->GetMapping(); } + + FillRegisterSpaces(rs.graphics, dst.Spaces, visibility[stage]); } - rootSig = &rs.graphics; - } - - if(rootSig) - { - state.m_RootSig.obj = rm->GetOriginalID(rootSig->rootsig); - - WrappedID3D12RootSignature *sig = - m_pDevice->GetResourceManager()->GetCurrentAs(rootSig->rootsig); - - struct Space - { - vector cbuffers; - vector samplers; - vector srvs; - vector uavs; - }; - - Space *spaces = new Space[sig->sig.numSpaces]; - create_array_uninit(state.m_RootSig.Spaces, sig->sig.numSpaces); - - for(size_t rootEl = 0; rootEl < RDCMIN(sig->sig.params.size(), rootSig->sigelems.size()); rootEl++) - { - const D3D12RenderState::SignatureElement &e = rootSig->sigelems[rootEl]; - const D3D12RootSignatureParameter &p = sig->sig.params[rootEl]; - - if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS && e.type == eRootConst) - { - D3D12PipelineState::CBuffer &cb = - resize_and_add(spaces[p.Constants.RegisterSpace].cbuffers, p.Constants.ShaderRegister); - cb.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - cb.Immediate = true; - cb.RootElement = (uint32_t)rootEl; - cb.ByteSize = uint32_t(sizeof(uint32_t) * p.Constants.Num32BitValues); - - create_array_init(cb.RootValues, e.constants.size(), &e.constants[0]); - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV && e.type == eRootCBV) - { - D3D12PipelineState::CBuffer &cb = - resize_and_add(spaces[p.Constants.RegisterSpace].cbuffers, p.Constants.ShaderRegister); - cb.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - cb.Immediate = true; - cb.RootElement = (uint32_t)rootEl; - - ID3D12Resource *res = rm->GetCurrentAs(e.id); - - cb.Buffer = rm->GetOriginalID(e.id); - cb.Offset = e.offset; - cb.ByteSize = uint32_t(res->GetDesc().Width - cb.Offset); - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV && e.type == eRootSRV) - { - D3D12PipelineState::ResourceView &view = - resize_and_add(spaces[p.Constants.RegisterSpace].srvs, p.Constants.ShaderRegister); - view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - view.Immediate = true; - view.RootElement = (uint32_t)rootEl; - - ID3D12Resource *res = rm->GetCurrentAs(e.id); - - // parameters from resource/view - view.Resource = rm->GetOriginalID(e.id); - view.Type = ToStr::Get(D3D12_SRV_DIMENSION_BUFFER); - view.Format = MakeResourceFormat(DXGI_FORMAT_R32_UINT); - - view.ElementSize = sizeof(uint32_t); - view.FirstElement = e.offset / sizeof(uint32_t); - view.NumElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV && e.type == eRootUAV) - { - D3D12PipelineState::ResourceView &view = - resize_and_add(spaces[p.Constants.RegisterSpace].uavs, p.Constants.ShaderRegister); - view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - view.Immediate = true; - view.RootElement = (uint32_t)rootEl; - - ID3D12Resource *res = rm->GetCurrentAs(e.id); - - // parameters from resource/view - view.Resource = rm->GetOriginalID(e.id); - view.Type = ToStr::Get(D3D12_UAV_DIMENSION_BUFFER); - view.Format = MakeResourceFormat(DXGI_FORMAT_R32_UINT); - - view.ElementSize = sizeof(uint32_t); - view.FirstElement = e.offset / sizeof(uint32_t); - view.NumElements = uint32_t((res->GetDesc().Width - e.offset) / sizeof(uint32_t)); - } - else if(p.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && e.type == eRootTable) - { - WrappedID3D12DescriptorHeap *heap = rm->GetCurrentAs(e.id); - - UINT prevTableOffset = 0; - - for(size_t r = 0; r < p.ranges.size(); r++) - { - const D3D12_DESCRIPTOR_RANGE &range = p.ranges[r]; - - UINT shaderReg = range.BaseShaderRegister; - UINT regSpace = range.RegisterSpace; - - D3D12Descriptor *desc = (D3D12Descriptor *)heap->GetCPUDescriptorHandleForHeapStart().ptr; - - desc += e.offset; - - UINT offset = range.OffsetInDescriptorsFromTableStart; - - if(range.OffsetInDescriptorsFromTableStart == D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND) - offset = prevTableOffset; - - desc += offset; - - prevTableOffset = offset + range.NumDescriptors; - - if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER) - { - UINT maxReg = shaderReg + range.NumDescriptors - 1; - if(maxReg >= spaces[regSpace].samplers.size()) - spaces[regSpace].samplers.resize(maxReg + 1); - - for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) - { - D3D12PipelineState::Sampler &samp = spaces[regSpace].samplers[shaderReg]; - samp.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - samp.Immediate = false; - samp.RootElement = (uint32_t)rootEl; - - D3D12_SAMPLER_DESC &sampDesc = desc->samp.desc; - - samp.AddressU = ToStr::Get(sampDesc.AddressU); - samp.AddressV = ToStr::Get(sampDesc.AddressV); - samp.AddressW = ToStr::Get(sampDesc.AddressW); - - memcpy(samp.BorderColor, sampDesc.BorderColor, sizeof(FLOAT) * 4); - - samp.Comparison = ToStr::Get(sampDesc.ComparisonFunc); - samp.Filter = ToStr::Get(sampDesc.Filter); - samp.MaxAniso = 0; - if(sampDesc.Filter == D3D12_FILTER_ANISOTROPIC || - sampDesc.Filter == D3D12_FILTER_COMPARISON_ANISOTROPIC || - sampDesc.Filter == D3D12_FILTER_MINIMUM_ANISOTROPIC || - sampDesc.Filter == D3D12_FILTER_MAXIMUM_ANISOTROPIC) - samp.MaxAniso = sampDesc.MaxAnisotropy; - samp.MaxLOD = sampDesc.MaxLOD; - samp.MinLOD = sampDesc.MinLOD; - samp.MipLODBias = sampDesc.MipLODBias; - samp.UseComparison = (sampDesc.Filter >= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT && - sampDesc.Filter <= D3D12_FILTER_COMPARISON_ANISOTROPIC); - samp.UseBorder = (sampDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER || - sampDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER || - sampDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER); - } - } - else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV) - { - UINT maxReg = shaderReg + range.NumDescriptors - 1; - if(maxReg >= spaces[regSpace].cbuffers.size()) - spaces[regSpace].cbuffers.resize(maxReg + 1); - - for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) - { - D3D12PipelineState::CBuffer &cb = spaces[regSpace].cbuffers[shaderReg]; - cb.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - cb.Immediate = false; - cb.RootElement = (uint32_t)rootEl; - - WrappedID3D12Resource::GetResIDFromAddr(desc->nonsamp.cbv.BufferLocation, cb.Buffer, - cb.Offset); - cb.Buffer = rm->GetOriginalID(cb.Buffer); - cb.ByteSize = desc->nonsamp.cbv.SizeInBytes; - } - } - else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV) - { - UINT maxReg = shaderReg + range.NumDescriptors - 1; - if(maxReg >= spaces[regSpace].srvs.size()) - spaces[regSpace].srvs.resize(maxReg + 1); - - for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) - { - D3D12PipelineState::ResourceView &view = spaces[regSpace].srvs[shaderReg]; - view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - view.Immediate = false; - view.RootElement = (uint32_t)rootEl; - - FillResourceView(view, desc); - } - } - else if(range.RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV) - { - UINT maxReg = shaderReg + range.NumDescriptors - 1; - if(maxReg >= spaces[regSpace].uavs.size()) - spaces[regSpace].uavs.resize(maxReg + 1); - - for(UINT i = 0; i < range.NumDescriptors; i++, desc++, shaderReg++) - { - D3D12PipelineState::ResourceView &view = spaces[regSpace].uavs[shaderReg]; - view.VisibilityMask = ConvertVisibility(p.ShaderVisibility); - view.Immediate = false; - view.RootElement = (uint32_t)rootEl; - - FillResourceView(view, desc); - } - } - } - } - } - - for(size_t i = 0; i < sig->sig.samplers.size(); i++) - { - D3D12_STATIC_SAMPLER_DESC &sampDesc = sig->sig.samplers[i]; - - D3D12PipelineState::Sampler &samp = - resize_and_add(spaces[sampDesc.RegisterSpace].samplers, sampDesc.ShaderRegister); - samp.VisibilityMask = ConvertVisibility(sampDesc.ShaderVisibility); - samp.Immediate = true; - samp.RootElement = (uint32_t)i; - - samp.AddressU = ToStr::Get(sampDesc.AddressU); - samp.AddressV = ToStr::Get(sampDesc.AddressV); - samp.AddressW = ToStr::Get(sampDesc.AddressW); - - if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK) - { - samp.BorderColor[0] = 0.0f; - samp.BorderColor[1] = 0.0f; - samp.BorderColor[2] = 0.0f; - samp.BorderColor[3] = 0.0f; - } - else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK) - { - samp.BorderColor[0] = 0.0f; - samp.BorderColor[1] = 0.0f; - samp.BorderColor[2] = 0.0f; - samp.BorderColor[3] = 1.0f; - } - else if(sampDesc.BorderColor == D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE) - { - samp.BorderColor[0] = 1.0f; - samp.BorderColor[1] = 1.0f; - samp.BorderColor[2] = 1.0f; - samp.BorderColor[3] = 1.0f; - } - else - { - RDCERR("Unexpected static border colour: %u", sampDesc.BorderColor); - } - - samp.Comparison = ToStr::Get(sampDesc.ComparisonFunc); - samp.Filter = ToStr::Get(sampDesc.Filter); - samp.MaxAniso = 0; - if(sampDesc.Filter == D3D12_FILTER_ANISOTROPIC || - sampDesc.Filter == D3D12_FILTER_COMPARISON_ANISOTROPIC || - sampDesc.Filter == D3D12_FILTER_MINIMUM_ANISOTROPIC || - sampDesc.Filter == D3D12_FILTER_MAXIMUM_ANISOTROPIC) - samp.MaxAniso = sampDesc.MaxAnisotropy; - samp.MaxLOD = sampDesc.MaxLOD; - samp.MinLOD = sampDesc.MinLOD; - samp.MipLODBias = sampDesc.MipLODBias; - samp.UseComparison = (sampDesc.Filter >= D3D12_FILTER_COMPARISON_MIN_MAG_MIP_POINT && - sampDesc.Filter <= D3D12_FILTER_COMPARISON_ANISOTROPIC); - samp.UseBorder = (sampDesc.AddressU == D3D12_TEXTURE_ADDRESS_MODE_BORDER || - sampDesc.AddressV == D3D12_TEXTURE_ADDRESS_MODE_BORDER || - sampDesc.AddressW == D3D12_TEXTURE_ADDRESS_MODE_BORDER); - } - - for(uint32_t i = 0; i < sig->sig.numSpaces; i++) - { - state.m_RootSig.Spaces[i].ConstantBuffers = spaces[i].cbuffers; - state.m_RootSig.Spaces[i].Samplers = spaces[i].samplers; - state.m_RootSig.Spaces[i].SRVs = spaces[i].srvs; - state.m_RootSig.Spaces[i].UAVs = spaces[i].uavs; - } - - SAFE_DELETE_ARRAY(spaces); + state.rootSig = rm->GetOriginalID(rs.graphics.rootsig); } if(pipe && pipe->IsGraphics()) @@ -959,7 +1026,6 @@ void D3D12Replay::MakePipelineState() view.RootElement = (uint32_t)i; view.Immediate = false; - view.VisibilityMask = eStageBits_All; FillResourceView(view, desc); } @@ -976,7 +1042,6 @@ void D3D12Replay::MakePipelineState() view.RootElement = 0; view.Immediate = false; - view.VisibilityMask = eStageBits_All; FillResourceView(view, desc); } diff --git a/renderdoc/driver/d3d12/d3d12_replay.h b/renderdoc/driver/d3d12/d3d12_replay.h index 398e21677..88938101d 100644 --- a/renderdoc/driver/d3d12/d3d12_replay.h +++ b/renderdoc/driver/d3d12/d3d12_replay.h @@ -28,6 +28,7 @@ #include "core/core.h" #include "replay/replay_driver.h" #include "d3d12_common.h" +#include "d3d12_state.h" class WrappedID3D12Device; @@ -165,6 +166,9 @@ public: private: void MakePipelineState(); + void FillRegisterSpaces(const D3D12RenderState::RootSignature &rootSig, + rdctype::array &spaces, + D3D12_SHADER_VISIBILITY visibility); void FillResourceView(D3D12PipelineState::ResourceView &view, D3D12Descriptor *desc); bool m_Proxy; diff --git a/renderdocui/Code/CommonPipelineState.cs b/renderdocui/Code/CommonPipelineState.cs index bc1d4eb41..792f38730 100644 --- a/renderdocui/Code/CommonPipelineState.cs +++ b/renderdocui/Code/CommonPipelineState.cs @@ -970,8 +970,8 @@ namespace renderdocui.Code { var bind = s.BindpointMapping.ConstantBlocks[s.ShaderDetails.ConstantBlocks[BufIdx].bindPoint]; - if (bind.bindset >= m_D3D12.m_RootSig.Spaces.Length || - bind.bind >= m_D3D12.m_RootSig.Spaces[bind.bindset].ConstantBuffers.Length) + if (bind.bindset >= s.Spaces.Length || + bind.bind >= s.Spaces[bind.bindset].ConstantBuffers.Length) { buf = ResourceId.Null; ByteOffset = 0; @@ -979,7 +979,7 @@ namespace renderdocui.Code return; } - var descriptor = m_D3D12.m_RootSig.Spaces[bind.bindset].ConstantBuffers[bind.bind]; + var descriptor = s.Spaces[bind.bindset].ConstantBuffers[bind.bind]; buf = descriptor.Buffer; ByteOffset = descriptor.Offset; @@ -1104,27 +1104,33 @@ namespace renderdocui.Code } else if (IsLogD3D12) { - ShaderStageBits mask = (ShaderStageBits)(1 << (int)stage); + D3D12PipelineState.ShaderStage s = null; - for (int space = 0; space < m_D3D12.m_RootSig.Spaces.Length; space++) + switch (stage) { - for (int reg = 0; reg < m_D3D12.m_RootSig.Spaces[space].SRVs.Length; reg++) + case ShaderStageType.Vertex: s = m_D3D12.m_VS; break; + case ShaderStageType.Domain: s = m_D3D12.m_DS; break; + case ShaderStageType.Hull: s = m_D3D12.m_HS; break; + case ShaderStageType.Geometry: s = m_D3D12.m_GS; break; + case ShaderStageType.Pixel: s = m_D3D12.m_PS; break; + case ShaderStageType.Compute: s = m_D3D12.m_CS; break; + } + + for (int space = 0; space < s.Spaces.Length; space++) + { + for (int reg = 0; reg < s.Spaces[space].SRVs.Length; reg++) { - var bind = m_D3D12.m_RootSig.Spaces[space].SRVs[reg]; + var bind = s.Spaces[space].SRVs[reg]; + var key = new BindpointMap(space, reg); + var val = new BoundResource(); - if ((bind.VisibilityMask & mask) == mask) - { - var key = new BindpointMap(space, reg); - var val = new BoundResource[1]; + val = new BoundResource(); + val.Id = bind.Resource; + val.HighestMip = (int)bind.HighestMip; + val.FirstSlice = (int)bind.FirstArraySlice; + val.typeHint = bind.Format.compType; - val[0] = new BoundResource(); - val[0].Id = bind.Resource; - val[0].HighestMip = (int)bind.HighestMip; - val[0].FirstSlice = (int)bind.FirstArraySlice; - val[0].typeHint = bind.Format.compType; - - ret.Add(key, val); - } + ret.Add(key, new BoundResource[] { val }); } } @@ -1235,27 +1241,33 @@ namespace renderdocui.Code } else if (IsLogD3D12) { - ShaderStageBits mask = (ShaderStageBits)(1 << (int)stage); + D3D12PipelineState.ShaderStage s = null; - for (int space = 0; space < m_D3D12.m_RootSig.Spaces.Length; space++) + switch (stage) { - for (int reg = 0; reg < m_D3D12.m_RootSig.Spaces[space].UAVs.Length; reg++) + case ShaderStageType.Vertex: s = m_D3D12.m_VS; break; + case ShaderStageType.Domain: s = m_D3D12.m_DS; break; + case ShaderStageType.Hull: s = m_D3D12.m_HS; break; + case ShaderStageType.Geometry: s = m_D3D12.m_GS; break; + case ShaderStageType.Pixel: s = m_D3D12.m_PS; break; + case ShaderStageType.Compute: s = m_D3D12.m_CS; break; + } + + for (int space = 0; space < s.Spaces.Length; space++) + { + for (int reg = 0; reg < s.Spaces[space].UAVs.Length; reg++) { - var bind = m_D3D12.m_RootSig.Spaces[space].UAVs[reg]; + var bind = s.Spaces[space].UAVs[reg]; + var key = new BindpointMap(space, reg); + var val = new BoundResource(); - if ((bind.VisibilityMask & mask) == mask) - { - var key = new BindpointMap(space, reg); - var val = new BoundResource[1]; + val = new BoundResource(); + val.Id = bind.Resource; + val.HighestMip = (int)bind.HighestMip; + val.FirstSlice = (int)bind.FirstArraySlice; + val.typeHint = bind.Format.compType; - val[0] = new BoundResource(); - val[0].Id = bind.Resource; - val[0].HighestMip = (int)bind.HighestMip; - val[0].FirstSlice = (int)bind.FirstArraySlice; - val[0].typeHint = bind.Format.compType; - - ret.Add(key, val); - } + ret.Add(key, new BoundResource[] { val }); } } diff --git a/renderdocui/Interop/D3D12PipelineState.cs b/renderdocui/Interop/D3D12PipelineState.cs index 109c55332..ce046d886 100644 --- a/renderdocui/Interop/D3D12PipelineState.cs +++ b/renderdocui/Interop/D3D12PipelineState.cs @@ -37,6 +37,8 @@ namespace renderdoc [CustomMarshalAs(CustomUnmanagedType.UTF8TemplatedString)] public string PipelineName; + public ResourceId rootSig; + [StructLayout(LayoutKind.Sequential)] public class InputAssembler { @@ -82,35 +84,9 @@ namespace renderdoc [CustomMarshalAs(CustomUnmanagedType.CustomClass)] public InputAssembler m_IA; - [StructLayout(LayoutKind.Sequential)] - public class ShaderStage - { - private void PostMarshal() - { - if (_ptr_ShaderDetails != IntPtr.Zero) - ShaderDetails = (ShaderReflection)CustomMarshal.PtrToStructure(_ptr_ShaderDetails, typeof(ShaderReflection), false); - else - ShaderDetails = null; - - _ptr_ShaderDetails = IntPtr.Zero; - } - - public ResourceId Shader; - private IntPtr _ptr_ShaderDetails; - [CustomMarshalAs(CustomUnmanagedType.Skip)] - public ShaderReflection ShaderDetails; - [CustomMarshalAs(CustomUnmanagedType.CustomClass)] - public ShaderBindpointMapping BindpointMapping; - - public ShaderStageType stage; - }; - [CustomMarshalAs(CustomUnmanagedType.CustomClass)] - public ShaderStage m_VS, m_HS, m_DS, m_GS, m_PS, m_CS; - [StructLayout(LayoutKind.Sequential)] public class ResourceView { - public ShaderStageBits VisibilityMask; public bool Immediate; public UInt32 RootElement; @@ -146,7 +122,6 @@ namespace renderdoc [StructLayout(LayoutKind.Sequential)] public class Sampler { - public ShaderStageBits VisibilityMask; public bool Immediate; public UInt32 RootElement; @@ -169,7 +144,6 @@ namespace renderdoc [StructLayout(LayoutKind.Sequential)] public class CBuffer { - public ShaderStageBits VisibilityMask; public bool Immediate; public UInt32 RootElement; @@ -182,9 +156,26 @@ namespace renderdoc }; [StructLayout(LayoutKind.Sequential)] - public class RootSignature + public class ShaderStage { - public ResourceId Obj; + private void PostMarshal() + { + if (_ptr_ShaderDetails != IntPtr.Zero) + ShaderDetails = (ShaderReflection)CustomMarshal.PtrToStructure(_ptr_ShaderDetails, typeof(ShaderReflection), false); + else + ShaderDetails = null; + + _ptr_ShaderDetails = IntPtr.Zero; + } + + public ResourceId Shader; + private IntPtr _ptr_ShaderDetails; + [CustomMarshalAs(CustomUnmanagedType.Skip)] + public ShaderReflection ShaderDetails; + [CustomMarshalAs(CustomUnmanagedType.CustomClass)] + public ShaderBindpointMapping BindpointMapping; + + public ShaderStageType stage; [StructLayout(LayoutKind.Sequential)] public class RegisterSpace @@ -203,7 +194,7 @@ namespace renderdoc public RegisterSpace[] Spaces; }; [CustomMarshalAs(CustomUnmanagedType.CustomClass)] - public RootSignature m_RootSig; + public ShaderStage m_VS, m_HS, m_DS, m_GS, m_PS, m_CS; [StructLayout(LayoutKind.Sequential)] public class Streamout diff --git a/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs b/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs index d1f4b77c7..56b27e900 100644 --- a/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs +++ b/renderdocui/Windows/PipelineState/D3D12PipelineStateViewer.cs @@ -96,6 +96,28 @@ namespace renderdocui.Windows.PipelineState public ShaderResource res; }; + private class CBufTag + { + public CBufTag(uint slot) + { + idx = slot; + space = 0; + reg = 0; + } + + public CBufTag(int s, int r) + { + idx = uint.MaxValue; + space = s; + reg = r; + } + + public uint idx; + + public int space; + public int reg; + }; + public D3D12PipelineStateViewer(Core core, DockContent c) { InitializeComponent(); @@ -256,7 +278,7 @@ namespace renderdocui.Windows.PipelineState m_ViewDetailNodes.Add(node); } - private bool HasImportantViewParams(D3D12PipelineState.ResourceView view, FetchTexture tex, ShaderStageBits stageMask) + private bool HasImportantViewParams(D3D12PipelineState.ResourceView view, FetchTexture tex) { // we don't count 'upgrade typeless to typed' as important, we just display the typed format // in the row since there's no real hidden important information there. The formats can't be @@ -273,20 +295,14 @@ namespace renderdocui.Windows.PipelineState if (view.Format.compType != FormatComponentType.None && view.Format != tex.format) return true; - if (!view.VisibilityMask.HasFlag(stageMask)) - return true; - return false; } - private bool HasImportantViewParams(D3D12PipelineState.ResourceView view, FetchBuffer buf, ShaderStageBits stageMask) + private bool HasImportantViewParams(D3D12PipelineState.ResourceView view, FetchBuffer buf) { if (view.FirstElement > 0 || view.NumElements*view.ElementSize < buf.length) return true; - if (!view.VisibilityMask.HasFlag(stageMask)) - return true; - return false; } @@ -300,40 +316,45 @@ namespace renderdocui.Windows.PipelineState cbuffers.Nodes.Clear(); } - private void AddResourceRow(TreelistView.TreeListView list, ShaderStageBits stageMask, BindpointMap bind, ShaderResource shaderInput, bool uav) + private void AddResourceRow(D3D12PipelineState.ShaderStage stage, + TreelistView.TreeListView list, + int space, int reg, bool uav) { D3D12PipelineState state = m_Core.CurD3D12PipelineState; FetchTexture[] texs = m_Core.CurTextures; FetchBuffer[] bufs = m_Core.CurBuffers; - string rootel = "--"; + BindpointMap bind = null; + ShaderResource shaderInput = null; - D3D12PipelineState.ResourceView r = null; + D3D12PipelineState.ResourceView r = uav ? stage.Spaces[space].UAVs[reg] : stage.Spaces[space].SRVs[reg]; - if (uav) + // consider this register to not exist - it's in a gap defined by sparse root signature elements + if (r.RootElement == uint.MaxValue) + return; + + if (stage.BindpointMapping != null && stage.ShaderDetails != null) { - if (bind.bindset < state.m_RootSig.Spaces.Length && - bind.bind < state.m_RootSig.Spaces[bind.bindset].UAVs.Length) + BindpointMap[] binds = uav ? stage.BindpointMapping.ReadWriteResources : stage.BindpointMapping.ReadOnlyResources; + ShaderResource[] resources = uav ? stage.ShaderDetails.ReadWriteResources : stage.ShaderDetails.ReadOnlyResources; + for (int i=0; i < binds.Length; i++) { - r = state.m_RootSig.Spaces[bind.bindset].UAVs[bind.bind]; - } - } - else - { - if (bind.bindset < state.m_RootSig.Spaces.Length && - bind.bind < state.m_RootSig.Spaces[bind.bindset].SRVs.Length) - { - r = state.m_RootSig.Spaces[bind.bindset].SRVs[bind.bind]; + var b = binds[i]; + var res = resources[i]; + + if (b.bindset == space && b.bind == reg && !res.IsSampler) + { + bind = b; + shaderInput = res; + break; + } } } - if (r != null) - rootel = r.Immediate ? String.Format("#{0} Direct", r.RootElement) : rootel = String.Format("#{0} Table", r.RootElement); + string rootel = r.Immediate ? String.Format("#{0} Direct", r.RootElement) : rootel = String.Format("#{0} Table", r.RootElement); - bool stageVisible = r != null && r.VisibilityMask.HasFlag(stageMask); - - bool filledSlot = (r != null && r.Resource != ResourceId.Null && stageVisible); - bool usedSlot = bind.used; + bool filledSlot = r.Resource != ResourceId.Null; + bool usedSlot = (bind != null && bind.used); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not @@ -341,7 +362,7 @@ namespace renderdocui.Windows.PipelineState (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { - string regname = bind.bind.ToString(); + string regname = reg.ToString(); if (shaderInput != null && shaderInput.name.Length > 0) regname += ": " + shaderInput.name; @@ -394,7 +415,7 @@ namespace renderdocui.Windows.PipelineState tag = new ViewTexTag(r, texs[t], true, shaderInput); - if (HasImportantViewParams(r, texs[t], stageMask)) + if (HasImportantViewParams(r, texs[t])) viewDetails = true; } } @@ -445,13 +466,13 @@ namespace renderdocui.Windows.PipelineState tag = new ViewBufTag(r, bufs[t], true, shaderInput); - if (HasImportantViewParams(r, bufs[t], stageMask)) + if (HasImportantViewParams(r, bufs[t])) viewDetails = true; } } } - var node = list.Nodes.Add(new object[] { rootel, bind.bindset, regname, name, typename, w, h, d, a, format }); + var node = list.Nodes.Add(new object[] { rootel, space, regname, name, typename, w, h, d, a, format }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; @@ -479,8 +500,6 @@ namespace renderdocui.Windows.PipelineState ShaderReflection shaderDetails = stage.ShaderDetails; ShaderBindpointMapping bindpointMapping = stage.BindpointMapping; - ShaderStageBits stageMask = (ShaderStageBits)(1 << (int)stage.stage); - if (stage.Shader == ResourceId.Null) shader.Text = "Unbound"; else if (state.customName) @@ -506,14 +525,11 @@ namespace renderdocui.Windows.PipelineState vs = resources.VScrollValue(); resources.BeginUpdate(); resources.Nodes.Clear(); - if (shaderDetails != null) + for (int space = 0; space < stage.Spaces.Length; space++) { - for (int i = 0; i < shaderDetails.ReadOnlyResources.Length; i++) + for (int reg = 0; reg < stage.Spaces[space].SRVs.Length; reg++) { - if (shaderDetails.ReadOnlyResources[i].IsSampler) - continue; - - AddResourceRow(resources, stageMask, bindpointMapping.ReadOnlyResources[i], shaderDetails.ReadOnlyResources[i], false); + AddResourceRow(stage, resources, space, reg, false); } } resources.EndUpdate(); @@ -523,11 +539,11 @@ namespace renderdocui.Windows.PipelineState vs = uavs.VScrollValue(); uavs.BeginUpdate(); uavs.Nodes.Clear(); - if (shaderDetails != null) + for (int space = 0; space < stage.Spaces.Length; space++) { - for (int i = 0; i < shaderDetails.ReadWriteResources.Length; i++) + for (int reg = 0; reg < stage.Spaces[space].UAVs.Length; reg++) { - AddResourceRow(resources, stageMask, bindpointMapping.ReadWriteResources[i], shaderDetails.ReadWriteResources[i], true); + AddResourceRow(stage, resources, space, reg, true); } } uavs.EndUpdate(); @@ -537,32 +553,39 @@ namespace renderdocui.Windows.PipelineState vs = samplers.VScrollValue(); samplers.BeginUpdate(); samplers.Nodes.Clear(); - if (shaderDetails != null) + for (int space = 0; space < stage.Spaces.Length; space++) { - for(int i=0; i < shaderDetails.ReadOnlyResources.Length; i++) + for (int reg = 0; reg < stage.Spaces[space].Samplers.Length; reg++) { - ShaderResource shaderInput = shaderDetails.ReadOnlyResources[i]; + D3D12PipelineState.Sampler s = stage.Spaces[space].Samplers[reg]; - if (!shaderInput.IsSampler) + // consider this register to not exist - it's in a gap defined by sparse root signature elements + if (s.RootElement == uint.MaxValue) continue; - BindpointMap bind = bindpointMapping.ReadOnlyResources[i]; + BindpointMap bind = null; + ShaderResource shaderInput = null; - D3D12PipelineState.Sampler s = null; - - string rootel = "--"; - - if (bind.bindset < state.m_RootSig.Spaces.Length && - bind.bind < state.m_RootSig.Spaces[bind.bindset].Samplers.Length) + if (stage.BindpointMapping != null && stage.ShaderDetails != null) { - s = state.m_RootSig.Spaces[bind.bindset].Samplers[bind.bind]; - rootel = s.Immediate ? String.Format("#{0} Static", s.RootElement) : String.Format("#{0} Table", s.RootElement); + for (int i = 0; i < stage.BindpointMapping.ReadOnlyResources.Length; i++) + { + var b = stage.BindpointMapping.ReadOnlyResources[i]; + var res = stage.ShaderDetails.ReadOnlyResources[i]; + + if (b.bindset == space && b.bind == reg && res.IsSampler) + { + bind = b; + shaderInput = res; + break; + } + } } - bool stageVisible = s != null && s.VisibilityMask.HasFlag(stageMask); + string rootel = s.Immediate ? String.Format("#{0} Static", s.RootElement) : String.Format("#{0} Table", s.RootElement); - bool filledSlot = (s != null && s.AddressU.Length > 0 && stageVisible); - bool usedSlot = bind.used; + bool filledSlot = (s.AddressU.Length > 0); + bool usedSlot = (bind != null && bind.used); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not @@ -570,7 +593,7 @@ namespace renderdocui.Windows.PipelineState (showEmpty.Checked && !filledSlot) // it's empty, and we have "show empty" ) { - string regname = bind.bind.ToString(); + string regname = reg.ToString(); if (shaderInput != null && shaderInput.name.Length > 0) regname += ": " + shaderInput.name; @@ -639,10 +662,7 @@ namespace renderdocui.Windows.PipelineState lodbias = s.MipLODBias; } - if (!stageVisible) - filter += " (Not visible)"; - - var node = samplers.Nodes.Add(new object[] { rootel, bind.bindset, regname, addressing, + var node = samplers.Nodes.Add(new object[] { rootel, space, regname, addressing, filter, lodclamp, lodbias.ToString() }); if (!filledSlot) @@ -660,40 +680,57 @@ namespace renderdocui.Windows.PipelineState vs = cbuffers.VScrollValue(); cbuffers.BeginUpdate(); cbuffers.Nodes.Clear(); - if(shaderDetails != null) + for (int space = 0; space < stage.Spaces.Length; space++) { - for (int i = 0; i < shaderDetails.ConstantBlocks.Length; i++) + for (int reg = 0; reg < stage.Spaces[space].ConstantBuffers.Length; reg++) { - ConstantBlock shaderCBuf = shaderDetails.ConstantBlocks[i]; + D3D12PipelineState.CBuffer b = stage.Spaces[space].ConstantBuffers[reg]; - BindpointMap bind = bindpointMapping.ConstantBlocks[i]; + // consider this register to not exist - it's in a gap defined by sparse root signature elements + if (b.RootElement == uint.MaxValue) + continue; - D3D12PipelineState.CBuffer b = null; + BindpointMap bind = null; + ConstantBlock shaderCBuf = null; - string rootel = "--"; + object tag = null; - if (bind.bindset < state.m_RootSig.Spaces.Length && - bind.bind < state.m_RootSig.Spaces[bind.bindset].ConstantBuffers.Length) + if (stage.BindpointMapping != null && stage.ShaderDetails != null) { - b = state.m_RootSig.Spaces[bind.bindset].ConstantBuffers[bind.bind]; + for (int i = 0; i < stage.BindpointMapping.ConstantBlocks.Length; i++) + { + var bd = stage.BindpointMapping.ConstantBlocks[i]; + var res = stage.ShaderDetails.ConstantBlocks[i]; - if (b.Immediate) - { - if (b.RootValues.Length > 0) - rootel = String.Format("#{0} Consts", b.RootElement); - else - rootel = String.Format("#{0} Direct", b.RootElement); - } - else - { - rootel = String.Format("#{0} Table", b.RootElement); + if (bd.bindset == space && bd.bind == reg) + { + bind = bd; + shaderCBuf = res; + tag = new CBufTag((uint)i); + break; + } } } - bool stageVisible = b != null && b.VisibilityMask.HasFlag(stageMask); + if(tag == null) + tag = new CBufTag(space, reg); - bool filledSlot = (b != null && b.Buffer != ResourceId.Null && stageVisible); - bool usedSlot = bind.used; + string rootel; + + if (b.Immediate) + { + if (b.RootValues.Length > 0) + rootel = String.Format("#{0} Consts", b.RootElement); + else + rootel = String.Format("#{0} Direct", b.RootElement); + } + else + { + rootel = String.Format("#{0} Table", b.RootElement); + } + + bool filledSlot = (b.Buffer != ResourceId.Null); + bool usedSlot = (bind != null && bind.used); // show if if (usedSlot || // it's referenced by the shader - regardless of empty or not @@ -707,20 +744,23 @@ namespace renderdocui.Windows.PipelineState int numvars = shaderCBuf != null ? shaderCBuf.variables.Length : 0; UInt32 byteSize = shaderCBuf != null ? shaderCBuf.byteSize : 0; + if (b.Immediate && b.RootValues.Length > 0) + byteSize = (UInt32)(b.RootValues.Length * 4); + if (!filledSlot) name = "Empty"; if (b != null) { + offset = b.Offset; + length = b.ByteSize; + for (int t = 0; t < bufs.Length; t++) if (bufs[t].ID == b.Buffer) name = bufs[t].name; - - offset = b.Offset; - length = b.ByteSize; } - string regname = bind.bind.ToString(); + string regname = reg.ToString(); if (shaderCBuf != null && shaderCBuf.name.Length > 0) regname += ": " + shaderCBuf.name; @@ -734,14 +774,11 @@ namespace renderdocui.Windows.PipelineState if (length < byteSize) filledSlot = false; - if (!stageVisible) - name += " (Not visible)"; - - var node = cbuffers.Nodes.Add(new object[] { rootel, bind.bindset, regname, name, offset, sizestr }); + var node = cbuffers.Nodes.Add(new object[] { rootel, space, regname, name, offset, sizestr }); node.Image = global::renderdocui.Properties.Resources.action; node.HoverImage = global::renderdocui.Properties.Resources.action_hover; - node.Tag = (UInt32)i; + node.Tag = tag; if (!filledSlot) EmptyRow(node); @@ -1241,7 +1278,7 @@ namespace renderdocui.Windows.PipelineState format = "Viewed as " + p.Format.ToString(); } - if (HasImportantViewParams(p, texs[t], ShaderStageBits.All)) + if (HasImportantViewParams(p, texs[t])) viewDetails = true; tag = new ViewTexTag(p, texs[t], false, null); @@ -1312,7 +1349,7 @@ namespace renderdocui.Windows.PipelineState format = "Viewed as " + state.m_OM.DepthTarget.Format.ToString(); } - if (HasImportantViewParams(state.m_OM.DepthTarget, texs[t], ShaderStageBits.All)) + if (HasImportantViewParams(state.m_OM.DepthTarget, texs[t])) viewDetails = true; tag = new ViewTexTag(state.m_OM.DepthTarget, texs[t], false, null); @@ -1549,9 +1586,6 @@ namespace renderdocui.Windows.PipelineState text += String.Format("The texture has {0} array slices, the view covers slices {1}-{2}.\n", tex.tex.arraysize, tex.view.FirstArraySlice, tex.view.FirstArraySlice + tex.view.ArraySize); } - - if (!tex.view.VisibilityMask.HasFlag(stageMask)) - text += "Root element not visible at this shader stage.\n"; } else if (buf != null) { @@ -1564,9 +1598,6 @@ namespace renderdocui.Windows.PipelineState buf.view.NumElements, buf.buf.length, buf.buf.length / buf.view.ElementSize); - - if (!buf.view.VisibilityMask.HasFlag(stageMask)) - text += "Root element not visible at this shader stage.\n"; } toolTip.Show(text.TrimEnd(), view, e.Location.X + Cursor.Size.Width, y); @@ -2212,38 +2243,28 @@ namespace renderdocui.Windows.PipelineState sv.Show(m_DockContent.DockPanel); } - private void ShowCBuffer(D3D12PipelineState.ShaderStage stage, UInt32 slot) + private void ShowCBuffer(D3D12PipelineState.ShaderStage stage, CBufTag tag) { - if (stage.ShaderDetails != null && - stage.BindpointMapping != null && - (stage.ShaderDetails.ConstantBlocks.Length <= slot || - stage.ShaderDetails.ConstantBlocks[slot].name.Length == 0) - ) + if (tag.idx == uint.MaxValue) { // unused cbuffer, open regular buffer viewer var viewer = new BufferViewer(m_Core, false); - var bind = stage.BindpointMapping.ConstantBlocks[slot]; - - if (bind.bindset >= m_Core.CurD3D12PipelineState.m_RootSig.Spaces.Length || - bind.bind >= m_Core.CurD3D12PipelineState.m_RootSig.Spaces[bind.bindset].ConstantBuffers.Length) - return; - - var buf = m_Core.CurD3D12PipelineState.m_RootSig.Spaces[bind.bindset].ConstantBuffers[bind.bind]; + var buf = stage.Spaces[tag.space].ConstantBuffers[tag.reg]; viewer.ViewRawBuffer(true, buf.Offset, buf.ByteSize, buf.Buffer); viewer.Show(m_DockContent.DockPanel); return; } - var existing = ConstantBufferPreviewer.Has(stage.stage, slot, 0); + var existing = ConstantBufferPreviewer.Has(stage.stage, tag.idx, 0); if (existing != null) { existing.Show(); return; } - var prev = new ConstantBufferPreviewer(m_Core, stage.stage, slot, 0); + var prev = new ConstantBufferPreviewer(m_Core, stage.stage, tag.idx, 0); prev.ShowDock(m_DockContent.Pane, DockAlignment.Right, 0.3); } @@ -2252,9 +2273,9 @@ namespace renderdocui.Windows.PipelineState { D3D12PipelineState.ShaderStage stage = GetStageForSender(node.OwnerView); - if (stage != null && node.Tag is UInt32) + if (stage != null && node.Tag is CBufTag) { - ShowCBuffer(stage, (UInt32)node.Tag); + ShowCBuffer(stage, (CBufTag)node.Tag); } } @@ -2264,9 +2285,9 @@ namespace renderdocui.Windows.PipelineState object tag = ((DataGridView)sender).Rows[e.RowIndex].Tag; - if (stage != null && tag is UInt32) + if (stage != null && tag is CBufTag) { - ShowCBuffer(stage, (UInt32)tag); + ShowCBuffer(stage, (CBufTag)tag); } }