Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/DXIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3088,7 +3088,7 @@ INSTR.MIPLEVELFORGETDIMENSION Use mip level on buffer when GetDimens
INSTR.MIPONUAVLOAD uav load don't support mipLevel/sampleIndex.
INSTR.MISSINGSETMESHOUTPUTCOUNTS Missing SetMeshOutputCounts call.
INSTR.MULTIPLEGETMESHPAYLOAD GetMeshPayload cannot be called multiple times.
INSTR.MULTIPLESETMESHOUTPUTCOUNTS SetMeshOUtputCounts cannot be called multiple times.
INSTR.MULTIPLESETMESHOUTPUTCOUNTS SetMeshOutputCounts cannot be called multiple times.
INSTR.NODERECORDHANDLEUSEAFTERCOMPLETE Invalid use of completed record handle.
INSTR.NOGENERICPTRADDRSPACECAST Address space cast between pointer types must have one part to be generic address space.
INSTR.NOIDIVBYZERO No signed integer division by zero.
Expand Down
10 changes: 7 additions & 3 deletions include/dxc/DXIL/DxilFunctionProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,6 @@ struct DxilFunctionProps {
unsigned MaxDispatchGrid[3];
unsigned MaxRecursionDepth;
// BEGIN experimental mesh node properties
DXIL::MeshOutputTopology OutputTopology;
unsigned MaxVertexCount;
unsigned MaxPrimitiveCount;
unsigned MaxInputRecordsPerGraphEntryRecord;
bool MaxInputRecSharedAcrossNodeArray;
// END experimental mesh node properties
Expand Down Expand Up @@ -238,6 +235,13 @@ struct DxilFunctionProps {
return shaderKind == DXIL::ShaderKind::Node ||
Node.LaunchType != DXIL::NodeLaunchType::Invalid;
};
bool IsMeshNode() const {
return shaderKind == DXIL::ShaderKind::Node &&
Node.LaunchType == DXIL::NodeLaunchType::Mesh;
};
bool UsesPatchConstOrPrimSignature() {
return IsHS() || IsDS() || IsMS() || IsMeshNode();
}
};

} // namespace hlsl
2 changes: 2 additions & 0 deletions include/dxc/DXIL/DxilSigPoint.inl
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,8 @@ DXIL::SigPointKind SigPoint::GetKind(DXIL::ShaderKind shaderKind,
}
break;
case DXIL::ShaderKind::Mesh:
// Assuming mesh node
case DXIL::ShaderKind::Node:
switch (sigKind) {
case DXIL::SignatureKind::Input:
return DXIL::SigPointKind::MSIn;
Expand Down
44 changes: 24 additions & 20 deletions lib/DXIL/DxilMetadataHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1902,18 +1902,16 @@ void DxilMDHelper::LoadDxilEntryProperties(const MDOperand &MDO,
} break;
case DxilMDHelper::kDxilNodeMeshOutputTopologyTag: {
hasNodeTag = true;
auto &Node = props.Node;
Node.OutputTopology = (DXIL::MeshOutputTopology)ConstMDToUint32(MDO);
props.ShaderProps.MS.outputTopology =
(DXIL::MeshOutputTopology)ConstMDToUint32(MDO);
} break;
case DxilMDHelper::kDxilNodeMeshMaxVertexCountTag: {
hasNodeTag = true;
auto &Node = props.Node;
Node.MaxVertexCount = ConstMDToUint32(MDO);
props.ShaderProps.MS.maxVertexCount = ConstMDToUint32(MDO);
} break;
case DxilMDHelper::kDxilNodeMeshMaxPrimitiveCountTag: {
hasNodeTag = true;
auto &Node = props.Node;
Node.MaxPrimitiveCount = ConstMDToUint32(MDO);
props.ShaderProps.MS.maxPrimitiveCount = ConstMDToUint32(MDO);
} break;
case DxilMDHelper::kDxilNodeMaxInputRecordsPerGraphEntryRecordTag: {
hasNodeTag = true;
Expand Down Expand Up @@ -1981,10 +1979,12 @@ void DxilMDHelper::SerializeNodeProps(SmallVectorImpl<llvm::Metadata *> &MDVals,
MDVals.push_back(Uint32ToConstMD(NodeProps.MaxDispatchGrid[1]));
MDVals.push_back(Uint32ToConstMD(NodeProps.MaxDispatchGrid[2]));
MDVals.push_back(Uint32ToConstMD(NodeProps.MaxRecursionDepth));
if (DXIL::CompareVersions(m_MinValMajor, m_MinValMinor, 1, 9) >= 0) {
MDVals.emplace_back(Uint32ToConstMD((unsigned)NodeProps.OutputTopology));
MDVals.emplace_back(Uint32ToConstMD(NodeProps.MaxVertexCount));
MDVals.emplace_back(Uint32ToConstMD(NodeProps.MaxPrimitiveCount));
if (props->IsMeshNode()) {
MDVals.emplace_back(
Uint32ToConstMD((unsigned)props->ShaderProps.MS.outputTopology));
MDVals.emplace_back(Uint32ToConstMD(props->ShaderProps.MS.maxVertexCount));
MDVals.emplace_back(
Uint32ToConstMD(props->ShaderProps.MS.maxPrimitiveCount));
MDVals.push_back(
Uint32ToConstMD(NodeProps.MaxInputRecordsPerGraphEntryRecord));
MDVals.push_back(BoolToConstMD(NodeProps.MaxInputRecSharedAcrossNodeArray));
Expand Down Expand Up @@ -2042,11 +2042,13 @@ void DxilMDHelper::DeserializeNodeProps(const MDTuple *pProps, unsigned &idx,
NodeProps.MaxDispatchGrid[1] = ConstMDToUint32(pProps->getOperand(idx++));
NodeProps.MaxDispatchGrid[2] = ConstMDToUint32(pProps->getOperand(idx++));
NodeProps.MaxRecursionDepth = ConstMDToUint32(pProps->getOperand(idx++));
if (DXIL::CompareVersions(m_MinValMajor, m_MinValMinor, 1, 9) >= 0) {
NodeProps.OutputTopology =
if (props->IsMeshNode()) {
props->ShaderProps.MS.outputTopology =
(DXIL::MeshOutputTopology)ConstMDToUint32(pProps->getOperand(idx++));
NodeProps.MaxVertexCount = ConstMDToUint32(pProps->getOperand(idx++));
NodeProps.MaxPrimitiveCount = ConstMDToUint32(pProps->getOperand(idx++));
props->ShaderProps.MS.maxVertexCount =
ConstMDToUint32(pProps->getOperand(idx++));
props->ShaderProps.MS.maxPrimitiveCount =
ConstMDToUint32(pProps->getOperand(idx++));
NodeProps.MaxInputRecordsPerGraphEntryRecord =
ConstMDToUint32(pProps->getOperand(idx++));
NodeProps.MaxInputRecSharedAcrossNodeArray =
Expand Down Expand Up @@ -2791,22 +2793,24 @@ void DxilMDHelper::EmitDxilNodeState(std::vector<llvm::Metadata *> &MDVals,
}

// Experimental mesh node shader properties
if (Node.OutputTopology != DXIL::MeshOutputTopology::Undefined) {
if (props.IsMeshNode()) {
MDVals.emplace_back(
Uint32ToConstMD(DxilMDHelper::kDxilNodeMeshOutputTopologyTag));
MDVals.emplace_back(Uint32ToConstMD((unsigned)Node.OutputTopology));
MDVals.emplace_back(
Uint32ToConstMD((unsigned)props.ShaderProps.MS.outputTopology));
}

if (Node.MaxVertexCount > 0) {
if (props.ShaderProps.MS.maxVertexCount > 0) {
MDVals.emplace_back(
Uint32ToConstMD(DxilMDHelper::kDxilNodeMeshMaxVertexCountTag));
MDVals.emplace_back(Uint32ToConstMD(Node.MaxVertexCount));
MDVals.emplace_back(Uint32ToConstMD(props.ShaderProps.MS.maxVertexCount));
}

if (Node.MaxPrimitiveCount > 0) {
if (props.ShaderProps.MS.maxPrimitiveCount > 0) {
MDVals.emplace_back(
Uint32ToConstMD(DxilMDHelper::kDxilNodeMeshMaxPrimitiveCountTag));
MDVals.emplace_back(Uint32ToConstMD(Node.MaxPrimitiveCount));
MDVals.emplace_back(
Uint32ToConstMD(props.ShaderProps.MS.maxPrimitiveCount));
}

if (Node.MaxInputRecordsPerGraphEntryRecord) {
Expand Down
3 changes: 1 addition & 2 deletions lib/DXIL/DxilModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2344,8 +2344,7 @@ void DxilModule::UpdateFunctionToShaderCompat(const llvm::Function *dxilFunc) {
if (DXIL::OpCode::SetMeshOutputCounts == OP::GetDxilOpFuncCallInst(CI) &&
HasDxilFunctionProps(F)) {
const DxilFunctionProps &props = GetDxilFunctionProps(F);
if (props.shaderKind != DXIL::ShaderKind::Node ||
props.Node.LaunchType != DXIL::NodeLaunchType::Mesh)
if (!props.IsMeshNode())
mask &= ~SFLAG(Node);
}
info.mask &= mask;
Expand Down
10 changes: 5 additions & 5 deletions lib/DXIL/DxilOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3251,16 +3251,16 @@ void OP::GetMinShaderModelAndMask(OpCode C, bool bWithTranslation,
mask = SFLAG(Library) | SFLAG(Pixel);
return;
}
// Instructions: EmitIndices=169, GetMeshPayload=170, StoreVertexOutput=171,
// StorePrimitiveOutput=172
if ((169 <= op && op <= 172)) {
// Instructions: GetMeshPayload=170
if (op == 170) {
major = 6;
minor = 5;
mask = SFLAG(Mesh);
return;
}
// Instructions: SetMeshOutputCounts=168
if (op == 168) {
// Instructions: SetMeshOutputCounts=168, EmitIndices=169,
// StoreVertexOutput=171, StorePrimitiveOutput=172
if ((168 <= op && op <= 169) || (171 <= op && op <= 172)) {
major = 6;
minor = 5;
mask = SFLAG(Mesh) | SFLAG(Node);
Expand Down
2 changes: 2 additions & 0 deletions lib/DXIL/DxilTypeSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,8 @@ DXIL::SigPointKind SigPointFromInputQual(DxilParamInputQual Q,
}
break;
case DXIL::ShaderKind::Mesh:
// assuming mesh node, wouldn't be here otherwise
case DXIL::ShaderKind::Node:
switch (Q) {
case DxilParamInputQual::In:
case DxilParamInputQual::InPayload:
Expand Down
9 changes: 5 additions & 4 deletions lib/DxilContainer/DxilContainerAssembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1656,13 +1656,14 @@ class DxilRDATWriter : public DxilPartWriter {
funcAttribs.push_back(Builder.InsertRecord(nAttrib));
}

if (props.Node.OutputTopology != DXIL::MeshOutputTopology::Undefined) {
if (props.Node.LaunchType == NodeLaunchType::Mesh) {
nAttrib = {};
nAttrib.AttribKind = (uint32_t)RDAT::NodeFuncAttribKind::MeshShaderInfo;
RDAT::MSInfo info = {};
info.MeshOutputTopology = (uint8_t)props.Node.OutputTopology;
info.MaxOutputVertices = (uint16_t)props.Node.MaxVertexCount;
info.MaxOutputPrimitives = (uint16_t)props.Node.MaxPrimitiveCount;
info.MeshOutputTopology = (uint8_t)props.ShaderProps.MS.outputTopology;
info.MaxOutputVertices = (uint16_t)props.ShaderProps.MS.maxVertexCount;
info.MaxOutputPrimitives =
(uint16_t)props.ShaderProps.MS.maxPrimitiveCount;
nAttrib.MeshShaderInfo = Builder.InsertRecord(info);
funcAttribs.push_back(Builder.InsertRecord(nAttrib));
}
Expand Down
15 changes: 8 additions & 7 deletions lib/HLSL/DxilValidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1463,8 +1463,7 @@ static void ValidateSignatureDxilOp(CallInst *CI, DXIL::OpCode opcode,
}
} break;
case DXIL::OpCode::SetMeshOutputCounts: {
if (!props.IsMS() && (!props.IsNode() || props.Node.LaunchType !=
DXIL::NodeLaunchType::Mesh)) {
if (!props.IsMS() && !props.IsMeshNode()) {
ValCtx.EmitInstrFormatError(CI, ValidationRule::SmOpcodeInInvalidFunction,
{"SetMeshOutputCounts", "Mesh shader"});
}
Expand Down Expand Up @@ -2797,10 +2796,7 @@ static void ValidateMsIntrinsics(Function *F, ValidationContext &ValCtx,
CallInst *getMeshPayload) {
if (ValCtx.DxilMod.HasDxilFunctionProps(F)) {
DxilFunctionProps &props = ValCtx.DxilMod.GetDxilFunctionProps(F);
DXIL::ShaderKind shaderKind = props.shaderKind;
if (shaderKind != DXIL::ShaderKind::Mesh &&
(shaderKind != DXIL::ShaderKind::Node ||
props.Node.LaunchType != DXIL::NodeLaunchType::Mesh))
if (!props.IsMS() && !props.IsMeshNode())
return;
} else {
return;
Expand Down Expand Up @@ -5170,6 +5166,7 @@ static void ValidateEntrySignatures(ValidationContext &ValCtx,
bool isGS = props.IsGS();
bool isCS = props.IsCS();
bool isMS = props.IsMS();
bool isMN = props.IsMeshNode();

if (isPS) {
// PS output no interp mode.
Expand All @@ -5179,7 +5176,7 @@ static void ValidateEntrySignatures(ValidationContext &ValCtx,
ValidateNoInterpModeSignature(ValCtx, S.InputSignature);
}

if (isMS) {
if (isMS || isMN) {
// primitive output constant interp mode.
ValidateConstantInterpModeSignature(ValCtx, S.PatchConstOrPrimSignature);
} else {
Expand All @@ -5204,6 +5201,10 @@ static void ValidateEntrySignatures(ValidationContext &ValCtx,
maxOutputScalars = DXIL::kMaxOutputTotalScalars;
maxPatchConstantScalars = DXIL::kMaxHSOutputPatchConstantTotalScalars;
break;
case DXIL::ShaderKind::Node:
if (!isMN)
break;
LLVM_FALLTHROUGH;
case DXIL::ShaderKind::Mesh:
maxOutputScalars = DXIL::kMaxOutputTotalScalars;
maxPatchConstantScalars = DXIL::kMaxOutputTotalScalars;
Expand Down
44 changes: 28 additions & 16 deletions lib/HLSL/HLSignatureLower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 +467,13 @@ void HLSignatureLower::CreateDxilSignatures() {
if (HLModule::IsStreamOutputPtrType(Ty))
continue;

// Skip OutIndices and InPayload
// Skip OutIndices, InPayload, and NodeIO
DxilParameterAnnotation &paramAnnotation =
EntryAnnotation->GetParameterAnnotation(arg.getArgNo());
hlsl::DxilParamInputQual qual = paramAnnotation.GetParamInputQual();
if (qual == hlsl::DxilParamInputQual::OutIndices ||
qual == hlsl::DxilParamInputQual::InPayload)
qual == hlsl::DxilParamInputQual::InPayload ||
qual == hlsl::DxilParamInputQual::NodeIO)
continue;

ProcessArgument(Entry, EntryAnnotation, arg, props, pSM,
Expand Down Expand Up @@ -523,17 +524,15 @@ void HLSignatureLower::AllocateDxilInputOutputs() {
"Failed to allocate all input signature elements in available space.");
}

if (props.shaderKind != DXIL::ShaderKind::Amplification) {
if (!props.IsAS()) {
hlsl::PackDxilSignature(EntrySig.OutputSignature, packing);
if (!EntrySig.OutputSignature.IsFullyAllocated()) {
llvm_unreachable("Failed to allocate all output signature elements in "
"available space.");
}
}

if (props.shaderKind == DXIL::ShaderKind::Hull ||
props.shaderKind == DXIL::ShaderKind::Domain ||
props.shaderKind == DXIL::ShaderKind::Mesh) {
if (props.UsesPatchConstOrPrimSignature()) {
hlsl::PackDxilSignature(EntrySig.PatchConstOrPrimSignature, packing);
if (!EntrySig.PatchConstOrPrimSignature.IsFullyAllocated()) {
llvm_unreachable("Failed to allocate all patch constant signature "
Expand Down Expand Up @@ -886,7 +885,7 @@ struct InputOutputAccessInfo {
void collectInputOutputAccessInfo(
Value *GV, Constant *constZero,
std::vector<InputOutputAccessInfo> &accessInfoList, bool hasVertexOrPrimID,
bool bInput, bool bRowMajor, bool isMS) {
bool bInput, bool bRowMajor) {
// merge GEP use for input output.
dxilutil::MergeGepUse(GV);
for (auto User = GV->user_begin(); User != GV->user_end();) {
Expand Down Expand Up @@ -1129,8 +1128,8 @@ void HLSignatureLower::GenerateDxilInputsOutputs(DXIL::SignatureKind SK) {
opcode = OP::OpCode::LoadInput;
break;
case DXIL::SignatureKind::Output:
opcode =
props.IsMS() ? OP::OpCode::StoreVertexOutput : OP::OpCode::StoreOutput;
opcode = props.IsMS() || props.IsMeshNode() ? OP::OpCode::StoreVertexOutput
: OP::OpCode::StoreOutput;
break;
case DXIL::SignatureKind::PatchConstOrPrim:
opcode = OP::OpCode::StorePrimitiveOutput;
Expand All @@ -1141,7 +1140,7 @@ void HLSignatureLower::GenerateDxilInputsOutputs(DXIL::SignatureKind SK) {
bool bInput = SK == DXIL::SignatureKind::Input;
bool bNeedVertexOrPrimID =
bInput && (props.IsGS() || props.IsDS() || props.IsHS());
bNeedVertexOrPrimID |= !bInput && props.IsMS();
bNeedVertexOrPrimID |= !bInput && (props.IsMS() || props.IsMeshNode());

Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);

Expand All @@ -1155,7 +1154,7 @@ void HLSignatureLower::GenerateDxilInputsOutputs(DXIL::SignatureKind SK) {

Constant *constZero = hlslOP->GetU32Const(0);

Value *undefVertexIdx = props.IsMS() || !bInput
Value *undefVertexIdx = props.IsMS() || props.IsMeshNode() || !bInput
? nullptr
: UndefValue::get(Type::getInt32Ty(HLM.GetCtx()));

Expand Down Expand Up @@ -1236,7 +1235,7 @@ void HLSignatureLower::GenerateDxilInputsOutputs(DXIL::SignatureKind SK) {
std::vector<InputOutputAccessInfo> accessInfoList;
collectInputOutputAccessInfo(GV, constZero, accessInfoList,
bNeedVertexOrPrimID && bIsArrayTy, bInput,
bRowMajor, props.IsMS());
bRowMajor);

for (InputOutputAccessInfo &info : accessInfoList) {
GenerateInputOutputUserCall(
Expand All @@ -1258,6 +1257,14 @@ void HLSignatureLower::GenerateDxilComputeAndNodeCommonInputs() {
DxilParameterAnnotation &paramAnnotation =
funcAnnotation->GetParameterAnnotation(arg.getArgNo());

DxilParamInputQual inputQual = paramAnnotation.GetParamInputQual();
// Skip mesh node out params
if (funcProps.IsMeshNode() &&
(inputQual == DxilParamInputQual::OutIndices ||
inputQual == DxilParamInputQual::OutVertices ||
inputQual == DxilParamInputQual::OutPrimitives))
continue;

llvm::StringRef semanticStr = paramAnnotation.GetSemanticString();

if (semanticStr.empty()) {
Expand Down Expand Up @@ -1424,8 +1431,7 @@ void HLSignatureLower::GenerateDxilPatchConstantLdSt() {
}
std::vector<InputOutputAccessInfo> accessInfoList;
collectInputOutputAccessInfo(GV, constZero, accessInfoList,
bNeedVertexOrPrimID, bIsInput, bRowMajor,
false);
bNeedVertexOrPrimID, bIsInput, bRowMajor);

bool bIsArrayTy = GV->getType()->getPointerElementType()->isArrayTy();
bool isPrecise = m_preciseSigSet.count(SE);
Expand Down Expand Up @@ -1499,8 +1505,7 @@ void HLSignatureLower::GenerateDxilPatchConstantFunctionInputs() {
}
std::vector<InputOutputAccessInfo> accessInfoList;
collectInputOutputAccessInfo(&arg, constZero, accessInfoList,
/*hasVertexOrPrimID*/ true, true, bRowMajor,
false);
/*hasVertexOrPrimID*/ true, true, bRowMajor);
for (InputOutputAccessInfo &info : accessInfoList) {
Constant *OpArg = hlslOP->GetU32Const((unsigned)opcode);
if (LoadInst *ldInst = dyn_cast<LoadInst>(info.user)) {
Expand Down Expand Up @@ -1802,6 +1807,13 @@ void HLSignatureLower::Run() {
GenerateDxilPrimOutputs();
}
} else if (props.IsCS() || props.IsNode()) {
if (props.IsMeshNode()) {
GenerateEmitIndicesOperations();
CreateDxilSignatures();
AllocateDxilInputOutputs();
GenerateDxilOutputs();
GenerateDxilPrimOutputs();
}
GenerateDxilComputeAndNodeCommonInputs();
}

Expand Down
6 changes: 1 addition & 5 deletions tools/clang/lib/CodeGen/CGHLSLMS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1726,14 +1726,10 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
DXIL::TessellatorOutputPrimitive primitive =
StringToTessOutputPrimitive(Attr->getTopology());
funcProps->ShaderProps.HS.outputPrimitive = primitive;
} else if (isMS) {
} else if (isMS || isNode) {
DXIL::MeshOutputTopology topology =
StringToMeshOutputTopology(Attr->getTopology());
funcProps->ShaderProps.MS.outputTopology = topology;
} else if (isNode) {
DXIL::MeshOutputTopology topology =
StringToMeshOutputTopology(Attr->getTopology());
funcProps->Node.OutputTopology = topology;
} else if (isEntry && !SM->IsHS() && !SM->IsMS()) {
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Warning,
Expand Down
Loading