Divide up register spaces by shader stage (namespacing same as DX11)

This commit is contained in:
baldurk
2016-09-23 11:41:16 +02:00
parent 6fdc883388
commit 06e6677616
6 changed files with 578 additions and 493 deletions
+15 -23
View File
@@ -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<uint32_t> 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<ResourceView> UAVs;
};
rdctype::array<RegisterSpace> Spaces;
} m_RootSig;
} m_VS, m_HS, m_DS, m_GS, m_PS, m_CS;
struct Streamout
{
+346 -281
View File
@@ -476,6 +476,342 @@ void D3D12Replay::FillResourceView(D3D12PipelineState::ResourceView &view, D3D12
}
}
void D3D12Replay::FillRegisterSpaces(
const D3D12RenderState::RootSignature &rootSig,
rdctype::array<D3D12PipelineState::ShaderStage::RegisterSpace> &dstSpaces,
D3D12_SHADER_VISIBILITY visibility)
{
D3D12ResourceManager *rm = m_pDevice->GetResourceManager();
WrappedID3D12RootSignature *sig =
m_pDevice->GetResourceManager()->GetCurrentAs<WrappedID3D12RootSignature>(rootSig.rootsig);
struct Space
{
vector<D3D12PipelineState::CBuffer> cbuffers;
vector<D3D12PipelineState::Sampler> samplers;
vector<D3D12PipelineState::ResourceView> srvs;
vector<D3D12PipelineState::ResourceView> 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<ID3D12Resource>(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<ID3D12Resource>(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<ID3D12Resource>(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<WrappedID3D12DescriptorHeap>(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<WrappedID3D12RootSignature>(rootSig->rootsig);
struct Space
{
vector<D3D12PipelineState::CBuffer> cbuffers;
vector<D3D12PipelineState::Sampler> samplers;
vector<D3D12PipelineState::ResourceView> srvs;
vector<D3D12PipelineState::ResourceView> 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<ID3D12Resource>(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<ID3D12Resource>(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<ID3D12Resource>(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<WrappedID3D12DescriptorHeap>(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);
}
+4
View File
@@ -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<D3D12PipelineState::ShaderStage::RegisterSpace> &spaces,
D3D12_SHADER_VISIBILITY visibility);
void FillResourceView(D3D12PipelineState::ResourceView &view, D3D12Descriptor *desc);
bool m_Proxy;
+47 -35
View File
@@ -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 });
}
}
+22 -31
View File
@@ -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
@@ -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);
}
}