in projects/dxilconv/lib/DxbcConverter/DxbcConverter.cpp [5742:6442]
void DxbcConverter::LoadOperand(OperandValue &SrcVal,
D3D10ShaderBinary::CInstruction &Inst,
const unsigned OpIdx,
const CMask &Mask,
const CompType &ValueType) {
D3D10ShaderBinary::COperandBase &O = Inst.m_Operands[OpIdx];
switch (O.m_Type) {
case D3D10_SB_OPERAND_TYPE_IMMEDIATE32:
DXASSERT_DXBC(O.m_Modifier == D3D10_SB_OPERAND_MODIFIER_NONE);
for (BYTE c = 0; c < DXBC::kWidth; c++) {
if (!Mask.IsSet(c)) continue;
bool bVec4 = O.m_NumComponents == D3D10_SB_OPERAND_4_COMPONENT;
BYTE Comp = bVec4 ? c : 0;
switch (ValueType.GetKind()) {
case CompType::Kind::F32:
SrcVal[c] = LoadConstFloat(O.m_Valuef[Comp]);
break;
case CompType::Kind::F16:
SrcVal[c] = CastDxbcValue(LoadConstFloat(O.m_Valuef[Comp]), CompType::Kind::F32, CompType::Kind::F16);
break;
case CompType::Kind::I32: __fallthrough;
case CompType::Kind::U32:
SrcVal[c] = m_pOP->GetU32Const(O.m_Value[Comp]);
break;
case CompType::Kind::I16: __fallthrough;
case CompType::Kind::U16:
SrcVal[c] = CastDxbcValue(m_pOP->GetU32Const(O.m_Value[Comp]), CompType::Kind::U32, CompType::Kind::I16);
break;
case CompType::Kind::I1:
SrcVal[c] = CastDxbcValue(m_pOP->GetU32Const(O.m_Value[Comp]), CompType::Kind::U32, CompType::Kind::I1);
break;
default:
DXASSERT_DXBC(false);
}
}
break;
case D3D10_SB_OPERAND_TYPE_IMMEDIATE64:
DXASSERT_NOMSG(ValueType.GetKind() == CompType::Kind::F64);
for (BYTE c = 0; c < DXBC::kWidth; c += 2) {
if (!Mask.IsSet(c)) continue;
SrcVal[c] = m_pOP->GetDoubleConst(O.m_Valued[c]);
}
break;
case D3D10_SB_OPERAND_TYPE_TEMP: {
DXASSERT_DXBC(O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_1D);
unsigned Reg = O.m_Index[0].m_RegIndex;
CompType DxbcValueType = DXBC::GetCompTypeFromMinPrec(O.m_MinPrecision, ValueType);
if (DxbcValueType.IsBoolTy()) {
DxbcValueType = CompType::getI32();
}
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
if (DxbcValueType.GetKind() != CompType::Kind::F64)
{
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *Args[2];
Args[0] = m_pOP->GetU32Const((unsigned)OP::OpCode::TempRegLoad); // OpCode
Args[1] = m_pOP->GetU32Const(DXBC::GetRegIndex(Reg, Comp)); // Linearized register index
Function *F = m_pOP->GetOpFunc(OP::OpCode::TempRegLoad, pDxbcValueType);
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
} else {
DXASSERT_DXBC(CMask::IsValidDoubleMask(Mask));
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *pValue1, *pValue2;
{
Value *Args[2];
Args[0] = m_pOP->GetU32Const((unsigned)OP::OpCode::TempRegLoad); // OpCode
Args[1] = m_pOP->GetU32Const(DXBC::GetRegIndex(Reg, Comp)); // Linearized register index1
Function *F = m_pOP->GetOpFunc(OP::OpCode::TempRegLoad, CompType::getU32().GetLLVMType(m_Ctx));
pValue1 = m_pBuilder->CreateCall(F, Args);
Args[1] = m_pOP->GetU32Const(DXBC::GetRegIndex(Reg, Comp+1)); // Linearized register index2
pValue2 = m_pBuilder->CreateCall(F, Args);
}
Value *pValue;
{
Value *Args[3];
Function *F = m_pOP->GetOpFunc(OP::OpCode::MakeDouble, pDxbcValueType);
Args[0] = m_pOP->GetU32Const((unsigned)OP::OpCode::MakeDouble); // OpCode
Args[1] = pValue1; // Lo part
Args[2] = pValue2; // Hi part
pValue = m_pBuilder->CreateCall(F, Args);
pValue = ApplyOperandModifiers(pValue, O);
}
OVH.SetValue(pValue);
OVH.Advance();
}
}
break;
}
case D3D10_SB_OPERAND_TYPE_INDEXABLE_TEMP: {
DXASSERT_DXBC(O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_2D);
DXASSERT_DXBC(O.m_IndexType[0] == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
unsigned Reg = O.m_Index[0].m_RegIndex;
IndexableReg &IRRec = m_IndexableRegs[Reg];
Value *pXRegIndex = LoadOperandIndex(O.m_Index[1], O.m_IndexType[1]);
Value *pRegIndex = m_pBuilder->CreateMul(pXRegIndex, m_pOP->GetI32Const(IRRec.NumComps));
CompType DxbcValueType = DXBC::GetCompTypeFromMinPrec(O.m_MinPrecision, ValueType);
if (DxbcValueType.IsBoolTy()) {
DxbcValueType = CompType::getI32();
}
if (DxbcValueType.GetKind() != CompType::Kind::F64) {
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *pValue = nullptr;
// Create GEP.
Value *pIndex = m_pBuilder->CreateAdd(pRegIndex, m_pOP->GetU32Const(Comp));
Value *pGEPIndices[2] = { m_pOP->GetU32Const(0), pIndex };
if (!DxbcValueType.HasMinPrec()) {
Value *pBasePtr = m_IndexableRegs[Reg].pValue32;
Value *pPtr = m_pBuilder->CreateGEP(pBasePtr, pGEPIndices);
pValue = m_pBuilder->CreateAlignedLoad(pPtr, kRegCompAlignment);
pValue = CastDxbcValue(pValue, CompType::getF32(), ValueType);
} else {
// Create GEP.
Value *pBasePtr = m_IndexableRegs[Reg].pValue16;
Value *pPtr = m_pBuilder->CreateGEP(pBasePtr, pGEPIndices);
pValue = m_pBuilder->CreateAlignedLoad(pPtr, kRegCompAlignment/2);
pValue = CastDxbcValue(pValue, CompType::getF16(), ValueType);
}
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
} else {
// Double precision.
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *pValue = nullptr;
// Create GEP.
Value *pIndex = m_pBuilder->CreateAdd(pRegIndex, m_pOP->GetU32Const(Comp));
Value *pGEPIndices[1] = { pIndex };
Value *pBasePtr = m_pBuilder->CreateBitCast(m_IndexableRegs[Reg].pValue32, Type::getDoublePtrTy(m_Ctx));
Value *pPtr = m_pBuilder->CreateGEP(pBasePtr, pGEPIndices);
pValue = m_pBuilder->CreateAlignedLoad(pPtr, kRegCompAlignment*2);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
OVH.Advance();
OVH.SetValue(pValue);
}
}
break;
}
case D3D10_SB_OPERAND_TYPE_INPUT:
case D3D11_SB_OPERAND_TYPE_INPUT_CONTROL_POINT: {
OP::OpCode OpCode = OP::OpCode::LoadInput;
unsigned Register; // Starting index of the register range.
Value *pUnitIndexValue; // Vertex/point index expression.
Value *pRowIndexValue; // Row index expression.
switch (O.m_IndexDimension) {
case D3D10_SB_OPERAND_INDEX_1D:
Register = O.m_Index[0].m_RegIndex;
pUnitIndexValue = m_pUnusedI32;
pRowIndexValue = LoadOperandIndex(O.m_Index[0], O.m_IndexType[0]);
break;
case D3D10_SB_OPERAND_INDEX_2D:
// 2D input register index: <index1, input register index>.
// index1: GS -- vertex index, DS -- input control point index.
Register = O.m_Index[1].m_RegIndex;
pUnitIndexValue = LoadOperandIndex(O.m_Index[0], O.m_IndexType[0]);
pRowIndexValue = LoadOperandIndex(O.m_Index[1], O.m_IndexType[1]);
break;
default:
DXASSERT(false, "there should no other index dimensions");
}
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
// Retrieve signature element.
const DxilSignatureElement *E = m_pInputSignature->GetElement(Register, Comp);
CompType DxbcValueType = E->GetCompType();
if (DxbcValueType.IsBoolTy()) {
DxbcValueType = CompType::getI32();
}
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
MutableArrayRef<Value *> Args;
Value *Args1[1];
Value *Args5[5];
if (E->GetKind() == DXIL::SemanticKind::SampleIndex) {
// Use SampleIndex intrinsic instead of LoadInput
Args = Args1;
OpCode = OP::OpCode::SampleIndex;
} else {
Args = Args5;
// Make row/col index relative within element.
Value *pRowIndexValueRel = m_pBuilder->CreateSub(pRowIndexValue, m_pOP->GetU32Const(E->GetStartRow()));
Args[1] = m_pOP->GetU32Const(E->GetID()); // Input signature element ID
Args[2] = pRowIndexValueRel; // Row, relative to the element
Args[3] = m_pOP->GetU8Const(Comp - E->GetStartCol()); // Col, relative to the element
Args[4] = pUnitIndexValue; // Vertex/point index
}
Args[0] = m_pOP->GetU32Const((unsigned)OpCode); // OpCode
Function *F = m_pOP->GetOpFunc(OpCode, pDxbcValueType);
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
break;
}
case D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER: {
// Upconvert operand to SM5.1.
if (O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_2D) {
O.m_IndexDimension = D3D10_SB_OPERAND_INDEX_3D;
O.m_IndexType[2] = O.m_IndexType[1];
O.m_Index[2] = O.m_Index[1];
O.m_IndexType[1] = O.m_IndexType[0];
O.m_Index[1] = O.m_Index[0];
}
// Retrieve cbuffer range ID and record.
const DxilCBuffer* pR = m_pClassInstanceCBuffers;
if (O.m_IndexType[0] == D3D10_SB_OPERAND_INDEX_IMMEDIATE32) {
unsigned RangeID = O.m_Index[0].m_RegIndex;
unsigned RecIdx = m_CBufferRangeMap[RangeID];
pR = &m_pPR->GetCBuffer(RecIdx);
}
const DxilCBuffer &R = *pR;
// Setup cbuffer handle.
Value *pHandle = GetCachedHandle(R);
if (pHandle == nullptr) {
// Create dynamic-index handle.
pHandle = CreateHandle(R.GetClass(), R.GetID(), LoadOperandIndex(O.m_Index[1], O.m_IndexType[1]), O.m_Nonuniform);
}
// Load values for unique components.
Value *pRegIndexValue = LoadOperandIndex(O.m_Index[2], O.m_IndexType[2]);
CompType DxbcValueType = ValueType.GetBaseCompType();
if (DxbcValueType.IsBoolTy()) {
DxbcValueType = CompType::getI32();
}
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
DXASSERT_NOMSG(m_bLegacyCBufferLoad);
Value *Args[3];
Args[0] = m_pOP->GetU32Const((unsigned)OP::OpCode::CBufferLoadLegacy); // OpCode
Args[1] = pHandle; // CBuffer handle
Args[2] = pRegIndexValue; // 0-based index into cbuffer instance
Function *pCBufferLoadFunc = m_pOP->GetOpFunc(OP::OpCode::CBufferLoadLegacy, pDxbcValueType);
Value *pCBufferRetValue = m_pBuilder->CreateCall(pCBufferLoadFunc, Args);
if (ValueType.GetKind() != CompType::Kind::F64) {
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *pValue = m_pBuilder->CreateExtractValue(pCBufferRetValue, Comp);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
} else {
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp() / 2;
Value *pValue = m_pBuilder->CreateExtractValue(pCBufferRetValue, Comp);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
OVH.Advance();
OVH.SetValue(pValue);
}
}
break;
}
case D3D10_SB_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER: {
DXASSERT_DXBC(O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_1D);
Value *pRegIndex = LoadOperandIndex(O.m_Index[0], O.m_IndexType[0]);
if (ValueType.GetKind() != CompType::Kind::F64) {
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *pValueIndex = m_pBuilder->CreateMul(pRegIndex, m_pOP->GetI32Const(DXBC::kWidth));
pValueIndex = m_pBuilder->CreateAdd(pValueIndex, m_pOP->GetI32Const(Comp));
// Create GEP.
Value *pGEPIndices[2] = { m_pOP->GetU32Const(0), pValueIndex };
Value *pPtr = m_pBuilder->CreateGEP(m_pIcbGV, pGEPIndices);
LoadInst *pLoad = m_pBuilder->CreateLoad(pPtr);
pLoad->setAlignment(kRegCompAlignment);
Value *pValue = CastDxbcValue(pLoad, CompType::getF32(), ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
} else {
// Double precision ICB.
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *pValueIndex = m_pBuilder->CreateMul(pRegIndex, m_pOP->GetI32Const(DXBC::kWidth));
pValueIndex = m_pBuilder->CreateAdd(pValueIndex, m_pOP->GetI32Const(Comp));
// Bitcast pointer.
Value *pPtrBase = m_pBuilder->CreateBitCast(m_pIcbGV, Type::getDoublePtrTy(m_Ctx));
// Create GEP.
Value *pGEPIndices[1] = { pValueIndex };
Value *pPtr = m_pBuilder->CreateGEP(pPtrBase, pGEPIndices);
LoadInst *pLoad = m_pBuilder->CreateLoad(pPtr);
pLoad->setAlignment(kRegCompAlignment*2);
Value *pValue = pLoad;
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
OVH.Advance();
OVH.SetValue(pValue);
}
}
break;
}
case D3D10_SB_OPERAND_TYPE_SAMPLER: {
// Upconvert operand to SM5.1.
if (O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_1D) {
O.m_IndexDimension = D3D10_SB_OPERAND_INDEX_2D;
O.m_IndexType[1] = O.m_IndexType[0];
O.m_Index[1] = O.m_Index[0];
}
// Retrieve sampler range ID and record.
const DxilSampler* pR = nullptr;
if (O.m_IndexType[0] == D3D10_SB_OPERAND_INDEX_IMMEDIATE32) {
unsigned RangeID = O.m_Index[0].m_RegIndex;
unsigned RecIdx = m_SamplerRangeMap[RangeID];
pR = &m_pPR->GetSampler(RecIdx);
}
else {
switch (Inst.OpCode()) {
case D3D10_SB_OPCODE_SAMPLE_C:
case D3D10_SB_OPCODE_SAMPLE_C_LZ:
case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_CLAMP_FEEDBACK:
case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_LZ_FEEDBACK:
case D3D11_SB_OPCODE_GATHER4_PO_C:
case D3DWDDM1_3_SB_OPCODE_GATHER4_PO_C_FEEDBACK:
pR = m_pClassInstanceComparisonSamplers;
break;
default:
pR = m_pClassInstanceSamplers;
break;
}
}
const DxilSampler &R = *pR;
// Setup sampler handle.
Value *pHandle = GetCachedHandle(R);
if (pHandle == nullptr) {
// Create dynamic-index handle.
pHandle = CreateHandle(R.GetClass(), R.GetID(), LoadOperandIndex(O.m_Index[1], O.m_IndexType[1]), O.m_Nonuniform);
}
// Replicate handle values.
for (BYTE c = 0; c < DXBC::kWidth; c++) {
if (Mask.IsSet(c))
SrcVal[c] = pHandle;
}
break;
}
case D3D10_SB_OPERAND_TYPE_RESOURCE: {
(void)LoadSRVOperand(SrcVal, Inst, OpIdx, Mask, ValueType);
break;
}
case D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW: {
// Upconvert operand to SM5.1.
if (O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_1D) {
DXASSERT_DXBC(O.m_IndexType[0] == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
O.m_IndexDimension = D3D10_SB_OPERAND_INDEX_2D;
O.m_IndexType[1] = O.m_IndexType[0];
O.m_Index[1] = O.m_Index[0];
}
// Retrieve UAV range ID and record.
DXASSERT_DXBC(O.m_IndexType[0] == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
unsigned RangeID = O.m_Index[0].m_RegIndex;
unsigned RecIdx = m_UAVRangeMap[RangeID];
const DxilResource &R = m_pPR->GetUAV(RecIdx);
// Setup UAV handle.
Value *pHandle = GetCachedHandle(R);
if (pHandle == nullptr) {
DXASSERT(IsSM51Plus(), "otherwise did not initialize handles on entry to main");
// Create dynamic-index handle.
pHandle = CreateHandle(R.GetClass(), R.GetID(), LoadOperandIndex(O.m_Index[1], O.m_IndexType[1]), O.m_Nonuniform);
}
// Replicate handle values.
for (BYTE c = 0; c < DXBC::kWidth; c++) {
if (Mask.IsSet(c))
SrcVal[c] = pHandle;
}
break;
}
case D3D10_SB_OPERAND_TYPE_RASTERIZER: {
DXASSERT_DXBC(O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_0D);
DXASSERT_DXBC(false); // "rasterizer" register is not used in DXIL.
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: {
OP::OpCode OpCode;
switch (O.m_Type) {
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID: OpCode = OP::OpCode::ThreadId; break;
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_GROUP_ID: OpCode = OP::OpCode::GroupId; break;
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP: OpCode = OP::OpCode::ThreadIdInGroup; break;
}
CompType DxbcValueType = CompType::Kind::I32;
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
Function *F = m_pOP->GetOpFunc(OpCode, pDxbcValueType);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *Args[2];
Args[0] = m_pOP->GetU32Const((unsigned)OpCode); // OpCode
Args[1] = m_pOP->GetU32Const(Comp); // Component: x,y,z
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
break;
}
case D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED: {
OP::OpCode OpCode = OP::OpCode::FlattenedThreadIdInGroup;
CompType DxbcValueType = CompType::Kind::I32;
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
Function *F = m_pOP->GetOpFunc(OpCode, pDxbcValueType);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
Value *Args[1];
Args[0] = m_pOP->GetU32Const((unsigned)OpCode); // OpCode
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
break;
}
case D3D11_SB_OPERAND_TYPE_INPUT_PATCH_CONSTANT: {
DXASSERT_DXBC(O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_1D);
unsigned Register = O.m_Index[0].m_RegIndex;
Value *pRowIndexValue = LoadOperandIndex(O.m_Index[0], O.m_IndexType[0]);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
// Retrieve signature element.
const DxilSignatureElement *E = m_pPatchConstantSignature->GetElement(Register, Comp);
CompType DxbcValueType = E->GetCompType();
if (DxbcValueType.IsBoolTy()) {
DxbcValueType = CompType::getI32();
}
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
// Make row/col index relative within element.
Value *pRowIndexValueRel = m_pBuilder->CreateSub(pRowIndexValue, m_pOP->GetU32Const(E->GetStartRow()));
Value *Args[4];
Args[0] = m_pOP->GetU32Const((unsigned)OP::OpCode::LoadPatchConstant); // OpCode
Args[1] = m_pOP->GetU32Const(E->GetID()); // Patch constant signature element ID
Args[2] = pRowIndexValueRel; // Row, relative to the element
Args[3] = m_pOP->GetU8Const(Comp - E->GetStartCol()); // Col, relative to the element
Function *F = m_pOP->GetOpFunc(OP::OpCode::LoadPatchConstant, pDxbcValueType);
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
break;
}
case D3D11_SB_OPERAND_TYPE_OUTPUT_CONTROL_POINT: {
DXASSERT_DXBC(O.m_IndexDimension == D3D10_SB_OPERAND_INDEX_2D);
OP::OpCode OpCode = OP::OpCode::LoadOutputControlPoint;
unsigned Register = O.m_Index[1].m_RegIndex; // Starting index of the register range.
Value *pUnitIndexValue = LoadOperandIndex(O.m_Index[0], O.m_IndexType[0]); // Vertex/point index expression.
Value *pRowIndexValue = LoadOperandIndex(O.m_Index[1], O.m_IndexType[1]); // Row index expression.
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
// Retrieve signature element.
const DxilSignatureElement *E = m_pOutputSignature->GetElement(Register, Comp);
CompType DxbcValueType = E->GetCompType();
if (DxbcValueType.IsBoolTy()) {
DxbcValueType = CompType::getI32();
}
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
// Make row/col index relative within element.
Value *pRowIndexValueRel = m_pBuilder->CreateSub(pRowIndexValue, m_pOP->GetU32Const(E->GetStartRow()));
Value *Args[5];
Args[0] = m_pOP->GetU32Const((unsigned)OpCode); // OpCode
Args[1] = m_pOP->GetU32Const(E->GetID()); // Output signature element ID
Args[2] = pRowIndexValueRel; // Row, relative to the element
Args[3] = m_pOP->GetU8Const(Comp - E->GetStartCol()); // Col, relative to the element
Args[4] = pUnitIndexValue; // Vertex/point index
Function *F = m_pOP->GetOpFunc(OpCode, pDxbcValueType);
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
break;
}
case D3D11_SB_OPERAND_TYPE_INPUT_DOMAIN_POINT: {
OP::OpCode OpCode = OP::OpCode::DomainLocation;
CompType DxbcValueType = CompType::Kind::F32;
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
Function *F = m_pOP->GetOpFunc(OpCode, pDxbcValueType);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *Args[2];
Args[0] = m_pOP->GetU32Const((unsigned)OpCode); // OpCode
Args[1] = m_pOP->GetU8Const(Comp); // Component
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
break;
}
case D3D11_SB_OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID:
case D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID:
case D3D11_SB_OPERAND_TYPE_INPUT_GS_INSTANCE_ID:
case D3D11_SB_OPERAND_TYPE_INPUT_COVERAGE_MASK:
case D3D11_SB_OPERAND_TYPE_INNER_COVERAGE: {
OP::OpCode OpCode;
switch (O.m_Type) {
case D3D11_SB_OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID: OpCode = OP::OpCode::OutputControlPointID; break;
case D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID: OpCode = OP::OpCode::PrimitiveID; break;
case D3D11_SB_OPERAND_TYPE_INPUT_GS_INSTANCE_ID: OpCode = OP::OpCode::GSInstanceID; break;
case D3D11_SB_OPERAND_TYPE_INPUT_COVERAGE_MASK: OpCode = OP::OpCode::Coverage; break;
case D3D11_SB_OPERAND_TYPE_INNER_COVERAGE: OpCode = OP::OpCode::InnerCoverage; break;
}
CompType DxbcValueType = CompType::Kind::I32;
Type *pDxbcValueType = DxbcValueType.GetLLVMType(m_Ctx);
Function *F = m_pOP->GetOpFunc(OpCode, pDxbcValueType);
Value *Args[1];
Args[0] = m_pOP->GetU32Const((unsigned)OpCode); // OpCode
Value *pValue = m_pBuilder->CreateCall(F, Args);
pValue = CastDxbcValue(pValue, DxbcValueType, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
OVH.SetValue(pValue);
}
break;
}
case D3D11_SB_OPERAND_TYPE_CYCLE_COUNTER: {
OP::OpCode OpCode = OP::OpCode::CycleCounterLegacy;
Function *F = m_pOP->GetOpFunc(OpCode, Type::getVoidTy(m_Ctx));
Value *Args[1];
Args[0] = m_pOP->GetU32Const((unsigned)OpCode); // OpCode
Value *pValue = m_pBuilder->CreateCall(F, Args);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE c = OVH.GetComp();
switch (c) {
case 0: {
Value *pLo32 = m_pBuilder->CreateExtractValue(pValue, 0);
pLo32 = CastDxbcValue(pLo32, CompType::Kind::I32, ValueType);
OVH.SetValue(pLo32);
break;
}
case 1: {
Value *pHi32 = m_pBuilder->CreateExtractValue(pValue, 1);
pHi32 = CastDxbcValue(pHi32, CompType::Kind::I32, ValueType);
OVH.SetValue(pHi32);
break;
}
default:
OVH.SetValue(m_pOP->GetU32Const(0));
}
}
break;
}
case D3D11_SB_OPERAND_TYPE_INPUT_FORK_INSTANCE_ID:
case D3D11_SB_OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID: {
Scope &HullScope = m_ScopeStack.FindParentHullLoop();
Value *pValue = m_pBuilder->CreateLoad(HullScope.pInductionVar);
pValue = ApplyOperandModifiers(pValue, O);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
OVH.SetValue(pValue);
}
break;
}
case D3D11_SB_OPERAND_TYPE_THIS_POINTER: {
Value *pIfaceIdx = LoadOperandIndex(O.m_Index[0], O.m_IndexType[0]);
// The CBuffer layout here is a UINT for the interface class type selection, then 3 UINTs padding, per interface.
// After that, there's another 4 UINTs per interface which defines the "this" pointer data.
// Note, legacy CBuffer loads address their data in number of 4-float constants, not bytes or single elements.
// Since the "this" data comes after 4 UINTs per interface, adjust the CB offset just by the number of interfaces.
Value* pCBOffset = m_pBuilder->CreateAdd(m_pOP->GetU32Const(m_NumIfaces), pIfaceIdx);
Value *Args[3];
Args[0] = m_pOP->GetU32Const((unsigned)OP::OpCode::CBufferLoadLegacy); // OpCode
Args[1] = CreateHandle(m_pInterfaceDataBuffer->GetClass(),
m_pInterfaceDataBuffer->GetID(),
m_pOP->GetU32Const(m_pInterfaceDataBuffer->GetLowerBound()),
false /*Nonuniform*/); // CBuffer handle
Args[2] = pCBOffset; // 0-based index into cbuffer instance
Function *pCBufferLoadFunc = m_pOP->GetOpFunc(OP::OpCode::CBufferLoadLegacy, Type::getInt32Ty(m_Ctx));
Value* pCBufferRetValue = m_pBuilder->CreateCall(pCBufferLoadFunc, Args);
for (OperandValueHelper OVH(SrcVal, Mask, O); !OVH.IsDone(); OVH.Advance()) {
BYTE Comp = OVH.GetComp();
Value *pValue = m_pBuilder->CreateExtractValue(pCBufferRetValue, Comp);
pValue = CastDxbcValue(pValue, CompType::Kind::I32, ValueType);
pValue = ApplyOperandModifiers(pValue, O);
OVH.SetValue(pValue);
}
break;
}
default:
DXASSERT_ARGS(false, "Operand type %u is not yet implemented", O.m_Type);
}
}