in projects/dxilconv/lib/DxbcConverter/DxbcConverter.cpp [1171:1900]
void DxbcConverter::AnalyzeShader(D3D10ShaderBinary::CShaderCodeParser &Parser) {
// Parse shader model.
D3D10_SB_TOKENIZED_PROGRAM_TYPE ShaderType = Parser.ShaderType();
m_DxbcMajor = Parser.ShaderMajorVersion();
m_DxbcMinor = Parser.ShaderMinorVersion();
ShaderModel::Kind ShaderKind = DXBC::GetShaderModelKind(ShaderType);
// The converter always promotes the shader version to 6.0.
m_pSM = ShaderModel::Get(ShaderKind, 6, 0);
m_pPR->SetShaderModel(m_pSM);
// By default refactoring is disallowed, unless we encounter
// dcl_globalflags allowRefactoring
m_pPR->m_ShaderFlags.SetDisableMathRefactoring(true);
// By default, all resources are assumed bound for SM5.0 shaders,
// unless we encounter interface declarations
m_pPR->m_ShaderFlags.SetAllResourcesBound(true);
// Setup signature helpers.
m_pInputSignature.reset(new SignatureHelper(m_pSM->GetKind(), DXIL::SignatureKind::Input));
m_pOutputSignature.reset(new SignatureHelper(m_pSM->GetKind(), DXIL::SignatureKind::Output));
m_pPatchConstantSignature.reset(new SignatureHelper(m_pSM->GetKind(), DXIL::SignatureKind::PatchConstOrPrim));
// Collect:
// 1. Declarations
// 2. Labels
// Declare:
// 1. Global symbols for resources/samplers.
// 2. Their types.
BYTE CurrentOutputStream = 0;
unsigned MaxOutputRegister = 0;
m_bControlPointPhase = false;
bool bPatchConstantPhase = false;
D3D10ShaderBinary::CInstruction Inst;
while(!Parser.EndOfShader()) {
Parser.ParseInstruction(&Inst);
switch (Inst.OpCode()) {
case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER: {
// Record this cbuffer declaration in DxilModule.
unsigned ID = m_pPR->AddCBuffer(unique_ptr<DxilCBuffer>(new DxilCBuffer));
DxilCBuffer &R = m_pPR->GetCBuffer(ID); // R == record
R.SetID(ID);
// Root signature bindings.
unsigned RangeID = Inst.m_Operands[0].m_Index[0].m_RegIndex;
unsigned CBufferSize = Inst.m_ConstantBufferDecl.Size * DXBC::kWidth * 4;
unsigned LB, RangeSize;
switch (Inst.m_Operands[0].m_IndexDimension) {
case D3D10_SB_OPERAND_INDEX_2D: // SM 5.0-
LB = RangeID;
RangeSize = 1;
break;
case D3D10_SB_OPERAND_INDEX_3D: // SM 5.1
LB = Inst.m_Operands[0].m_Index[1].m_RegIndex;
RangeSize = Inst.m_Operands[0].m_Index[2].m_RegIndex != UINT_MAX ? Inst.m_Operands[0].m_Index[2].m_RegIndex - LB + 1 : UINT_MAX;
break;
default:
DXASSERT_DXBC(false);
IFTARG(NULL);
}
R.SetLowerBound(LB);
R.SetRangeSize(RangeSize);
R.SetSpaceID(Inst.m_ConstantBufferDecl.Space);
// Declare global variable.
R.SetGlobalName(SynthesizeResGVName("CB", R.GetID()));
StructType *pResType = GetStructResElemType(CBufferSize);
R.SetGlobalSymbol(DeclareUndefPtr(pResType, DXIL::kCBufferAddrSpace));
// CBuffer-specific state.
R.SetSize(CBufferSize);
//R.SetImmediateIndexed(Inst.m_ConstantBufferDecl.AccessPattern == D3D10_SB_CONSTANT_BUFFER_IMMEDIATE_INDEXED);
// Record shader register/rangeID mapping for upcoming instruction conversion.
DXASSERT(m_CBufferRangeMap.find(RangeID) == m_CBufferRangeMap.end(), "otherwise overlapping declarations");
m_CBufferRangeMap[RangeID] = R.GetID();
break;
}
case D3D10_SB_OPCODE_DCL_SAMPLER: {
// Record this sampler declaration in DxilModule.
unsigned ID = m_pPR->AddSampler(unique_ptr<DxilSampler>(new DxilSampler));
DxilSampler &R = m_pPR->GetSampler(ID); // R == record
R.SetID(ID);
// Root signature bindings.
unsigned RangeID = Inst.m_Operands[0].m_Index[0].m_RegIndex;
unsigned LB, RangeSize;
switch (Inst.m_Operands[0].m_IndexDimension) {
case D3D10_SB_OPERAND_INDEX_1D: // SM 5.0-
LB = RangeID;
RangeSize = 1;
break;
case D3D10_SB_OPERAND_INDEX_3D: // SM 5.1
LB = Inst.m_Operands[0].m_Index[1].m_RegIndex;
RangeSize = Inst.m_Operands[0].m_Index[2].m_RegIndex != UINT_MAX ? Inst.m_Operands[0].m_Index[2].m_RegIndex - LB + 1 : UINT_MAX;
break;
default:
DXASSERT_DXBC(false);
IFTARG(NULL);
}
R.SetLowerBound(LB);
R.SetRangeSize(RangeSize);
R.SetSpaceID(Inst.m_SamplerDecl.Space);
// Declare global variable.
R.SetGlobalName(SynthesizeResGVName("S", R.GetID()));
string ResTypeName("dx.types.Sampler");
StructType *pResType = m_pModule->getTypeByName(ResTypeName);
if (pResType == nullptr) {
pResType = StructType::create(m_Ctx, ResTypeName);
}
R.SetGlobalSymbol(DeclareUndefPtr(pResType, DXIL::kDeviceMemoryAddrSpace));
// Sampler-specific state.
R.SetSamplerKind(DXBC::GetSamplerKind(Inst.m_SamplerDecl.SamplerMode));
// Record shader register/rangeID mapping for upcoming instruction conversion.
DXASSERT(m_SamplerRangeMap.find(RangeID) == m_SamplerRangeMap.end(), "otherwise overlapping declarations");
m_SamplerRangeMap[RangeID] = R.GetID();
break;
}
case D3D10_SB_OPCODE_DCL_RESOURCE:
case D3D11_SB_OPCODE_DCL_RESOURCE_RAW:
case D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED: {
// Record this SRV declaration in DxilModule.
unsigned ID = m_pPR->AddSRV(unique_ptr<DxilResource>(new DxilResource));
DxilResource &R = m_pPR->GetSRV(ID); // R == record
R.SetID(ID);
R.SetRW(false);
// Root signature bindings.
unsigned RangeID = Inst.m_Operands[0].m_Index[0].m_RegIndex;
unsigned LB, RangeSize;
if (IsSM51Plus()) {
LB = Inst.m_Operands[0].m_Index[1].m_RegIndex;
RangeSize = Inst.m_Operands[0].m_Index[2].m_RegIndex != UINT_MAX ? Inst.m_Operands[0].m_Index[2].m_RegIndex - LB + 1 : UINT_MAX;
} else {
LB = RangeID;
RangeSize = 1;
}
R.SetLowerBound(LB);
R.SetRangeSize(RangeSize);
// Resource-specific state.
StructType *pResType = nullptr;
switch (Inst.OpCode()) {
case D3D10_SB_OPCODE_DCL_RESOURCE: {
R.SetSpaceID(Inst.m_ResourceDecl.Space);
R.SetKind(DXBC::GetResourceKind(Inst.m_ResourceDecl.Dimension));
const unsigned kTypedBufferElementSizeInBytes = 4;
R.SetElementStride(kTypedBufferElementSizeInBytes);
R.SetSampleCount(Inst.m_ResourceDecl.SampleCount);
CompType DeclCT = DXBC::GetDeclResCompType(Inst.m_ResourceDecl.ReturnType[0]);
if (DeclCT.IsInvalid()) DeclCT = CompType::getU32();
R.SetCompType(DeclCT);
pResType = GetTypedResElemType(DeclCT);
break;
}
case D3D11_SB_OPCODE_DCL_RESOURCE_RAW: {
R.SetSpaceID(Inst.m_RawSRVDecl.Space);
R.SetKind(DxilResource::Kind::RawBuffer);
const unsigned kRawBufferElementSizeInBytes = 1;
R.SetElementStride(kRawBufferElementSizeInBytes);
pResType = GetTypedResElemType(CompType::getU32());
break;
}
case D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED: {
R.SetSpaceID(Inst.m_StructuredSRVDecl.Space);
R.SetKind(DxilResource::Kind::StructuredBuffer);
unsigned Stride = Inst.m_StructuredSRVDecl.ByteStride;
R.SetElementStride(Stride);
pResType = GetStructResElemType(Stride);
break;
}
default: ;
}
// Declare global variable.
R.SetGlobalName(SynthesizeResGVName("T", R.GetID()));
R.SetGlobalSymbol(DeclareUndefPtr(pResType, DXIL::kDeviceMemoryAddrSpace));
// Record shader register/rangeID mapping for upcoming instruction conversion.
DXASSERT(m_SRVRangeMap.find(RangeID) == m_SRVRangeMap.end(), "otherwise overlapping declarations");
m_SRVRangeMap[RangeID] = R.GetID();
break;
}
case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED:
case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW:
case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: {
// Record this UAV declaration in DxilModule.
unsigned ID = m_pPR->AddUAV(unique_ptr<DxilResource>(new DxilResource));
DxilResource &R = m_pPR->GetUAV(ID); // R == record
R.SetID(ID);
R.SetRW(true);
// Root signature bindings.
unsigned RangeID = Inst.m_Operands[0].m_Index[0].m_RegIndex;
unsigned LB, RangeSize;
if (IsSM51Plus()) {
LB = Inst.m_Operands[0].m_Index[1].m_RegIndex;
RangeSize = Inst.m_Operands[0].m_Index[2].m_RegIndex != UINT_MAX ? Inst.m_Operands[0].m_Index[2].m_RegIndex - LB + 1 : UINT_MAX;
} else {
LB = RangeID;
RangeSize = 1;
}
R.SetLowerBound(LB);
R.SetRangeSize(RangeSize);
// Resource-specific state.
string GVTypeName;
raw_string_ostream GVTypeNameStream(GVTypeName);
StructType *pResType = nullptr;
unsigned Flags = 0;
switch (Inst.OpCode()) {
case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: {
R.SetSpaceID(Inst.m_TypedUAVDecl.Space);
Flags = Inst.m_TypedUAVDecl.Flags;
R.SetKind(DXBC::GetResourceKind(Inst.m_TypedUAVDecl.Dimension));
const unsigned kTypedBufferElementSizeInBytes = 4;
R.SetElementStride(kTypedBufferElementSizeInBytes);
CompType DeclCT = DXBC::GetDeclResCompType(Inst.m_TypedUAVDecl.ReturnType[0]);
if (DeclCT.IsInvalid()) DeclCT = CompType::getU32();
R.SetCompType(DeclCT);
pResType = GetTypedResElemType(DeclCT);
break;
}
case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: {
R.SetSpaceID(Inst.m_RawUAVDecl.Space);
R.SetKind(DxilResource::Kind::RawBuffer);
Flags = Inst.m_RawUAVDecl.Flags;
const unsigned kRawBufferElementSizeInBytes = 1;
R.SetElementStride(kRawBufferElementSizeInBytes);
pResType = GetTypedResElemType(CompType::getU32());
break;
}
case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: {
R.SetSpaceID(Inst.m_StructuredUAVDecl.Space);
R.SetKind(DxilResource::Kind::StructuredBuffer);
Flags = Inst.m_StructuredUAVDecl.Flags;
unsigned Stride = Inst.m_StructuredUAVDecl.ByteStride;
R.SetElementStride(Stride);
pResType = GetStructResElemType(Stride);
break;
}
default: ;
}
R.SetGloballyCoherent((Flags & D3D11_SB_GLOBALLY_COHERENT_ACCESS) != 0);
R.SetHasCounter((Flags & D3D11_SB_UAV_HAS_ORDER_PRESERVING_COUNTER) != 0);
R.SetROV((Flags & D3D11_SB_RASTERIZER_ORDERED_ACCESS) != 0);
// Declare global variable.
R.SetGlobalName(SynthesizeResGVName("U", R.GetID()));
R.SetGlobalSymbol(DeclareUndefPtr(pResType, DXIL::kDeviceMemoryAddrSpace));
// Record shader register/rangeID mapping for upcoming instruction conversion.
DXASSERT(m_UAVRangeMap.find(RangeID) == m_UAVRangeMap.end(), "otherwise overlapping declarations");
m_UAVRangeMap[RangeID] = R.GetID();
break;
}
case D3D10_SB_OPCODE_DCL_INDEX_RANGE: {
unsigned RowRegIdx = (Inst.m_Operands[0].m_IndexDimension == D3D10_SB_OPERAND_INDEX_1D) ? 0 : 1;
SignatureHelper::Range R;
R.StartRow = Inst.m_Operands[0].m_Index[RowRegIdx].m_RegIndex;
R.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
R.Rows = Inst.m_IndexRangeDecl.RegCount;
R.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
R.OutputStream = CurrentOutputStream;
switch (Inst.m_Operands[0].m_Type) {
case D3D10_SB_OPERAND_TYPE_INPUT:
m_pInputSignature->m_Ranges.emplace_back(R);
break;
case D3D10_SB_OPERAND_TYPE_OUTPUT:
if (!m_pSM->IsHS() || m_bControlPointPhase) {
m_pOutputSignature->m_Ranges.emplace_back(R);
} else {
DXASSERT_NOMSG(m_pSM->IsHS() && bPatchConstantPhase);
m_pPatchConstantSignature->m_Ranges.emplace_back(R);
}
break;
case D3D11_SB_OPERAND_TYPE_INPUT_PATCH_CONSTANT:
DXASSERT_DXBC(m_pSM->IsHS() || m_pSM->IsDS());
m_pPatchConstantSignature->m_Ranges.emplace_back(R);
break;
case D3D11_SB_OPERAND_TYPE_INPUT_CONTROL_POINT:
DXASSERT_DXBC(m_pSM->IsHS() || m_pSM->IsDS());
m_pInputSignature->m_Ranges.emplace_back(R);
break;
default:
DXASSERT_DXBC(false);
}
break;
}
case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE:
m_pPR->SetInputPrimitive(DXBC::GetInputPrimitive(Inst.m_InputPrimitiveDecl.Primitive));
break;
case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY:
m_pPR->SetStreamPrimitiveTopology(DXBC::GetPrimitiveTopology(Inst.m_OutputTopologyDecl.Topology));
break;
case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT:
m_pPR->SetMaxVertexCount(Inst.m_GSMaxOutputVertexCountDecl.MaxOutputVertexCount);
break;
case D3D10_SB_OPCODE_DCL_INPUT: {
D3D10_SB_OPERAND_TYPE RegType = Inst.m_Operands[0].m_Type;
switch (RegType) {
case D3D11_SB_OPERAND_TYPE_INPUT_COVERAGE_MASK:
m_pInputSignature->m_bHasInputCoverage = true;
break;
case D3D11_SB_OPERAND_TYPE_INNER_COVERAGE:
m_pInputSignature->m_bHasInnerInputCoverage = true;
break;
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID:
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_GROUP_ID:
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP:
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED:
case D3D11_SB_OPERAND_TYPE_INPUT_DOMAIN_POINT:
case D3D11_SB_OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID:
case D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID:
case D3D11_SB_OPERAND_TYPE_INPUT_FORK_INSTANCE_ID:
case D3D11_SB_OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID:
case D3D11_SB_OPERAND_TYPE_CYCLE_COUNTER:
case D3D11_SB_OPERAND_TYPE_INPUT_GS_INSTANCE_ID:
break;
default: {
unsigned NumUnits, Row;
switch (Inst.m_Operands[0].m_IndexDimension) {
case D3D10_SB_OPERAND_INDEX_1D:
NumUnits = 0;
Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
break;
case D3D10_SB_OPERAND_INDEX_2D:
NumUnits = Inst.m_Operands[0].m_Index[0].m_RegIndex;
Row = Inst.m_Operands[0].m_Index[1].m_RegIndex;
break;
default:
DXASSERT(false, "there should no other index dimensions");
}
SignatureHelper::UsedElement E;
E.NumUnits = NumUnits;
E.Row = Row;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = D3D_INTERPOLATION_UNDEFINED;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
if (RegType == D3D10_SB_OPERAND_TYPE_INPUT) {
m_pInputSignature->m_UsedElements.emplace_back(E);
} else {
if (m_pSM->IsDS()) {
switch (RegType) {
case D3D11_SB_OPERAND_TYPE_INPUT_CONTROL_POINT:
m_pInputSignature->m_UsedElements.emplace_back(E);
break;
case D3D11_SB_OPERAND_TYPE_INPUT_PATCH_CONSTANT:
m_pPatchConstantSignature->m_UsedElements.emplace_back(E);
break;
default:
DXASSERT(false, "check unsupported case");
break;
}
}
if (m_pSM->IsHS()) {
switch (RegType) {
case D3D11_SB_OPERAND_TYPE_INPUT_CONTROL_POINT:
m_pInputSignature->m_UsedElements.emplace_back(E);
break;
case D3D11_SB_OPERAND_TYPE_INPUT_PATCH_CONSTANT:
break;
case D3D11_SB_OPERAND_TYPE_OUTPUT_CONTROL_POINT:
break;
default:
DXASSERT(false, "check unsupported case");
break;
}
}
}
break;
}
}
break;
}
case D3D10_SB_OPCODE_DCL_INPUT_SGV: {
SignatureHelper::UsedElement E;
E.Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = D3D_INTERPOLATION_UNDEFINED;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
m_pInputSignature->m_UsedElements.emplace_back(E);
break;
}
case D3D10_SB_OPCODE_DCL_INPUT_SIV: {
unsigned NumUnits = 0;
unsigned Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
if (m_pSM->IsGS()) {
NumUnits = Inst.m_Operands[0].m_Index[0].m_RegIndex;
Row = Inst.m_Operands[0].m_Index[1].m_RegIndex;
}
SignatureHelper::UsedElement E;
E.NumUnits = NumUnits;
E.Row = Row;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = D3D_INTERPOLATION_UNDEFINED;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
switch (Inst.m_Operands[0].m_Type) {
case D3D10_SB_OPERAND_TYPE_INPUT:
m_pInputSignature->m_UsedElements.emplace_back(E);
break;
case D3D11_SB_OPERAND_TYPE_INPUT_PATCH_CONSTANT:
m_pPatchConstantSignature->m_UsedElements.emplace_back(E);
break;
default:
DXASSERT(false, "missing case");
break;
}
break;
}
case D3D10_SB_OPCODE_DCL_INPUT_PS: {
SignatureHelper::UsedElement E;
E.Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = (D3D_INTERPOLATION_MODE)Inst.m_InputPSDecl.InterpolationMode;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
m_pInputSignature->m_UsedElements.emplace_back(E);
break;
}
case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV: {
SignatureHelper::UsedElement E;
E.Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = (D3D_INTERPOLATION_MODE)Inst.m_InputPSDeclSGV.InterpolationMode;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
m_pInputSignature->m_UsedElements.emplace_back(E);
break;
}
case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV: {
SignatureHelper::UsedElement E;
E.Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = (D3D_INTERPOLATION_MODE)Inst.m_InputPSDeclSIV.InterpolationMode;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
m_pInputSignature->m_UsedElements.emplace_back(E);
break;
}
case D3D10_SB_OPCODE_DCL_OUTPUT: {
D3D10_SB_OPERAND_TYPE RegType = Inst.m_Operands[0].m_Type;
switch (RegType) {
case D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH:
case D3D11_SB_OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL:
case D3D11_SB_OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL:
m_DepthRegType = RegType;
__fallthrough;
case D3D11_SB_OPERAND_TYPE_OUTPUT_STENCIL_REF:
case D3D10_SB_OPERAND_TYPE_OUTPUT_COVERAGE_MASK: {
m_bHasStencilRef = RegType == D3D11_SB_OPERAND_TYPE_OUTPUT_STENCIL_REF;
m_bHasCoverageOut = RegType == D3D10_SB_OPERAND_TYPE_OUTPUT_COVERAGE_MASK;
SignatureHelper::UsedElement E;
E.Row = Semantic::kUndefinedRow;
E.StartCol = 0;
E.Cols = 1;
E.InterpolationMode = D3D_INTERPOLATION_UNDEFINED;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
m_pOutputSignature->m_UsedElements.emplace_back(E);
break;
}
default: {
SignatureHelper::UsedElement E;
E.Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = D3D_INTERPOLATION_UNDEFINED;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
E.OutputStream = CurrentOutputStream;
if (!m_pSM->IsHS() || m_bControlPointPhase) {
m_pOutputSignature->m_UsedElements.emplace_back(E);
} else {
DXASSERT_NOMSG(m_pSM->IsHS() && bPatchConstantPhase);
m_pPatchConstantSignature->m_UsedElements.emplace_back(E);
}
MaxOutputRegister = std::max(MaxOutputRegister, E.Row);
break;
}
}
break;
}
case D3D10_SB_OPCODE_DCL_OUTPUT_SGV:
case D3D10_SB_OPCODE_DCL_OUTPUT_SIV: {
SignatureHelper::UsedElement E;
E.Row = Inst.m_Operands[0].m_Index[0].m_RegIndex;
E.StartCol = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetFirstActiveComp();
E.Cols = CMask::FromDXBC(Inst.m_Operands[0].m_WriteMask).GetNumActiveRangeComps();
E.InterpolationMode = D3D_INTERPOLATION_UNDEFINED;
E.MinPrecision = Inst.m_Operands[0].m_MinPrecision;
E.OutputStream = CurrentOutputStream;
if (!m_pSM->IsHS() || m_bControlPointPhase) {
m_pOutputSignature->m_UsedElements.emplace_back(E);
} else {
DXASSERT_NOMSG(m_pSM->IsHS() && bPatchConstantPhase);
m_pPatchConstantSignature->m_UsedElements.emplace_back(E);
}
MaxOutputRegister = std::max(MaxOutputRegister, E.Row);
break;
}
case D3D10_SB_OPCODE_DCL_TEMPS:
m_NumTempRegs = std::max(m_NumTempRegs, Inst.m_TempsDecl.NumTemps);
break;
case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP: {
// Record x-register.
unsigned Reg = Inst.m_IndexableTempDecl.IndexableTempNumber;
unsigned NumRegs = Inst.m_IndexableTempDecl.NumRegisters;
CMask Mask = CMask::FromDXBC(Inst.m_IndexableTempDecl.Mask);
IndexableReg IR = { nullptr, nullptr, NumRegs, Mask.GetNumActiveRangeComps(), true };
if (!bPatchConstantPhase) {
// This is the main shader.
DXASSERT_DXBC(m_IndexableRegs.find(Reg) == m_IndexableRegs.end());
m_IndexableRegs[Reg] = IR;
} else {
// This is patch constant function.
// Can have dcl per phase
auto itIR = m_PatchConstantIndexableRegs.find(Reg);
if (itIR != m_PatchConstantIndexableRegs.end()) {
auto &theIR = itIR->second;
theIR.NumComps = std::max(theIR.NumComps, IR.NumComps);
theIR.NumComps = std::max(theIR.NumRegs, IR.NumRegs);
} else {
m_PatchConstantIndexableRegs[Reg] = IR;
}
}
break;
}
case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS:
SetShaderGlobalFlags(Inst.m_GlobalFlagsDecl.Flags);
break;
case D3D11_SB_OPCODE_DCL_STREAM: {
BYTE Stream = (BYTE)Inst.m_Operands[0].m_Index[0].m_RegIndex;
IFTBOOL(Stream < DXIL::kNumOutputStreams, DXC_E_INCORRECT_DXBC);
CurrentOutputStream = Stream;
m_pPR->SetStreamActive(Stream, true);
break;
}
case D3D11_SB_OPCODE_HS_DECLS:
break;
case D3D11_SB_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT:
m_pPR->SetInputControlPointCount(Inst.m_InputControlPointCountDecl.InputControlPointCount);
break;
case D3D11_SB_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT:
m_pPR->SetOutputControlPointCount(Inst.m_OutputControlPointCountDecl.OutputControlPointCount);
break;
case D3D11_SB_OPCODE_DCL_TESS_DOMAIN:
m_pPR->SetTessellatorDomain(DXBC::GetTessellatorDomain(Inst.m_TessellatorDomainDecl.TessellatorDomain));
break;
case D3D11_SB_OPCODE_DCL_TESS_PARTITIONING:
m_pPR->SetTessellatorPartitioning(DXBC::GetTessellatorPartitioning(Inst.m_TessellatorPartitioningDecl.TessellatorPartitioning));
break;
case D3D11_SB_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE:
m_pPR->SetTessellatorOutputPrimitive(DXBC::GetTessellatorOutputPrimitive(Inst.m_TessellatorOutputPrimitiveDecl.TessellatorOutputPrimitive));
break;
case D3D11_SB_OPCODE_DCL_HS_MAX_TESSFACTOR:
m_pPR->SetMaxTessellationFactor(Inst.m_HSMaxTessFactorDecl.MaxTessFactor);
break;
case D3D11_SB_OPCODE_HS_CONTROL_POINT_PHASE:
DXASSERT_NOMSG(!m_bControlPointPhase && !bPatchConstantPhase);
m_bControlPointPhase = true;
break;
case D3D11_SB_OPCODE_HS_FORK_PHASE:
case D3D11_SB_OPCODE_HS_JOIN_PHASE:
m_bControlPointPhase = false;
bPatchConstantPhase = true;
m_PatchConstantPhaseInstanceCounts.push_back(1);
break;
case D3D11_SB_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT:
m_PatchConstantPhaseInstanceCounts.back() = Inst.m_HSForkPhaseInstanceCountDecl.InstanceCount;
break;
case D3D11_SB_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT:
m_PatchConstantPhaseInstanceCounts.back() = Inst.m_HSJoinPhaseInstanceCountDecl.InstanceCount;
break;
case D3D11_SB_OPCODE_DCL_THREAD_GROUP:
m_pPR->SetNumThreads(Inst.m_ThreadGroupDecl.x,
Inst.m_ThreadGroupDecl.y,
Inst.m_ThreadGroupDecl.z);
break;
case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW:
case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: {
TGSMEntry E;
E.Id = m_TGSMCount++;
if (Inst.OpCode() == D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW) {
E.Stride = 1;
E.Count = Inst.m_RawTGSMDecl.ByteCount;
} else {
E.Stride = Inst.m_StructuredTGSMDecl.StructByteStride;
E.Count = Inst.m_StructuredTGSMDecl.StructCount;
}
// Declare global variable.
unsigned SizeInBytes = E.Stride*E.Count;
Type *pArrayType = ArrayType::get(Type::getInt8Ty(m_Ctx), SizeInBytes);
E.pVar = new GlobalVariable(*m_pModule, pArrayType,
false, GlobalValue::InternalLinkage,
UndefValue::get(pArrayType),
Twine("TGSM") + Twine(E.Id), nullptr,
GlobalVariable::NotThreadLocal, DXIL::kTGSMAddrSpace);
E.pVar->setAlignment(kRegCompAlignment);
// Mark GV as being used for LLVM.
m_pPR->GetLLVMUsed().push_back(E.pVar);
m_TGSMMap[Inst.m_Operands[0].m_Index[0].m_RegIndex] = E;
break;
}
case D3D11_SB_OPCODE_DCL_GS_INSTANCE_COUNT:
m_pPR->SetGSInstanceCount(Inst.m_GSInstanceCountDecl.InstanceCount);
break;
case D3D10_SB_OPCODE_CUSTOMDATA:
break;
case D3D11_SB_OPCODE_DCL_FUNCTION_BODY: {
DXASSERT_DXBC(Inst.m_NumOperands == 0);
unsigned FBIdx = Inst.m_FunctionBodyDecl.FunctionBodyNumber;
m_InterfaceFunctionBodies[FBIdx].pFunc = nullptr;
break;
}
case D3D11_SB_OPCODE_DCL_FUNCTION_TABLE: {
DXASSERT_DXBC(Inst.m_NumOperands == 0);
auto& FnTable = m_FunctionTables[Inst.m_FunctionTableDecl.FunctionTableNumber];
FnTable.assign(Inst.m_FunctionTableDecl.pFunctionIdentifiers, Inst.m_FunctionTableDecl.pFunctionIdentifiers + Inst.m_FunctionTableDecl.TableLength);
break;
}
case D3D11_SB_OPCODE_DCL_INTERFACE: {
DXASSERT_DXBC(Inst.m_NumOperands == 0);
auto& Iface = m_Interfaces[Inst.m_InterfaceDecl.InterfaceNumber];
Iface.Tables.assign(Inst.m_InterfaceDecl.pFunctionTableIdentifiers, Inst.m_InterfaceDecl.pFunctionTableIdentifiers + Inst.m_InterfaceDecl.TableLength);
#ifdef DBG
for (unsigned TableIdx : Iface.Tables) {
DXASSERT_DXBC(m_FunctionTables[TableIdx].size() == Inst.m_InterfaceDecl.ExpectedTableSize);
}
#endif
Iface.bDynamicallyIndexed = Inst.m_InterfaceDecl.bDynamicallyIndexed;
Iface.NumArrayEntries = Inst.m_InterfaceDecl.ArrayLength;
m_NumIfaces = std::max(m_NumIfaces, Inst.m_InterfaceDecl.InterfaceNumber + Iface.NumArrayEntries);
InsertInterfacesResourceDecls();
break;
}
case D3D10_SB_OPCODE_LABEL: {
m_bControlPointPhase = false;
bPatchConstantPhase = false;
DXASSERT_DXBC(Inst.m_NumOperands == 1);
DXASSERT_DXBC(Inst.m_Operands[0].m_Type == D3D10_SB_OPERAND_TYPE_LABEL ||
Inst.m_Operands[0].m_Type == D3D11_SB_OPERAND_TYPE_FUNCTION_BODY);
FunctionType *pFuncType = FunctionType::get(Type::getVoidTy(m_Ctx), false);
unsigned LabelIdx = Inst.m_Operands[0].m_Index[0].m_RegIndex;
LabelEntry Label;
const bool IsFb = Inst.m_Operands[0].m_Type == D3D11_SB_OPERAND_TYPE_FUNCTION_BODY;
auto& LabelMap = IsFb ? m_InterfaceFunctionBodies : m_Labels;
DXASSERT_DXBC((LabelMap.find(LabelIdx) == LabelMap.end()) == !IsFb); // Function bodies should be pre-declared, labels aren't
Label.pFunc = Function::Create(pFuncType, GlobalValue::LinkageTypes::InternalLinkage,
StringRef(IsFb ? "dx.fb." : "dx.label.") + Twine(LabelIdx), m_pModule.get());
Label.pFunc->setCallingConv(CallingConv::C);
LabelMap[LabelIdx] = Label;
break;
}
default:
break;
}
}
}