in renderdoc/driver/shaders/dxbc/dxbc_bytecode_ops.cpp [1731:2566]
bool Program::DecodeDecl(uint32_t *&tokenStream, Declaration &retDecl, bool friendlyName)
{
uint32_t *begin = tokenStream;
uint32_t OpcodeToken0 = tokenStream[0];
ToString flags = friendlyName ? ToString::FriendlyNameRegisters : ToString::None;
flags = flags | ToString::IsDecl;
const bool sm51 = (m_Major == 0x5 && m_Minor == 0x1);
OpcodeType op = Opcode::Type.Get(OpcodeToken0);
RDCASSERT(op < NUM_REAL_OPCODES);
if(!IsDeclaration(op))
return false;
retDecl.declaration = op;
if(op == OPCODE_CUSTOMDATA)
{
CustomDataClass customClass = Opcode::CustomClass.Get(OpcodeToken0);
tokenStream++;
// DWORD length including OpcodeToken0 and this length token
uint32_t customDataLength = tokenStream[0];
tokenStream++;
uint32_t dataLength = customDataLength - 2;
RDCASSERT(customDataLength >= 2);
switch(customClass)
{
case CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER:
{
retDecl.declaration = OPCODE_DCL_IMMEDIATE_CONSTANT_BUFFER;
retDecl.str = "dcl_immediateConstantBuffer {";
RDCASSERT(dataLength % 4 == 0);
for(uint32_t i = 0; i < dataLength; i++)
{
if(i % 4 == 0)
retDecl.str += "\n\t\t\t{ ";
m_Immediate.push_back(tokenStream[0]);
retDecl.str += toString(tokenStream, 1);
tokenStream++;
if((i + 1) % 4 == 0)
retDecl.str += "}";
if(i + 1 < dataLength)
retDecl.str += ", ";
}
retDecl.str += " }";
break;
}
default:
{
// add this as an opaque declaration
retDecl.declaration = OPCODE_OPAQUE_CUSTOMDATA;
retDecl.customDataIndex = (uint32_t)m_CustomDatas.size();
m_CustomDatas.push_back(make_rdcpair(customClass, rdcarray<uint32_t>()));
m_CustomDatas.back().second.assign(tokenStream, dataLength);
// unsupported custom data should be treated in operation as it's first
RDCWARN("Unsupported custom data class %d treated as declaration", customClass);
tokenStream += dataLength;
}
}
return true;
}
uint32_t declLength = Opcode::Length.Get(OpcodeToken0);
tokenStream++;
retDecl.str = ToStr(op);
if(op == OPCODE_DCL_GLOBAL_FLAGS)
{
retDecl.global_flags.refactoringAllowed = Decl::RefactoringAllowed.Get(OpcodeToken0);
retDecl.global_flags.doublePrecisionFloats = Decl::DoubleFloatOps.Get(OpcodeToken0);
retDecl.global_flags.forceEarlyDepthStencil = Decl::ForceEarlyDepthStencil.Get(OpcodeToken0);
retDecl.global_flags.enableRawAndStructuredBuffers =
Decl::EnableRawStructuredBufs.Get(OpcodeToken0);
retDecl.global_flags.skipOptimisation = Decl::SkipOptimisation.Get(OpcodeToken0);
retDecl.global_flags.enableMinPrecision = Decl::EnableMinPrecision.Get(OpcodeToken0);
retDecl.global_flags.enableD3D11_1DoubleExtensions =
Decl::EnableD3D11_1DoubleExtensions.Get(OpcodeToken0);
retDecl.global_flags.enableD3D11_1ShaderExtensions =
Decl::EnableD3D11_1ShaderExtensions.Get(OpcodeToken0);
retDecl.global_flags.enableD3D12AllResourcesBound =
Decl::EnableD3D12AllResourcesBound.Get(OpcodeToken0);
retDecl.str += " ";
bool added = false;
if(retDecl.global_flags.refactoringAllowed)
{
retDecl.str += "refactoringAllowed";
added = true;
}
if(retDecl.global_flags.doublePrecisionFloats)
{
if(added)
retDecl.str += ", ";
retDecl.str += "doublePrecisionFloats";
added = true;
}
if(retDecl.global_flags.forceEarlyDepthStencil)
{
if(added)
retDecl.str += ", ";
retDecl.str += "forceEarlyDepthStencil";
added = true;
}
if(retDecl.global_flags.enableRawAndStructuredBuffers)
{
if(added)
retDecl.str += ", ";
retDecl.str += "enableRawAndStructuredBuffers";
added = true;
}
if(retDecl.global_flags.skipOptimisation)
{
if(added)
retDecl.str += ", ";
retDecl.str += "skipOptimisation";
added = true;
}
if(retDecl.global_flags.enableMinPrecision)
{
if(added)
retDecl.str += ", ";
retDecl.str += "enableMinPrecision";
added = true;
}
if(retDecl.global_flags.enableD3D11_1DoubleExtensions)
{
if(added)
retDecl.str += ", ";
retDecl.str += "doubleExtensions";
added = true;
}
if(retDecl.global_flags.enableD3D11_1ShaderExtensions)
{
if(added)
retDecl.str += ", ";
retDecl.str += "shaderExtensions";
added = true;
}
if(retDecl.global_flags.enableD3D12AllResourcesBound)
{
if(added)
retDecl.str += ", ";
retDecl.str += "d3d12AllResourcesBound";
added = true;
}
}
else if(op == OPCODE_DCL_CONSTANT_BUFFER)
{
retDecl.cbuffer.accessPattern = Decl::AccessPattern.Get(OpcodeToken0);
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.str += " ";
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
if(sm51)
{
// Store the size provided. If there's no reflection data, this will be
// necessary to guess the buffer size properly
retDecl.cbuffer.vectorSize = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt("[%u]", retDecl.cbuffer.vectorSize);
}
retDecl.str += ", ";
if(retDecl.cbuffer.accessPattern == ACCESS_IMMEDIATE_INDEXED)
retDecl.str += "immediateIndexed";
else if(retDecl.cbuffer.accessPattern == ACCESS_DYNAMIC_INDEXED)
retDecl.str += "dynamicIndexed";
else
RDCERR("Unexpected cbuffer access pattern");
retDecl.space = 0;
if(sm51)
{
retDecl.space = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" space=%u", retDecl.space);
if(retDecl.operand.indices[1].index == retDecl.operand.indices[2].index)
retDecl.str += StringFormat::Fmt(",reg=%u", retDecl.operand.indices[1].index);
else if(retDecl.operand.indices[2].index == 0xffffffff)
retDecl.str += StringFormat::Fmt(",regs=%u:unbounded", retDecl.operand.indices[1].index);
else
retDecl.str += StringFormat::Fmt(",regs=%u:%u", retDecl.operand.indices[1].index,
retDecl.operand.indices[2].index);
}
}
else if(op == OPCODE_DCL_INPUT)
{
retDecl.str += " ";
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
if(retDecl.operand.type == TYPE_INPUT_COVERAGE_MASK)
m_InputCoverage = true;
retDecl.str += retDecl.operand.toString(m_Reflection, flags | ToString::ShowSwizzle);
}
else if(op == OPCODE_DCL_TEMPS)
{
retDecl.numTemps = tokenStream[0];
m_NumTemps = retDecl.numTemps;
tokenStream++;
retDecl.str += StringFormat::Fmt(" %u", retDecl.numTemps);
}
else if(op == OPCODE_DCL_INDEXABLE_TEMP)
{
retDecl.indexable_temp.tempReg = tokenStream[0];
tokenStream++;
retDecl.indexable_temp.numTemps = tokenStream[0];
tokenStream++;
retDecl.indexable_temp.tempComponentCount = tokenStream[0];
tokenStream++;
// I don't think the compiler will ever declare a non-compact list of indexable temps, but just
// to be sure our indexing works let's be safe.
if(retDecl.indexable_temp.tempReg >= m_IndexTempSizes.size())
m_IndexTempSizes.resize(retDecl.indexable_temp.tempReg + 1);
m_IndexTempSizes[retDecl.indexable_temp.tempReg] = retDecl.indexable_temp.numTemps;
retDecl.str += StringFormat::Fmt(" x%u[%u], %u", retDecl.indexable_temp.tempReg,
retDecl.indexable_temp.numTemps,
retDecl.indexable_temp.tempComponentCount);
}
else if(op == OPCODE_DCL_OUTPUT)
{
retDecl.str += " ";
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.str += retDecl.operand.toString(m_Reflection, flags | ToString::ShowSwizzle);
}
else if(op == OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT)
{
retDecl.str += " ";
retDecl.maxVertexOutCount = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" %u", retDecl.maxVertexOutCount);
}
else if(op == OPCODE_DCL_INPUT_SIV || op == OPCODE_DCL_INPUT_SGV || op == OPCODE_DCL_OUTPUT_SIV ||
op == OPCODE_DCL_OUTPUT_SGV)
{
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.inputOutput.systemValue = (DXBC::SVSemantic)tokenStream[0];
tokenStream++;
retDecl.str += " ";
retDecl.str += retDecl.operand.toString(m_Reflection, flags | ToString::ShowSwizzle);
retDecl.str += ", ";
retDecl.str += ToStr(retDecl.inputOutput.systemValue);
}
else if(op == OPCODE_DCL_INPUT_PS || op == OPCODE_DCL_INPUT_PS_SIV || op == OPCODE_DCL_INPUT_PS_SGV)
{
// the (minimal) spec says this is 0 for SGV, but it's not and fxc displays the interp mode
retDecl.inputOutput.inputInterpolation = Decl::InterpolationMode.Get(OpcodeToken0);
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
if(op == OPCODE_DCL_INPUT_PS_SIV || op == OPCODE_DCL_INPUT_PS_SGV)
{
retDecl.inputOutput.systemValue = (DXBC::SVSemantic)tokenStream[0];
tokenStream++;
}
retDecl.str += " ";
retDecl.str += ToStr(retDecl.inputOutput.inputInterpolation);
retDecl.str += " ";
retDecl.str += retDecl.operand.toString(m_Reflection, flags | ToString::ShowSwizzle);
if(op == OPCODE_DCL_INPUT_PS_SIV || op == OPCODE_DCL_INPUT_PS_SGV)
{
retDecl.str += ", ";
retDecl.str += ToStr(retDecl.inputOutput.systemValue);
}
}
else if(op == OPCODE_DCL_STREAM)
{
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.str += " ";
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
}
else if(op == OPCODE_DCL_SAMPLER)
{
retDecl.samplerMode = Decl::SamplerMode.Get(OpcodeToken0);
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.str += " ";
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
retDecl.str += ", ";
if(retDecl.samplerMode == SAMPLER_MODE_DEFAULT)
retDecl.str += "mode_default";
if(retDecl.samplerMode == SAMPLER_MODE_COMPARISON)
retDecl.str += "mode_comparison";
if(retDecl.samplerMode == SAMPLER_MODE_MONO)
retDecl.str += "mode_mono";
retDecl.space = 0;
if(sm51)
{
retDecl.space = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" space=%u", retDecl.space);
if(retDecl.operand.indices[1].index == retDecl.operand.indices[2].index)
retDecl.str += StringFormat::Fmt(",reg=%u", retDecl.operand.indices[1].index);
else if(retDecl.operand.indices[2].index == 0xffffffff)
retDecl.str += StringFormat::Fmt(",regs=%u:unbounded", retDecl.operand.indices[1].index);
else
retDecl.str += StringFormat::Fmt(",regs=%u:%u", retDecl.operand.indices[1].index,
retDecl.operand.indices[2].index);
}
}
else if(op == OPCODE_DCL_RESOURCE)
{
retDecl.resource.dim = Decl::ResourceDim.Get(OpcodeToken0);
retDecl.resource.sampleCount = 0;
if(retDecl.resource.dim == RESOURCE_DIMENSION_TEXTURE2DMS ||
retDecl.resource.dim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY)
{
retDecl.resource.sampleCount = Decl::SampleCount.Get(OpcodeToken0);
}
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
uint32_t ResourceReturnTypeToken = tokenStream[0];
tokenStream++;
retDecl.resource.resType[0] = Decl::ReturnTypeX.Get(ResourceReturnTypeToken);
retDecl.resource.resType[1] = Decl::ReturnTypeY.Get(ResourceReturnTypeToken);
retDecl.resource.resType[2] = Decl::ReturnTypeZ.Get(ResourceReturnTypeToken);
retDecl.resource.resType[3] = Decl::ReturnTypeW.Get(ResourceReturnTypeToken);
retDecl.str += "_";
retDecl.str += ToStr(retDecl.resource.dim);
if(retDecl.resource.sampleCount > 0)
{
retDecl.str += "(";
retDecl.str += ToStr(retDecl.resource.sampleCount);
retDecl.str += ")";
}
retDecl.str += " ";
retDecl.str += "(";
retDecl.str += ToStr(retDecl.resource.resType[0]);
retDecl.str += ",";
retDecl.str += ToStr(retDecl.resource.resType[1]);
retDecl.str += ",";
retDecl.str += ToStr(retDecl.resource.resType[2]);
retDecl.str += ",";
retDecl.str += ToStr(retDecl.resource.resType[3]);
retDecl.str += ")";
retDecl.str += " " + retDecl.operand.toString(m_Reflection, flags);
retDecl.space = 0;
if(sm51)
{
retDecl.space = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" space=%u", retDecl.space);
if(retDecl.operand.indices[1].index == retDecl.operand.indices[2].index)
retDecl.str += StringFormat::Fmt(",reg=%u", retDecl.operand.indices[1].index);
else if(retDecl.operand.indices[2].index == 0xffffffff)
retDecl.str += StringFormat::Fmt(",regs=%u:unbounded", retDecl.operand.indices[1].index);
else
retDecl.str += StringFormat::Fmt(",regs=%u:%u", retDecl.operand.indices[1].index,
retDecl.operand.indices[2].index);
}
}
else if(op == OPCODE_DCL_INDEX_RANGE)
{
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.str += " ";
retDecl.str += retDecl.operand.toString(m_Reflection, flags | ToString::ShowSwizzle);
retDecl.indexRange = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" %u", retDecl.indexRange);
}
else if(op == OPCODE_DCL_THREAD_GROUP)
{
retDecl.groupSize[0] = tokenStream[0];
tokenStream++;
retDecl.groupSize[1] = tokenStream[0];
tokenStream++;
retDecl.groupSize[2] = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" %u, %u, %u", retDecl.groupSize[0], retDecl.groupSize[1],
retDecl.groupSize[2]);
}
else if(op == OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW)
{
retDecl.str += " ";
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.tgsmCount = tokenStream[0];
tokenStream++;
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
retDecl.str += StringFormat::Fmt(", %u", retDecl.tgsmCount);
}
else if(op == OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED)
{
retDecl.str += " ";
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.tsgm_structured.stride = tokenStream[0];
tokenStream++;
retDecl.tsgm_structured.count = tokenStream[0];
tokenStream++;
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
retDecl.str +=
StringFormat::Fmt(", %u, %u", retDecl.tsgm_structured.stride, retDecl.tsgm_structured.count);
}
else if(op == OPCODE_DCL_INPUT_CONTROL_POINT_COUNT || op == OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT)
{
retDecl.controlPointCount = Decl::ControlPointCount.Get(OpcodeToken0);
retDecl.str += StringFormat::Fmt(" %u", retDecl.controlPointCount);
}
else if(op == OPCODE_DCL_TESS_DOMAIN)
{
retDecl.tessDomain = Decl::TessDomain.Get(OpcodeToken0);
retDecl.str += " ";
if(retDecl.tessDomain == DOMAIN_ISOLINE)
retDecl.str += "domain_isoline";
else if(retDecl.tessDomain == DOMAIN_TRI)
retDecl.str += "domain_tri";
else if(retDecl.tessDomain == DOMAIN_QUAD)
retDecl.str += "domain_quad";
else
RDCERR("Unexpected Tessellation domain");
}
else if(op == OPCODE_DCL_TESS_PARTITIONING)
{
retDecl.tessPartition = Decl::TessPartitioning.Get(OpcodeToken0);
retDecl.str += " ";
if(retDecl.tessPartition == PARTITIONING_INTEGER)
retDecl.str += "partitioning_integer";
else if(retDecl.tessPartition == PARTITIONING_POW2)
retDecl.str += "partitioning_pow2";
else if(retDecl.tessPartition == PARTITIONING_FRACTIONAL_ODD)
retDecl.str += "partitioning_fractional_odd";
else if(retDecl.tessPartition == PARTITIONING_FRACTIONAL_EVEN)
retDecl.str += "partitioning_fractional_even";
else
RDCERR("Unexpected Partitioning");
}
else if(op == OPCODE_DCL_GS_INPUT_PRIMITIVE)
{
retDecl.geomInputPrimitive = Decl::InputPrimitive.Get(OpcodeToken0);
retDecl.str += " ";
if(retDecl.geomInputPrimitive == PRIMITIVE_POINT)
retDecl.str += "point";
else if(retDecl.geomInputPrimitive == PRIMITIVE_LINE)
retDecl.str += "line";
else if(retDecl.geomInputPrimitive == PRIMITIVE_TRIANGLE)
retDecl.str += "triangle";
else if(retDecl.geomInputPrimitive == PRIMITIVE_LINE_ADJ)
retDecl.str += "line_adj";
else if(retDecl.geomInputPrimitive == PRIMITIVE_TRIANGLE_ADJ)
retDecl.str += "triangle_adj";
else if(retDecl.geomInputPrimitive >= PRIMITIVE_1_CONTROL_POINT_PATCH &&
retDecl.geomInputPrimitive <= PRIMITIVE_32_CONTROL_POINT_PATCH)
{
retDecl.str +=
StringFormat::Fmt("control_point_patch_%u",
1 + int(retDecl.geomInputPrimitive - PRIMITIVE_1_CONTROL_POINT_PATCH));
}
else
RDCERR("Unexpected primitive type");
}
else if(op == OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY)
{
retDecl.geomOutputTopology = Decl::OutputPrimitiveTopology.Get(OpcodeToken0);
retDecl.str += " ";
if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_POINTLIST)
retDecl.str += "point";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_LINELIST)
retDecl.str += "linelist";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_LINESTRIP)
retDecl.str += "linestrip";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST)
retDecl.str += "trianglelist";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP)
retDecl.str += "trianglestrip";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ)
retDecl.str += "linelist_adj";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ)
retDecl.str += "linestrip_adj";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ)
retDecl.str += "trianglelist_adj";
else if(retDecl.geomOutputTopology == D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ)
retDecl.str += "trianglestrip_adj";
else
RDCERR("Unexpected primitive topology");
}
else if(op == OPCODE_DCL_TESS_OUTPUT_PRIMITIVE)
{
retDecl.tessOutputPrimitive = Decl::OutputPrimitive.Get(OpcodeToken0);
retDecl.str += " ";
if(retDecl.tessOutputPrimitive == OUTPUT_PRIMITIVE_POINT)
retDecl.str += "output_point";
else if(retDecl.tessOutputPrimitive == OUTPUT_PRIMITIVE_LINE)
retDecl.str += "output_line";
else if(retDecl.tessOutputPrimitive == OUTPUT_PRIMITIVE_TRIANGLE_CW)
retDecl.str += "output_triangle_cw";
else if(retDecl.tessOutputPrimitive == OUTPUT_PRIMITIVE_TRIANGLE_CCW)
retDecl.str += "output_triangle_ccw";
else
RDCERR("Unexpected output primitive");
}
else if(op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW || op == OPCODE_DCL_RESOURCE_RAW)
{
retDecl.raw.rov = (op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW) &&
Decl::RasterizerOrderedAccess.Get(OpcodeToken0);
retDecl.raw.globallyCoherant =
(op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW) & Decl::GloballyCoherent.Get(OpcodeToken0);
retDecl.str += " ";
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
if(retDecl.raw.globallyCoherant)
retDecl.str += ", globallyCoherant";
if(retDecl.raw.rov)
retDecl.str += ", rasterizerOrderedAccess";
retDecl.space = 0;
if(sm51)
{
retDecl.space = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" space=%u", retDecl.space);
if(retDecl.operand.indices[1].index == retDecl.operand.indices[2].index)
retDecl.str += StringFormat::Fmt(",reg=%u", retDecl.operand.indices[1].index);
else if(retDecl.operand.indices[2].index == 0xffffffff)
retDecl.str += StringFormat::Fmt(",regs=%u:unbounded", retDecl.operand.indices[1].index);
else
retDecl.str += StringFormat::Fmt(",regs=%u:%u", retDecl.operand.indices[1].index,
retDecl.operand.indices[2].index);
}
}
else if(op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED || op == OPCODE_DCL_RESOURCE_STRUCTURED)
{
retDecl.structured.hasCounter = (op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED) &&
Decl::HasOrderPreservingCounter.Get(OpcodeToken0);
retDecl.structured.rov = (op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED) &&
Decl::RasterizerOrderedAccess.Get(OpcodeToken0);
retDecl.structured.globallyCoherant = (op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED) &
Decl::GloballyCoherent.Get(OpcodeToken0);
retDecl.str += " ";
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
retDecl.structured.stride = tokenStream[0];
tokenStream++;
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
retDecl.str += StringFormat::Fmt(", %u", retDecl.structured.stride);
if(retDecl.structured.hasCounter)
retDecl.str += ", hasOrderPreservingCounter";
if(retDecl.structured.globallyCoherant)
retDecl.str += ", globallyCoherant";
if(retDecl.structured.rov)
retDecl.str += ", rasterizerOrderedAccess";
retDecl.space = 0;
if(sm51)
{
retDecl.space = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" space=%u", retDecl.space);
if(retDecl.operand.indices[1].index == retDecl.operand.indices[2].index)
retDecl.str += StringFormat::Fmt(",reg=%u", retDecl.operand.indices[1].index);
else if(retDecl.operand.indices[2].index == 0xffffffff)
retDecl.str += StringFormat::Fmt(",regs=%u:unbounded", retDecl.operand.indices[1].index);
else
retDecl.str += StringFormat::Fmt(",regs=%u:%u", retDecl.operand.indices[1].index,
retDecl.operand.indices[2].index);
}
}
else if(op == OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED)
{
retDecl.uav_typed.dim = Decl::ResourceDim.Get(OpcodeToken0);
retDecl.uav_typed.globallyCoherant = Decl::GloballyCoherent.Get(OpcodeToken0);
retDecl.uav_typed.rov = Decl::RasterizerOrderedAccess.Get(OpcodeToken0);
retDecl.str += "_";
retDecl.str += ToStr(retDecl.uav_typed.dim);
if(retDecl.uav_typed.globallyCoherant)
retDecl.str += "_glc";
bool ret = DecodeOperand(tokenStream, flags, retDecl.operand);
RDCASSERT(ret);
uint32_t ResourceReturnTypeToken = tokenStream[0];
tokenStream++;
retDecl.uav_typed.resType[0] = Decl::ReturnTypeX.Get(ResourceReturnTypeToken);
retDecl.uav_typed.resType[1] = Decl::ReturnTypeY.Get(ResourceReturnTypeToken);
retDecl.uav_typed.resType[2] = Decl::ReturnTypeZ.Get(ResourceReturnTypeToken);
retDecl.uav_typed.resType[3] = Decl::ReturnTypeW.Get(ResourceReturnTypeToken);
retDecl.str += " ";
retDecl.str += "(";
retDecl.str += ToStr(retDecl.uav_typed.resType[0]);
retDecl.str += ",";
retDecl.str += ToStr(retDecl.uav_typed.resType[1]);
retDecl.str += ",";
retDecl.str += ToStr(retDecl.uav_typed.resType[2]);
retDecl.str += ",";
retDecl.str += ToStr(retDecl.uav_typed.resType[3]);
retDecl.str += ")";
retDecl.str += " ";
retDecl.str += retDecl.operand.toString(m_Reflection, flags);
if(retDecl.uav_typed.rov)
retDecl.str += ", rasterizerOrderedAccess";
retDecl.space = 0;
if(sm51)
{
retDecl.space = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" space=%u", retDecl.space);
if(retDecl.operand.indices[1].index == retDecl.operand.indices[2].index)
retDecl.str += StringFormat::Fmt(",reg=%u", retDecl.operand.indices[1].index);
else if(retDecl.operand.indices[2].index == 0xffffffff)
retDecl.str += StringFormat::Fmt(",regs=%u:unbounded", retDecl.operand.indices[1].index);
else
retDecl.str += StringFormat::Fmt(",regs=%u:%u", retDecl.operand.indices[1].index,
retDecl.operand.indices[2].index);
}
}
else if(op == OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT ||
op == OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT || op == OPCODE_DCL_GS_INSTANCE_COUNT)
{
retDecl.instanceCount = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" %u", retDecl.instanceCount);
}
else if(op == OPCODE_DCL_HS_MAX_TESSFACTOR)
{
float *f = (float *)tokenStream;
retDecl.maxTessFactor = *f;
tokenStream++;
retDecl.str += StringFormat::Fmt(" l(%f)", retDecl.maxTessFactor);
}
else if(op == OPCODE_DCL_FUNCTION_BODY)
{
retDecl.functionBody = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" fb%u", retDecl.functionBody);
}
else if(op == OPCODE_DCL_FUNCTION_TABLE)
{
retDecl.functionTable = tokenStream[0];
tokenStream++;
retDecl.str += StringFormat::Fmt(" ft%u", retDecl.functionTable);
uint32_t TableLength = tokenStream[0];
tokenStream++;
retDecl.str += " = {";
for(uint32_t i = 0; i < TableLength; i++)
{
retDecl.str += StringFormat::Fmt("fb%u", tokenStream[0]);
if(i + 1 < TableLength)
retDecl.str += ", ";
retDecl.functionTableContents.push_back(tokenStream[0]);
tokenStream++;
}
retDecl.str += "}";
}
else if(op == OPCODE_DCL_INTERFACE)
{
retDecl.iface.interfaceID = tokenStream[0];
tokenStream++;
retDecl.iface.numTypes = tokenStream[0];
tokenStream++;
uint32_t CountToken = tokenStream[0];
tokenStream++;
retDecl.iface.numInterfaces = Decl::NumInterfaces.Get(CountToken);
uint32_t TableLength = Decl::TableLength.Get(CountToken);
retDecl.str += StringFormat::Fmt(" fp%u[%u][%u]", retDecl.iface.interfaceID,
retDecl.iface.numInterfaces, retDecl.iface.numTypes);
retDecl.str += " = {";
for(uint32_t i = 0; i < TableLength; i++)
{
retDecl.str += StringFormat::Fmt("ft%u", tokenStream[0]);
if(i + 1 < TableLength)
retDecl.str += ", ";
retDecl.functionTableContents.push_back(tokenStream[0]);
tokenStream++;
}
retDecl.str += "}";
}
else if(op == OPCODE_HS_DECLS)
{
}
else
{
RDCERR("Unexpected opcode decl %d", op);
}
if(op == OPCODE_DCL_OUTPUT || op == OPCODE_DCL_OUTPUT_SIV || op == OPCODE_DCL_OUTPUT_SGV)
{
if(retDecl.operand.type == TYPE_OUTPUT_COVERAGE_MASK)
m_OutputCoverage = true;
else if(retDecl.operand.type == TYPE_OUTPUT_STENCIL_REF)
m_OutputStencil = true;
else if(retDecl.operand.type == TYPE_OUTPUT_DEPTH ||
retDecl.operand.type == TYPE_OUTPUT_DEPTH_GREATER_EQUAL ||
retDecl.operand.type == TYPE_OUTPUT_DEPTH_LESS_EQUAL)
m_OutputDepth = true;
else if(retDecl.operand.indices[0].absolute && retDecl.operand.indices[0].index < 0xffff)
m_NumOutputs = RDCMAX(m_NumOutputs, uint32_t(retDecl.operand.indices[0].index) + 1);
}
// make sure we consumed all uint32s
RDCASSERT((uint32_t)(tokenStream - begin) == declLength);
return true;
}