Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move NodeMaxDispatchGrid diagnostic into Sema #5806

Merged
merged 9 commits into from
Oct 4, 2023
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
4 changes: 4 additions & 0 deletions tools/clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7837,6 +7837,10 @@ def err_hlsl_missing_node_attr : Error<
"Node shader '%0' with %1 launch type requires '%2' attribute">;
def err_hlsl_missing_dispatchgrid_attr : Error<
"Broadcasting node shader '%0' must have either the NodeDispatchGrid or NodeMaxDispatchGrid attribute">;
def err_hlsl_missing_dispatchgrid_semantic : Error<
"Broadcasting node shader '%0' with NodeMaxDispatchGrid attribute must declare an input record containing a field with SV_DispatchGrid semantic">;
def err_hlsl_dispatchgrid_semantic_already_specified : Error<
"a field with SV_DispatchGrid has already been specified">;
def err_hlsl_maxrecursiondepth_exceeded : Error<
"NodeMaxRecursionDepth may not exceed 32">;
def err_hlsl_too_many_node_inputs : Error<
Expand Down
38 changes: 3 additions & 35 deletions tools/clang/lib/CodeGen/CGHLSLMS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2485,26 +2485,6 @@ void CGMSHLSLRuntime::AddHLSLFunctionInfo(Function *F, const FunctionDecl *FD) {
/*isPatchConstantFunction*/ false);
}
}

// Make sure that if "NodeMaxDispatchGrid" is used, that an input
// with the SV_DispatchGrid attribute is provided.
if (funcProps->Node.MaxDispatchGrid[0] > 0) {
bool found = false;
for (auto node : funcProps->InputNodes) {
if (node.RecordType.SV_DispatchGrid.NumComponents != 0) {
found = true;
break;
}
}

if (!found) {
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error,
"node shader '%0' with NodeMaxDispatchGrid attribute must declare an"
" input record containing a field with the SV_DispatchGrid semantic");
Diags.Report(FD->getLocation(), DiagID) << FD->getIdentifier()->getName();
}
}

// All output decls and param names are available and errors can be generated
// and parameter output array indices that correspond to param names can be
Expand Down Expand Up @@ -2700,9 +2680,6 @@ void CGMSHLSLRuntime::AddHLSLNodeRecordTypeInfo(
// Ex: For DispatchNodeInputRecord<MY_RECORD>, set size =
// size(MY_RECORD)
node.RecordType.size = CGM.getDataLayout().getTypeAllocSize(Type);
// If we find SV_DispatchGrid we'll remember the location for
// diagnostics
SourceLocation SV_DispatchGridLoc;
// Iterate over fields of the MY_RECORD(example) struct
for (auto fieldDecl : RD->fields()) {
// Check if any of the fields have a semantic annotation =
Expand All @@ -2719,18 +2696,9 @@ void CGMSHLSLRuntime::AddHLSLNodeRecordTypeInfo(
clang::QualType FT = fieldDecl->getType();
auto &DL = CGM.getDataLayout();
auto &SDGRec = node.RecordType.SV_DispatchGrid;
if (SDGRec.NumComponents != 0) {
DiagnosticsEngine &Diags = CGM.getDiags();
unsigned DiagID = Diags.getCustomDiagID(
DiagnosticsEngine::Error, "a field with SV_DispatchGrid "
"has already been specified");
Diags.Report(it->Loc, DiagID);
Diags.Report(SV_DispatchGridLoc, diag::note_defined_here)
<< "previously";
} else {
// Set SV_DispatchGridLoc for use in diagnostics ;
SV_DispatchGridLoc = it->Loc;
}

DXASSERT_NOMSG(SDGRec.NumComponents == 0);

unsigned fieldIdx = fieldDecl->getFieldIndex();
if (StructType *ST = dyn_cast<StructType>(Type)) {
SDGRec.ByteOffset =
Expand Down
98 changes: 98 additions & 0 deletions tools/clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15138,6 +15138,63 @@ static bool nodeInputIsCompatible(DXIL::NodeIOKind IOType,
}
}

// Diagnose input node record to make sure it has exactly one SV_DispatchGrid
// semantics. Recursivelly walk all fields on the record and all of its base
// classes/structs
void DiagnoseMustHaveOneDispatchGridSemantics(Sema &S,
CXXRecordDecl *InputRecordDecl,
SourceLocation &DispatchGridLoc,
bool &Found) {
// Iterate over fields of the input record struct
for (auto FieldDecl : InputRecordDecl->fields()) {
// Check if any of the fields have SV_DispatchGrid annotation
hekota marked this conversation as resolved.
Show resolved Hide resolved
for (const hlsl::UnusualAnnotation *it :
FieldDecl->getUnusualAnnotations()) {
if (it->getKind() == hlsl::UnusualAnnotation::UA_SemanticDecl) {
const hlsl::SemanticDecl *sd = cast<hlsl::SemanticDecl>(it);
if (sd->SemanticName.equals("SV_DispatchGrid")) {
hekota marked this conversation as resolved.
Show resolved Hide resolved
if (!Found) {
Found = true;
DispatchGridLoc = it->Loc;
hekota marked this conversation as resolved.
Show resolved Hide resolved
} else {
// There should be just one SV_DispatchGrid in per record struct
S.Diags.Report(
it->Loc,
diag::err_hlsl_dispatchgrid_semantic_already_specified);
S.Diags.Report(DispatchGridLoc, diag::note_defined_here)
hekota marked this conversation as resolved.
Show resolved Hide resolved
<< "other SV_DispatchGrid";
}
break;
}
}
}
}

// Walk up the inheritance chain and check all fields on base classes
for (CXXRecordDecl::base_class_iterator B = InputRecordDecl->bases_begin(),
BEnd = InputRecordDecl->bases_end();
B != BEnd; ++B) {

const RecordType *BaseStructType = B->getType()->getAsStructureType();
if (nullptr != BaseStructType) {
CXXRecordDecl *BaseTypeDecl =
dyn_cast<CXXRecordDecl>(BaseStructType->getDecl());
if (nullptr != BaseTypeDecl) {
DiagnoseMustHaveOneDispatchGridSemantics(S, BaseTypeDecl,
DispatchGridLoc, Found);
}
}
}
}

void DiagnoseMustHaveOneDispatchGridSemantics(Sema &S,
CXXRecordDecl *InputRecordStruct,
bool &Found) {
SourceLocation DispatchGridLoc;
DiagnoseMustHaveOneDispatchGridSemantics(S, InputRecordStruct,
DispatchGridLoc, Found);
}

void DiagnoseAmplificationEntry(Sema &S, FunctionDecl *FD,
llvm::StringRef StageName) {

Expand Down Expand Up @@ -15297,6 +15354,47 @@ void DiagnoseNodeEntry(Sema &S, FunctionDecl *FD, llvm::StringRef StageName,
S.Diags.Report(NodeDG->getLocation(), diag::note_defined_here)
<< NodeDG->getSpelling();
}
// Node with NodeMaxDispatchGrid must have SV_DispatchGrid semantic.
if (NodeMDG) {
bool Found = false;
for (FunctionDecl::param_iterator I = FD->param_begin(),
E = FD->param_end();
I != E; ++I) {
QualType ParamType = (*I)->getType().getCanonicalType();

// Find parameter that is the node input record
if (hlsl::IsHLSLNodeInputType(ParamType)) {
// Node input records are template types
if (const RecordType *NodeInputRT = dyn_cast<RecordType>(ParamType)) {
if (const ClassTemplateSpecializationDecl *templateDecl =
dyn_cast<ClassTemplateSpecializationDecl>(
NodeInputRT->getDecl())) {

// Get the input record struct
auto &TemplateArgs = templateDecl->getTemplateArgs();
DXASSERT_NOMSG(TemplateArgs.size() >= 1);
QualType Arg0Type = TemplateArgs.get(0).getAsType();
const RecordType *NodeInputStructType =
Arg0Type->getAsStructureType();
if (nullptr != NodeInputStructType) {
CXXRecordDecl *NodeInputStructDecl =
dyn_cast<CXXRecordDecl>(NodeInputStructType->getDecl());
if (nullptr != NodeInputStructDecl) {
// Make sure there is exactly one SV_DispatchGrid semantics
DiagnoseMustHaveOneDispatchGridSemantics(
S, NodeInputStructDecl, Found);
}
}
}
}
}
}
if (!Found) {
S.Diags.Report(FD->getLocation(),
diag::err_hlsl_missing_dispatchgrid_semantic)
<< FD->getName();
}
}
}

if (!FD->getReturnType()->isVoidType())
Expand Down
2 changes: 1 addition & 1 deletion tools/clang/test/HLSL/workgraph/attribute_diags.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void node04()
[NodeMaxDispatchGrid(256, 64, 32)] // expected-error {{Node shader 'node05' may not use both 'nodemaxdispatchgrid' and 'nodedispatchgrid'}}
[NodeDispatchGrid(32, 1, 1)] // expected-note {{nodedispatchgrid defined here}}
[NumThreads(32, 1, 1)]
void node05()
void node05() // expected-error {{Broadcasting node shader 'node05' with NodeMaxDispatchGrid attribute must declare an input record containing a field with SV_DispatchGrid semantic}}
{ }

// One of NodeDispatchGrid or NodeMaxDispatchGrid must be specified for a Broadcasting node
Expand Down
70 changes: 64 additions & 6 deletions tools/clang/test/HLSL/workgraph/dispatchgrid_diags.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
// - the x, y, z, component values must be in the range 1 to 2^16 - 1 (65,535) inclusive
// - the product x * y * z must not exceed 2^24 - 1 (16,777,215)
// - a warning should be generated for 2nd and subsequent occurances of these attributes
// - node with NodeMaxDispatchGrid must have a input record with SV_DispatchGrid semantics
// on exactly one field

struct MyStruct {
float a;
uint3 grid : SV_DispatchGrid;
};

[Shader("node")]
[NodeLaunch("broadcasting")]
Expand Down Expand Up @@ -55,41 +62,92 @@ void node06()
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(65535, 1, 1)]
[NumThreads(32, 1, 1)]
void node11()
void node11(DispatchNodeInputRecord<MyStruct> input)
{ }

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(1, 65536, 1)] // expected-error {{'NodeMaxDispatchGrid' Y component value must be between 1 and 65,535 (2^16-1) inclusive}}
[NumThreads(32, 1, 1)]
void node12()
void node12(DispatchNodeInputRecord<MyStruct> input)
{ }

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(1, 1, 0)] // expected-error {{'NodeMaxDispatchGrid' Z component value must be between 1 and 65,535 (2^16-1) inclusive}}
[NumThreads(32, 1, 1)]
void node13()
void node13(DispatchNodeInputRecord<MyStruct> input)
{ }

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(1, y, z)] // expected-error {{'NodeMaxDispatchGrid' Z component value must be between 1 and 65,535 (2^16-1) inclusive}}
[NumThreads(32, 1, 1)]
void node14()
void node14(DispatchNodeInputRecord<MyStruct> input)
{ }

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(1, 65535, 257)] // expected-error {{'NodeMaxDispatchGrid' X * Y * Z product may not exceed 16,777,215 (2^24-1)}}
[NumThreads(32, 1, 1)]
void node15()
void node15(DispatchNodeInputRecord<MyStruct> input)
{ }

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(256, 8, 8)] // expected-warning {{attribute 'NodeMaxDispatchGrid' is already applied}}
[NodeMaxDispatchGrid(64, 1, 1)]
[NumThreads(32, 1, 1)]
void node16()
void node16(DispatchNodeInputRecord<MyStruct> input)
{ }

[Shader("node")]
[NodeMaxDispatchGrid(3, 1, 1)]
[NumThreads(17, 1, 1)]
void node17() // expected-error {{Broadcasting node shader 'node17' with NodeMaxDispatchGrid attribute must declare an input record containing a field with SV_DispatchGrid semantic}}
{ }

struct MyStruct2 {
float3 b;
};

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(256, 8, 8)]
[NumThreads(32, 1, 1)]
void node18(DispatchNodeInputRecord<MyStruct2> input) // expected-error {{Broadcasting node shader 'node18' with NodeMaxDispatchGrid attribute must declare an input record containing a field with SV_DispatchGrid semantic}}
{ }

struct MyStruct3 {
uint3 grid : SV_DispatchGrid; // expected-note {{other SV_DispatchGrid defined here}}
float3 b;
int3 grid2 : SV_DispatchGrid; // expected-error {{a field with SV_DispatchGrid has already been specified}}
};

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(256, 8, 8)]
[NumThreads(32, 1, 1)]
void node19(DispatchNodeInputRecord<MyStruct3> input)
{ }

struct A {
float a;
uint3 grid : SV_DispatchGrid; // expected-error {{a field with SV_DispatchGrid has already been specified}}
};

struct B : A {
float b;
};

struct C : B {
float b;
int3 grid2 : SV_DispatchGrid; // expected-note {{other SV_DispatchGrid defined here}}
hekota marked this conversation as resolved.
Show resolved Hide resolved
};

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(8, 4, 4)]
[NumThreads(32, 1, 1)]
void node20(DispatchNodeInputRecord<C> input)
{ }
5 changes: 3 additions & 2 deletions tools/clang/test/HLSL/workgraph/member_write_diagnostics.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ struct RECORD
{
uint3 a;
bool b;
uint3 grid : SV_DispatchGrid;
};

[Shader("node")]
Expand Down Expand Up @@ -96,7 +97,7 @@ void node06(RWThreadNodeInputRecord<RECORD> input6)
[Shader("node")]
[NumThreads(1024,1,1)]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(1024,1,1)]
[NodeDispatchGrid(1024,1,1)]
void node07(NodeOutput<RECORD> output7)
{
RECORD x;
Expand All @@ -110,7 +111,7 @@ void node07(NodeOutput<RECORD> output7)
[Shader("node")]
[NumThreads(1024,1,1)]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(1024,1,1)]
[NodeDispatchGrid(1024,1,1)]
pow2clk marked this conversation as resolved.
Show resolved Hide resolved
void node08([MaxRecords(8)] NodeOutputArray<RECORD> output8)
{
RECORD x;
Expand Down
8 changes: 4 additions & 4 deletions tools/clang/test/HLSL/workgraph/nodeoutput_array.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct Record {

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(65535, 1, 1)]
[NodeDispatchGrid(65535, 1, 1)]
[NodeIsProgramEntry]
[NumThreads(32, 1, 1)]
// expected-error@+2 {{entry parameter of type 'NodeOutput<Record> [9]' may not be an array}}
Expand All @@ -19,7 +19,7 @@ void node01(NodeOutput<Record> output[9])

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(65535, 1, 1)]
[NodeDispatchGrid(65535, 1, 1)]
[NumThreads(32, 1, 1)]
// expected-error@+2 {{entry parameter of type 'EmptyNodeOutput [4]' may not be an array}}
// expected-note@+1 {{'EmptyNodeOutput' cannot be used as an array; did you mean 'EmptyNodeOutputArray'?}}
Expand All @@ -28,7 +28,7 @@ void node02(EmptyNodeOutput output[4])

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(65535, 1, 1)]
[NodeDispatchGrid(65535, 1, 1)]
[NodeIsProgramEntry]
[NumThreads(32, 1, 1)]
// expected-error@+1 {{entry parameter of type 'NodeOutputArray<Record> [9]' may not be an array}}
Expand All @@ -37,7 +37,7 @@ void node03(NodeOutputArray<Record> output[9])

[Shader("node")]
[NodeLaunch("broadcasting")]
[NodeMaxDispatchGrid(65535, 1, 1)]
[NodeDispatchGrid(65535, 1, 1)]
[NumThreads(32, 1, 1)]
// expected-error@+1 {{entry parameter of type 'EmptyNodeOutputArray [4]' may not be an array}}
void node04(EmptyNodeOutputArray output[4])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

struct RECORD {
int i;
uint3 grid : SV_DispatchGrid;
};

[Shader("node")]
Expand Down Expand Up @@ -68,7 +69,7 @@ void node_emptynodeinput([MaxRecords(5)] EmptyNodeInput emptyNodeInput)
[Shader("node")]
[NodeLaunch("broadcasting")]
[NumThreads(1,1,1)]
[NodeMaxDispatchGrid(1,1,1)]
[NodeDispatchGrid(1,1,1)]
void node_nodeoutput(NodeOutput<RECORD> nodeOutput)
{
nodeOutput.OutputComplete(); // expected-error {{no member named 'OutputComplete' in 'NodeOutput<RECORD>'}}
Expand All @@ -77,7 +78,7 @@ void node_nodeoutput(NodeOutput<RECORD> nodeOutput)
[Shader("node")]
[NodeLaunch("broadcasting")]
[NumThreads(1,1,1)]
[NodeMaxDispatchGrid(1,1,1)]
[NodeDispatchGrid(1,1,1)]
void node127_emptynodeoutput(EmptyNodeOutput emptyNodeOutput)
{
emptyNodeOutput.OutputComplete(); // expected-error {{no member named 'OutputComplete' in 'EmptyNodeOutput'}}
Expand Down
Loading