[Sema] Move more diagnostics over (#5992)

This PR moves over some more diagnostics from CGHLSLMS.cpp. Some
diagnostics are moved into DiagnoseEntryAttrAllowedOnStage, to
specifically diagnose when an attribute appears on a shader stage that
it shouldn't appear on. Other diagnostics that are covered in Sema are
removed in CGHLSLMS.
Fixes #5990

---------

Co-authored-by: Chris B <cbieneman@microsoft.com>
This commit is contained in:
Joshua Batista 2023-11-20 13:15:05 -08:00 коммит произвёл GitHub
Родитель 8c945e8280
Коммит dc7a595092
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 141 добавлений и 119 удалений

Просмотреть файл

@ -440,6 +440,7 @@ const clang::ExtVectorType *
ConvertHLSLVecMatTypeToExtVectorType(const clang::ASTContext &, ConvertHLSLVecMatTypeToExtVectorType(const clang::ASTContext &,
clang::QualType); clang::QualType);
bool IsHLSLVecMatType(clang::QualType); bool IsHLSLVecMatType(clang::QualType);
clang::RecordDecl *GetRecordDeclFromNodeObjectType(clang::QualType ObjectTy);
bool IsHLSLVecType(clang::QualType type); bool IsHLSLVecType(clang::QualType type);
bool IsHLSLMatType(clang::QualType type); bool IsHLSLMatType(clang::QualType type);
clang::QualType GetElementTypeOrType(clang::QualType type); clang::QualType GetElementTypeOrType(clang::QualType type);

Просмотреть файл

@ -7823,6 +7823,8 @@ def warn_hlsl_numthreads_group_size : Warning<
InGroup<IgnoredAttributes>; InGroup<IgnoredAttributes>;
def err_hlsl_wg_nodetrackrwinputsharing_missing : Error< def err_hlsl_wg_nodetrackrwinputsharing_missing : Error<
"Use of FinishedCrossGroupSharing() requires NodeTrackRWInputSharing attribute to be specified on the record struct type">; "Use of FinishedCrossGroupSharing() requires NodeTrackRWInputSharing attribute to be specified on the record struct type">;
def err_hlsl_wg_nodetrackrwinputsharing_invalid : Error<
"NodeTrackRWInputSharing attribute cannot be applied to Input Records that are not RWDispatchNodeInputRecord">;
def err_hlsl_wg_input_kind : Error< def err_hlsl_wg_input_kind : Error<
"'%0' may not be used with %1 nodes (only %select{DispatchNodeInputRecord or RWDispatchNodeInputRecord|" "'%0' may not be used with %1 nodes (only %select{DispatchNodeInputRecord or RWDispatchNodeInputRecord|"
"GroupNodeInputRecords, RWGroupNodeInputRecords, or EmptyNodeInput|ThreadNodeInputRecord or RWThreadNodeInputRecord}2)">; "GroupNodeInputRecords, RWGroupNodeInputRecords, or EmptyNodeInput|ThreadNodeInputRecord or RWThreadNodeInputRecord}2)">;

Просмотреть файл

@ -867,6 +867,24 @@ bool GetHLSLSubobjectKind(clang::QualType type,
return false; return false;
} }
clang::RecordDecl *GetRecordDeclFromNodeObjectType(clang::QualType ObjectTy) {
ObjectTy = ObjectTy.getCanonicalType();
DXASSERT(IsHLSLNodeType(ObjectTy), "Expected Node Object type");
if (const CXXRecordDecl *CXXRD = ObjectTy->getAsCXXRecordDecl()) {
if (const ClassTemplateSpecializationDecl *templateDecl =
dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
auto &TemplateArgs = templateDecl->getTemplateArgs();
clang::QualType RecType = TemplateArgs[0].getAsType();
if (const RecordType *RT = RecType->getAs<RecordType>())
return RT->getDecl();
}
}
return nullptr;
}
bool IsHLSLRayQueryType(clang::QualType type) { bool IsHLSLRayQueryType(clang::QualType type) {
type = type.getCanonicalType(); type = type.getCanonicalType();
if (const RecordType *RT = dyn_cast<RecordType>(type)) { if (const RecordType *RT = dyn_cast<RecordType>(type)) {

Просмотреть файл

@ -1402,15 +1402,6 @@ static DxilResource::Kind KeywordToKind(StringRef keyword) {
return DxilResource::Kind::Invalid; return DxilResource::Kind::Invalid;
} }
static void ReportMissingNodeDiag(DiagnosticsEngine &Diags,
const InheritableAttr *a) {
SourceLocation loc = a->getLocation();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "Attribute %0 only applies to node shaders "
"(indicated with '[shader(\"node\")]')");
Diags.Report(loc, DiagID) << a->getSpelling();
}
void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) { void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
// Add hlsl intrinsic attr // Add hlsl intrinsic attr
unsigned intrinsicOpcode; unsigned intrinsicOpcode;
@ -1522,20 +1513,16 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
}; };
// Some diagnostic assumptions for shader attribute: // Some diagnostic assumptions for shader attribute:
// - multiple shader attributes may exist in HLSL
// - duplicate attribute of same kind is ok // - duplicate attribute of same kind is ok
// - node attribute only combinable with compute
// - all attributes parsed before set from insertion or target shader model // - all attributes parsed before set from insertion or target shader model
auto DiagShaderStage = [&priorShaderAttrLoc, auto DiagShaderStage = [&priorShaderAttrLoc,
&Diags](clang::SourceLocation diagLoc, &Diags](clang::SourceLocation diagLoc,
llvm::StringRef shaderStage, llvm::StringRef shaderStage,
ShaderStageSource source, bool bConflict) { ShaderStageSource source) {
bool bFromProfile = source == ShaderStageSource::Profile; bool bFromProfile = source == ShaderStageSource::Profile;
unsigned DiagID = Diags.getCustomDiagID( unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, DiagnosticsEngine::Error, "Invalid shader %select{profile|attribute}0");
"%select{Invalid|Conflicting}0 shader %select{profile|attribute}1"); Diags.Report(diagLoc, DiagID) << bFromProfile;
Diags.Report(diagLoc, DiagID) << bConflict << bFromProfile;
if (priorShaderAttrLoc.isValid()) { if (priorShaderAttrLoc.isValid()) {
unsigned DiagID = Diags.getCustomDiagID( unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Note, "See conflicting shader attribute"); DiagnosticsEngine::Note, "See conflicting shader attribute");
@ -1547,7 +1534,7 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
[&](clang::SourceLocation diagLoc, DXIL::ShaderKind shaderKind, [&](clang::SourceLocation diagLoc, DXIL::ShaderKind shaderKind,
llvm::StringRef shaderStage, ShaderStageSource source) { llvm::StringRef shaderStage, ShaderStageSource source) {
if (!SetStageFlag(shaderKind)) { if (!SetStageFlag(shaderKind)) {
DiagShaderStage(diagLoc, shaderStage, source, false); DiagShaderStage(diagLoc, shaderStage, source);
} }
if (isEntry && isRay) { if (isEntry && isRay) {
unsigned DiagID = Diags.getCustomDiagID( unsigned DiagID = Diags.getCustomDiagID(
@ -1555,18 +1542,6 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
"Ray function cannot be used as a global entry point"); "Ray function cannot be used as a global entry point");
Diags.Report(diagLoc, DiagID); Diags.Report(diagLoc, DiagID);
} }
if (isEntry && isNode && !SM->IsCS()) {
unsigned DiagID =
Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Node function as global entry point must "
"be compiled to compute shader target");
Diags.Report(diagLoc, DiagID);
}
if (funcProps->shaderKind != DXIL::ShaderKind::Invalid &&
funcProps->shaderKind != shaderKind) {
// Different kinds and not the node case, so it's a conflict.
DiagShaderStage(diagLoc, shaderStage, source, true);
}
// Update shaderKind, unless we would be overriding one with node, so // Update shaderKind, unless we would be overriding one with node, so
// when node+compute, kind = compute. Other conflicts are diagnosed // when node+compute, kind = compute. Other conflicts are diagnosed
// above. // above.
@ -1841,79 +1816,46 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
if (isNode) { if (isNode) {
// Default launch type is defined to be Broadcasting. // Default launch type is defined to be Broadcasting.
funcProps->Node.LaunchType = DXIL::NodeLaunchType::Broadcasting; funcProps->Node.LaunchType = DXIL::NodeLaunchType::Broadcasting;
}
// Assign function properties for all "node" attributes. // Assign function properties for all "node" attributes.
if (const auto *pAttr = FD->getAttr<HLSLNodeLaunchAttr>()) { if (const auto *pAttr = FD->getAttr<HLSLNodeLaunchAttr>()) {
if (isNode)
funcProps->Node.LaunchType = funcProps->Node.LaunchType =
ShaderModel::NodeLaunchTypeFromName(pAttr->getLaunchType()); ShaderModel::NodeLaunchTypeFromName(pAttr->getLaunchType());
else }
ReportMissingNodeDiag(Diags, pAttr);
}
if (const auto *pAttr = FD->getAttr<HLSLNodeIsProgramEntryAttr>()) { if (const auto *pAttr = FD->getAttr<HLSLNodeIsProgramEntryAttr>()) {
if (isNode)
funcProps->Node.IsProgramEntry = true; funcProps->Node.IsProgramEntry = true;
else }
ReportMissingNodeDiag(Diags, pAttr);
}
if (const auto *pAttr = FD->getAttr<HLSLNodeIdAttr>()) { if (const auto *pAttr = FD->getAttr<HLSLNodeIdAttr>()) {
if (isNode) {
funcProps->NodeShaderID.Name = pAttr->getName().str(); funcProps->NodeShaderID.Name = pAttr->getName().str();
funcProps->NodeShaderID.Index = pAttr->getArrayIndex(); funcProps->NodeShaderID.Index = pAttr->getArrayIndex();
} else { } else {
ReportMissingNodeDiag(Diags, pAttr);
}
} else {
if (isNode) {
funcProps->NodeShaderID.Name = FD->getName().str(); funcProps->NodeShaderID.Name = FD->getName().str();
funcProps->NodeShaderID.Index = 0; funcProps->NodeShaderID.Index = 0;
} }
} if (const auto *pAttr =
if (const auto *pAttr = FD->getAttr<HLSLNodeLocalRootArgumentsTableIndexAttr>()) {
FD->getAttr<HLSLNodeLocalRootArgumentsTableIndexAttr>()) {
if (isNode)
funcProps->Node.LocalRootArgumentsTableIndex = pAttr->getIndex(); funcProps->Node.LocalRootArgumentsTableIndex = pAttr->getIndex();
else }
ReportMissingNodeDiag(Diags, pAttr); if (const auto *pAttr = FD->getAttr<HLSLNodeShareInputOfAttr>()) {
}
if (const auto *pAttr = FD->getAttr<HLSLNodeShareInputOfAttr>()) {
if (isNode) {
funcProps->NodeShaderSharedInput.Name = pAttr->getName().str(); funcProps->NodeShaderSharedInput.Name = pAttr->getName().str();
funcProps->NodeShaderSharedInput.Index = pAttr->getArrayIndex(); funcProps->NodeShaderSharedInput.Index = pAttr->getArrayIndex();
} else {
ReportMissingNodeDiag(Diags, pAttr);
} }
} if (const auto *pAttr = FD->getAttr<HLSLNodeDispatchGridAttr>()) {
if (const auto *pAttr = FD->getAttr<HLSLNodeDispatchGridAttr>()) {
if (isNode) {
funcProps->Node.DispatchGrid[0] = pAttr->getX(); funcProps->Node.DispatchGrid[0] = pAttr->getX();
funcProps->Node.DispatchGrid[1] = pAttr->getY(); funcProps->Node.DispatchGrid[1] = pAttr->getY();
funcProps->Node.DispatchGrid[2] = pAttr->getZ(); funcProps->Node.DispatchGrid[2] = pAttr->getZ();
} else {
ReportMissingNodeDiag(Diags, pAttr);
} }
} if (const auto *pAttr = FD->getAttr<HLSLNodeMaxDispatchGridAttr>()) {
if (const auto *pAttr = FD->getAttr<HLSLNodeMaxDispatchGridAttr>()) {
if (isNode) {
funcProps->Node.MaxDispatchGrid[0] = pAttr->getX(); funcProps->Node.MaxDispatchGrid[0] = pAttr->getX();
funcProps->Node.MaxDispatchGrid[1] = pAttr->getY(); funcProps->Node.MaxDispatchGrid[1] = pAttr->getY();
funcProps->Node.MaxDispatchGrid[2] = pAttr->getZ(); funcProps->Node.MaxDispatchGrid[2] = pAttr->getZ();
} else {
ReportMissingNodeDiag(Diags, pAttr);
} }
} if (const auto *pAttr = FD->getAttr<HLSLNodeMaxRecursionDepthAttr>()) {
if (const auto *pAttr = FD->getAttr<HLSLNodeMaxRecursionDepthAttr>()) {
if (isNode)
funcProps->Node.MaxRecursionDepth = pAttr->getCount(); funcProps->Node.MaxRecursionDepth = pAttr->getCount();
else }
ReportMissingNodeDiag(Diags, pAttr); if (!FD->getAttr<HLSLNumThreadsAttr>()) {
}
if (!FD->getAttr<HLSLNumThreadsAttr>()) {
if (isNode) {
// NumThreads wasn't specified. // NumThreads wasn't specified.
// For a Thread launch node the default is (1,1,1,) which we set here. // For a Thread launch node the default is (1,1,1,) which we set here.
// Other node launch types require NumThreads and an error will have // Other node launch types require NumThreads and an error will have
@ -1927,13 +1869,6 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
const unsigned profileAttributes = const unsigned profileAttributes =
isCS + isHS + isDS + isGS + isVS + isPS + isRay + isMS + isAS + isNode; isCS + isHS + isDS + isGS + isVS + isPS + isRay + isMS + isAS + isNode;
// TODO: check this in front-end and report error.
if (profileAttributes > 1)
Diags.Report(
FD->getLocation(),
Diags.getCustomDiagID(DiagnosticsEngine::Error,
"Invalid shader stage attribute combination"));
if (isEntry) { if (isEntry) {
switch (funcProps->shaderKind) { switch (funcProps->shaderKind) {
case ShaderModel::Kind::Compute: case ShaderModel::Kind::Compute:

Просмотреть файл

@ -11458,7 +11458,6 @@ void DiagnoseEntryAttrAllowedOnStage(clang::Sema *self,
if (entryPointDecl->hasAttrs()) { if (entryPointDecl->hasAttrs()) {
for (Attr *pAttr : entryPointDecl->getAttrs()) { for (Attr *pAttr : entryPointDecl->getAttrs()) {
switch (pAttr->getKind()) { switch (pAttr->getKind()) {
case clang::attr::HLSLWaveSize: { case clang::attr::HLSLWaveSize: {
switch (shaderKind) { switch (shaderKind) {
case DXIL::ShaderKind::Compute: case DXIL::ShaderKind::Compute:
@ -11471,6 +11470,22 @@ void DiagnoseEntryAttrAllowedOnStage(clang::Sema *self,
<< "compute or node"; << "compute or node";
break; break;
} }
break;
}
case clang::attr::HLSLNodeLaunch:
case clang::attr::HLSLNodeIsProgramEntry:
case clang::attr::HLSLNodeId:
case clang::attr::HLSLNodeLocalRootArgumentsTableIndex:
case clang::attr::HLSLNodeShareInputOf:
case clang::attr::HLSLNodeDispatchGrid:
case clang::attr::HLSLNodeMaxDispatchGrid:
case clang::attr::HLSLNodeMaxRecursionDepth: {
if (shaderKind != DXIL::ShaderKind::Node) {
self->Diag(pAttr->getRange().getBegin(),
diag::err_hlsl_attribute_unsupported_stage)
<< pAttr->getSpelling() << "node";
}
break;
} }
} }
} }
@ -15707,7 +15722,6 @@ void DiagnoseNodeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName,
auto *NodeArraySizeAttr = Param->getAttr<HLSLNodeArraySizeAttr>(); auto *NodeArraySizeAttr = Param->getAttr<HLSLNodeArraySizeAttr>();
auto *UnboundedSparseNodesAttr = auto *UnboundedSparseNodesAttr =
Param->getAttr<HLSLUnboundedSparseNodesAttr>(); Param->getAttr<HLSLUnboundedSparseNodesAttr>();
// Check any node input is compatible with the node launch type // Check any node input is compatible with the node launch type
if (hlsl::IsHLSLNodeInputType(ParamTy)) { if (hlsl::IsHLSLNodeInputType(ParamTy)) {
InputCount++; InputCount++;
@ -15792,19 +15806,16 @@ void DiagnoseNodeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName,
<< HLSLNodeObjectAttr::ConvertRecordTypeToStr(Kind); << HLSLNodeObjectAttr::ConvertRecordTypeToStr(Kind);
} }
} }
HLSLMaxRecordsSharedWithAttr *ExistingMRSWA = HLSLMaxRecordsSharedWithAttr *ExistingMRSWA =
Param->getAttr<HLSLMaxRecordsSharedWithAttr>(); Param->getAttr<HLSLMaxRecordsSharedWithAttr>();
if (ExistingMRSWA) { if (ExistingMRSWA) {
StringRef sharedName = ExistingMRSWA->getName()->getName(); StringRef sharedName = ExistingMRSWA->getName()->getName();
unsigned int ArgIdx = 0;
bool Found = false; bool Found = false;
while (ArgIdx < FD->getNumParams()) { for (const ParmVarDecl *ParamDecl : FD->params()) {
const ParmVarDecl *ParamDecl = FD->getParamDecl(ArgIdx);
// validation that MRSW doesn't reference its own parameter is // validation that MRSW doesn't reference its own parameter is
// already done at // already done at
// SemaHLSL.cpp:ValidateMaxRecordsSharedWithAttributes so we don't // SemaHLSL.cpp:ValidateMaxRecordsSharedWithAttributes so we don't
// need to check that ArgIdx != Idx. // need to check that we are on the same argument.
if (ParamDecl->getName() == sharedName) { if (ParamDecl->getName() == sharedName) {
// now we need to check that this parameter has an output record type. // now we need to check that this parameter has an output record type.
hlsl::NodeFlags nodeFlags; hlsl::NodeFlags nodeFlags;
@ -15816,7 +15827,6 @@ void DiagnoseNodeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName,
} }
} }
} }
ArgIdx++;
} }
if (!Found) { if (!Found) {
@ -15824,6 +15834,29 @@ void DiagnoseNodeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName,
diag::err_hlsl_maxrecordssharedwith_references_invalid_arg); diag::err_hlsl_maxrecordssharedwith_references_invalid_arg);
} }
} }
// Make sure NodeTrackRWInputSharing attribute cannot be applied to
// Input Records that are not RWDispatchNodeInputRecord
if (hlsl::IsHLSLNodeInputType(ParamTy)) {
hlsl::NodeFlags nodeFlags;
if (GetHLSLNodeIORecordType(Param, nodeFlags)) {
hlsl::NodeIOProperties node(nodeFlags);
// determine if the NodeTrackRWInputSharing is an attribute on the
// template type
clang::RecordDecl *RD = hlsl::GetRecordDeclFromNodeObjectType(ParamTy);
if (RD) {
// Emit a diagnostic if the record is not RWDispatchNode and
// if it has the NodeTrackRWInputSharing attribute
if (RD->hasAttr<HLSLNodeTrackRWInputSharingAttr>() &&
node.Flags.GetNodeIOKind() !=
DXIL::NodeIOKind::RWDispatchNodeInputRecord) {
S.Diags.Report(Param->getLocation(),
diag::err_hlsl_wg_nodetrackrwinputsharing_invalid);
}
}
}
}
} }
return; return;
} }
@ -15854,13 +15887,15 @@ void TryAddShaderAttrFromTargetProfile(Sema &S, FunctionDecl *FD,
return; return;
} }
isActiveEntry = true;
std::string profile = S.getLangOpts().HLSLProfile; std::string profile = S.getLangOpts().HLSLProfile;
const ShaderModel *SM = hlsl::ShaderModel::GetByName(profile.c_str()); const ShaderModel *SM = hlsl::ShaderModel::GetByName(profile.c_str());
const llvm::StringRef fullName = ShaderModel::FullNameFromKind(SM->GetKind()); const llvm::StringRef fullName = ShaderModel::FullNameFromKind(SM->GetKind());
// don't add the attribute for an invalid profile, like library // don't add the attribute for an invalid profile, like library
if (fullName.empty()) { if (fullName.empty()) {
return; llvm_unreachable("invalid shader kind");
} }
// At this point, we've found the active entry, so we'll take a note of that // At this point, we've found the active entry, so we'll take a note of that
@ -15868,12 +15903,12 @@ void TryAddShaderAttrFromTargetProfile(Sema &S, FunctionDecl *FD,
isActiveEntry = true; isActiveEntry = true;
HLSLShaderAttr *currentShaderAttr = FD->getAttr<HLSLShaderAttr>(); HLSLShaderAttr *currentShaderAttr = FD->getAttr<HLSLShaderAttr>();
// Don't add the attribute if it already exists as an attribute on the decl. // Don't add the attribute if it already exists as an attribute on the decl,
// In the special case that the target profile is compute and the // and emit an error.
// entry decl already has a node shader attr, don't do anything
if (currentShaderAttr) { if (currentShaderAttr) {
llvm::StringRef currentFullName = currentShaderAttr->getStage(); llvm::StringRef currentFullName = currentShaderAttr->getStage();
if (currentFullName != fullName) { if (currentFullName != fullName) {
S.Diag(currentShaderAttr->getLocation(), S.Diag(currentShaderAttr->getLocation(),
diag::err_hlsl_profile_conflicts_with_shader_attribute) diag::err_hlsl_profile_conflicts_with_shader_attribute)
<< fullName << profile << currentFullName << EntryPointName; << fullName << profile << currentFullName << EntryPointName;

Просмотреть файл

@ -1,23 +0,0 @@
// RUN: %dxc -T lib_6_8 %s | FileCheck %s
// check that an error gets generated each time a "node" attribute gets used without the presence of
// the '[shader("node")]' attribute
[Shader("compute")]
[NodeIsProgramEntry]
[NodeID("nodeName")]
[NodeLocalRootArgumentsTableIndex(3)]
[NodeShareInputOf("nodeName")]
[NodeMaxRecursionDepth(31)]
[NodeDispatchGrid(1, 1, 1)]
[NodeMaxDispatchGrid(2,2,2)]
[NumThreads(1, 1, 1)]
void secondNode()
{
// CHECK-DAG: Attribute nodeisprogramentry only applies to node shaders (indicated with '[shader("node")]')
// CHECK-DAG: Attribute nodeid only applies to node shaders (indicated with '[shader("node")]')
// CHECK-DAG: Attribute nodelocalrootargumentstableindex only applies to node shaders (indicated with '[shader("node")]')
// CHECK-DAG: Attribute nodeshareinputof only applies to node shaders (indicated with '[shader("node")]')
// CHECK-DAG: Attribute nodemaxrecursiondepth only applies to node shaders (indicated with '[shader("node")]')
// CHECK-DAG: Attribute nodedispatchgrid only applies to node shaders (indicated with '[shader("node")]')
// CHECK-DAG: Attribute nodemaxdispatchgrid only applies to node shaders (indicated with '[shader("node")]')
}

Просмотреть файл

@ -0,0 +1,20 @@
// RUN: %dxc -T ps_6_6 -E main -verify %s
struct loadStressRecord {
uint x : SV_DispatchGrid;
};
void loadStressWorker(NodeOutput<loadStressRecord> x) {
return;
}
[Shader("node")] // expected-error{{entry type 'pixel' from profile 'ps_6_6' conflicts with shader attribute type 'node' on entry function 'main'.}}
[NodeMaxDispatchGrid(3, 1, 1)]
[NumThreads(16, 1, 1)]
void main(
DispatchNodeInputRecord<loadStressRecord> input,
[MaxRecords(16)] NodeOutput<loadStressRecord> loadStressChild
)
{
loadStressWorker(loadStressChild);
}

Просмотреть файл

@ -0,0 +1,16 @@
// RUN: %dxc -T cs_6_6 -verify %s
// check that an error gets generated each time a "node" attribute gets used without the presence of
// the '[shader("node")]' attribute
[Shader("compute")]
[NodeIsProgramEntry] // expected-error{{attribute nodeisprogramentry only allowed on node shaders}}
[NodeID("nodeName")] // expected-error{{attribute nodeid only allowed on node shaders}}
[NodeLocalRootArgumentsTableIndex(3)] // expected-error{{attribute nodelocalrootargumentstableindex only allowed on node shaders}}
[NodeShareInputOf("nodeName")] // expected-error{{attribute nodeshareinputof only allowed on node shaders}}
[NodeMaxRecursionDepth(31)] // expected-error{{attribute nodemaxrecursiondepth only allowed on node shaders}}
[NodeDispatchGrid(1, 1, 1)] // expected-error{{attribute nodedispatchgrid only allowed on node shaders}}
[NodeMaxDispatchGrid(2,2,2)] // expected-error{{attribute nodemaxdispatchgrid only allowed on node shaders}}
[NumThreads(1, 1, 1)]
void secondNode()
{
}

Просмотреть файл

@ -0,0 +1,18 @@
// RUN: %dxc -T lib_6_8 -HV 2021 %s -verify
struct [NodeTrackRWInputSharing] TRACKED_RECORD
{
uint a;
};
//==============================================================================
// Check Get[GroupShared]NodeOutput[Array]() intrinsics don't match with invalid
// parameter types.
[Shader("node")]
[NumThreads(8,1,1)]
[NodeLaunch("broadcasting")]
[NodeDispatchGrid(8,1,1)]
// expected-error@+1{{NodeTrackRWInputSharing attribute cannot be applied to Input Records that are not RWDispatchNodeInputRecord}}
void node4_01(DispatchNodeInputRecord<TRACKED_RECORD> input) {
}