Skip to content

Commit 7a4f217

Browse files
committed
[SER] Generalize long vector diagnostics to HitObject
- Generalize long vector diagnostics code to HitObjects. - Diagnose unsupported use of HitObject in globals, entry params/returns and various other shader-kind-specific contexts. - Create HitObject variants from the invalid-longvec-decls*.hlsl tests to make sure all cases are covered. Specification: https://github.com/microsoft/hlsl-specs/blob/main/proposals/0027-shader-execution-reordering.md Bug: #7234 [SER] Diagnose and validate illegal use of HitObject in unsupported contexts
1 parent 847d5ad commit 7a4f217

13 files changed

Lines changed: 872 additions & 47 deletions

tools/clang/include/clang/AST/DeclCXX.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,10 @@ class CXXRecordDecl : public RecordDecl {
469469
/// class containing an HLSL vector longer than 4 elements.
470470
bool HasHLSLLongVector : 1;
471471

472+
/// \brief Whether this class contains at least one member or base
473+
/// class containing an HLSL HitObject.
474+
bool HasHLSLHitObject : 1;
475+
472476
/// \brief The number of base class specifiers in Bases.
473477
unsigned NumBases;
474478

@@ -1029,6 +1033,11 @@ class CXXRecordDecl : public RecordDecl {
10291033
/// \brief Set that this class contains an HLSL long vector of over 4 elements
10301034
bool setHasHLSLLongVector() { return data().HasHLSLLongVector = true; }
10311035

1036+
// \brief Determine whether this class contains an HLSL HitObject.
1037+
bool hasHLSLHitObject() { return data().HasHLSLHitObject; }
1038+
/// \brief Set that this class contains an HLSL HitObject.
1039+
bool setHasHLSLHitObject() { return data().HasHLSLHitObject = true; }
1040+
10321041
/// \brief Determine whether this class describes a lambda function object.
10331042
bool isLambda() const {
10341043
// An update record can't turn a non-lambda into a lambda.

tools/clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7878,14 +7878,14 @@ def err_hlsl_load_from_mesh_out_arrays: Error<
78787878
"output arrays of a mesh shader can not be read from">;
78797879
def err_hlsl_out_indices_array_incorrect_access: Error<
78807880
"a vector in out indices array must be accessed as a whole">;
7881-
def err_hlsl_unsupported_long_vector
7882-
: Error<"vectors of over 4 elements in "
7881+
def err_hlsl_unsupported_type
7882+
: Error<"%select{vectors of over 4 elements|HitObjects}0 in "
78837883
"%select{ConstantBuffers or TextureBuffers|"
78847884
"tessellation patches|geometry streams|node records|"
78857885
"cbuffers or tbuffers|user-defined struct parameter|"
78867886
"entry function parameters|entry function return type|"
78877887
"patch constant function parameters|patch constant function return type|"
7888-
"payload parameters|attributes}0 are not supported">;
7888+
"payload parameters|attributes}1 are not supported">;
78897889
def err_hlsl_logical_binop_scalar : Error<
78907890
"operands for short-circuiting logical binary operator must be scalar, for non-scalar types use '%select{and|or}0'">;
78917891
def err_hlsl_ternary_scalar : Error<

tools/clang/include/clang/Sema/SemaHLSL.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ unsigned CaculateInitListArraySizeForHLSL(clang::Sema *sema,
129129
const clang::QualType EltTy);
130130

131131
bool ContainsLongVector(clang::QualType);
132+
bool ContainsHitObject(clang::QualType);
133+
134+
/// \brief Determine if the given type contains a long vector or a hit object.
135+
/// \param QT The type to check.
136+
/// \param DiagTypeIdx The index of the type in the diagnostic message.
137+
/// \returns True if the type contains a long vector or a hit object, false
138+
/// otherwise.
139+
bool ContainsLongVecOrHitObject(clang::QualType QT, unsigned &DiagTypeIdx);
132140

133141
bool IsConversionToLessOrEqualElements(clang::Sema *self,
134142
const clang::ExprResult &sourceExpr,

tools/clang/lib/AST/DeclCXX.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,9 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
7272
ImplicitCopyAssignmentHasConstParam(true),
7373
HasDeclaredCopyConstructorWithConstParam(false),
7474
HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false),
75-
IsParsingBaseSpecifiers(false), HasHLSLLongVector(false), NumBases(0),
76-
NumVBases(0), Bases(), VBases(), Definition(D), FirstFriend() {}
75+
IsParsingBaseSpecifiers(false), HasHLSLLongVector(false),
76+
HasHLSLHitObject(false), NumBases(0), NumVBases(0), Bases(), VBases(),
77+
Definition(D), FirstFriend() {}
7778
// HLSL Change End - Add HasLongVector and clang-format
7879

7980
CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const {
@@ -206,6 +207,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
206207
// HLSL Change Begin - Propagate presence of long vector to child classes.
207208
if (BaseClassDecl->hasHLSLLongVector())
208209
data().HasHLSLLongVector = true;
210+
if (BaseClassDecl->hasHLSLHitObject())
211+
data().HasHLSLHitObject = true;
209212
// HLSL Change End
210213

211214
// Record if this base is the first non-literal field or base.
@@ -393,6 +396,8 @@ void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) {
393396
// HLSL Change Begin - Propagate presence of long vector to child classes.
394397
if (Subobj->hasHLSLLongVector())
395398
data().HasHLSLLongVector = true;
399+
if (Subobj->hasHLSLHitObject())
400+
data().HasHLSLHitObject = true;
396401
// HLSL Change End
397402
}
398403

tools/clang/lib/AST/HlslTypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "clang/AST/DeclTemplate.h"
2626
#include "clang/AST/Type.h"
2727
#include "clang/Sema/AttributeList.h" // conceptually ParsedAttributes
28+
#include "clang/Sema/SemaHLSL.h"
2829
#include "llvm/ADT/StringSwitch.h"
2930

3031
using namespace clang;
@@ -124,6 +125,8 @@ bool IsHLSLNumericUserDefinedType(clang::QualType type) {
124125
// which can't be annotated. But includes UDTs of trivially copyable data and
125126
// the builtin trivially copyable raytracing structs.
126127
bool IsHLSLCopyableAnnotatableRecord(clang::QualType QT) {
128+
if (ContainsHitObject(QT))
129+
return false;
127130
return IsHLSLNumericUserDefinedType(QT) ||
128131
IsHLSLBuiltinRayAttributeStruct(QT);
129132
}

tools/clang/lib/Sema/SemaDXR.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,9 +835,11 @@ void DiagnoseBuiltinCallWithPayload(Sema &S, const VarDecl *Payload,
835835
}
836836

837837
if (ContainsLongVector(Payload->getType())) {
838+
// No need to check for HitObject, checked with payload diagnosis.
839+
const unsigned LongVectorIdx = 0;
838840
const unsigned PayloadParametersIdx = 10;
839-
S.Diag(Payload->getLocation(), diag::err_hlsl_unsupported_long_vector)
840-
<< PayloadParametersIdx;
841+
S.Diag(Payload->getLocation(), diag::err_hlsl_unsupported_type)
842+
<< LongVectorIdx << PayloadParametersIdx;
841843
return;
842844
}
843845

tools/clang/lib/Sema/SemaDecl.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13247,10 +13247,16 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
1324713247
SmallVector<FieldDecl*, 32> RecFields;
1324813248

1324913249
bool ARCErrReported = false;
13250+
bool HasHitObject = false;
1325013251
for (ArrayRef<Decl *>::iterator i = Fields.begin(), end = Fields.end();
1325113252
i != end; ++i) {
1325213253
FieldDecl *FD = cast<FieldDecl>(*i);
1325313254

13255+
// HLSL Change Begin - set HitObject bit for fields
13256+
if (!HasHitObject && hlsl::ContainsHitObject(FD->getType()))
13257+
HasHitObject = true;
13258+
// HLSL Change End
13259+
1325413260
// Get the type for the field.
1325513261
const Type *FDTy = FD->getType().getTypePtr();
1325613262

@@ -13439,7 +13445,12 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl,
1343913445
I = CXXRecord->conversion_begin(),
1344013446
E = CXXRecord->conversion_end(); I != E; ++I)
1344113447
I.setAccess((*I)->getAccess());
13442-
13448+
13449+
// HLSL Change Begin - set HitObject bit for fields
13450+
if (HasHitObject)
13451+
CXXRecord->setHasHLSLHitObject();
13452+
// HLSL Change End
13453+
1344313454
if (!CXXRecord->isDependentType()) {
1344413455
if (CXXRecord->hasUserDeclaredDestructor()) {
1344513456
// Adjust user-defined destructor exception spec.

tools/clang/lib/Sema/SemaHLSL.cpp

Lines changed: 76 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5533,10 +5533,11 @@ class HLSLExternalSource : public ExternalSemaSource {
55335533
m_sema->RequireCompleteType(argSrcLoc, argType,
55345534
diag::err_typecheck_decl_incomplete_type);
55355535

5536-
if (ContainsLongVector(argType)) {
5536+
unsigned DiagTypeIdx = 0;
5537+
if (hlsl::ContainsLongVecOrHitObject(argType, DiagTypeIdx)) {
55375538
const unsigned ConstantBuffersOrTextureBuffersIdx = 0;
5538-
m_sema->Diag(argSrcLoc, diag::err_hlsl_unsupported_long_vector)
5539-
<< ConstantBuffersOrTextureBuffersIdx;
5539+
m_sema->Diag(argSrcLoc, diag::err_hlsl_unsupported_type)
5540+
<< DiagTypeIdx << ConstantBuffersOrTextureBuffersIdx;
55405541
return true;
55415542
}
55425543
}
@@ -5641,11 +5642,11 @@ class HLSLExternalSource : public ExternalSemaSource {
56415642
CXXRecordDecl *Decl = arg.getAsType()->getAsCXXRecordDecl();
56425643
if (Decl && !Decl->isCompleteDefinition())
56435644
return true;
5644-
if (ContainsLongVector(arg.getAsType())) {
5645+
unsigned DiagTypeIdx = 0;
5646+
if (ContainsLongVecOrHitObject(arg.getAsType(), DiagTypeIdx)) {
56455647
const unsigned TessellationPatchesIDx = 1;
5646-
m_sema->Diag(argLoc.getLocation(),
5647-
diag::err_hlsl_unsupported_long_vector)
5648-
<< TessellationPatchesIDx;
5648+
m_sema->Diag(argLoc.getLocation(), diag::err_hlsl_unsupported_type)
5649+
<< DiagTypeIdx << TessellationPatchesIDx;
56495650
return true;
56505651
}
56515652
} else if (Template->getTemplatedDecl()->hasAttr<HLSLStreamOutputAttr>()) {
@@ -5660,11 +5661,11 @@ class HLSLExternalSource : public ExternalSemaSource {
56605661
CXXRecordDecl *Decl = arg.getAsType()->getAsCXXRecordDecl();
56615662
if (Decl && !Decl->isCompleteDefinition())
56625663
return true;
5663-
if (ContainsLongVector(arg.getAsType())) {
5664+
unsigned DiagTypeIdx = 0;
5665+
if (ContainsLongVecOrHitObject(arg.getAsType(), DiagTypeIdx)) {
56645666
const unsigned GeometryStreamsIdx = 2;
5665-
m_sema->Diag(argLoc.getLocation(),
5666-
diag::err_hlsl_unsupported_long_vector)
5667-
<< GeometryStreamsIdx;
5667+
m_sema->Diag(argLoc.getLocation(), diag::err_hlsl_unsupported_type)
5668+
<< DiagTypeIdx << GeometryStreamsIdx;
56685669
return true;
56695670
}
56705671
}
@@ -10779,8 +10780,11 @@ bool DiagnoseIntersectionAttributes(Sema &S, SourceLocation Loc, QualType Ty) {
1077910780
}
1078010781

1078110782
if (ContainsLongVector(Ty)) {
10783+
// No need to check for HitObject, checked with attributes diagnosis.
10784+
const unsigned LongVectorIdx = 0;
1078210785
const unsigned AttributesIdx = 11;
10783-
S.Diag(Loc, diag::err_hlsl_unsupported_long_vector) << AttributesIdx;
10786+
S.Diag(Loc, diag::err_hlsl_unsupported_type)
10787+
<< LongVectorIdx << AttributesIdx;
1078410788
return false;
1078510789
}
1078610790
return true;
@@ -12119,9 +12123,10 @@ bool hlsl::DiagnoseNodeStructArgument(Sema *self, TemplateArgumentLoc ArgLoc,
1211912123
switch (shapeKind) {
1212012124
case AR_TOBJ_VECTOR:
1212112125
if (GetHLSLVecSize(ArgTy) > DXIL::kDefaultMaxVectorLength) {
12126+
const unsigned LongVectorIdx = 0;
1212212127
const unsigned NodeRecordsIdx = 3;
12123-
self->Diag(ArgLoc.getLocation(), diag::err_hlsl_unsupported_long_vector)
12124-
<< NodeRecordsIdx;
12128+
self->Diag(ArgLoc.getLocation(), diag::err_hlsl_unsupported_type)
12129+
<< LongVectorIdx << NodeRecordsIdx;
1212512130
Empty = false;
1212612131
return false;
1212712132
}
@@ -12591,6 +12596,24 @@ bool hlsl::ShouldSkipNRVO(clang::Sema &sema, clang::QualType returnType,
1259112596
return false;
1259212597
}
1259312598

12599+
bool hlsl::ContainsHitObject(QualType QT) {
12600+
if (QT.isNull() || QT->isDependentType())
12601+
return false;
12602+
12603+
while (const ArrayType *Arr = QT->getAsArrayTypeUnsafe())
12604+
QT = Arr->getElementType();
12605+
12606+
if (IsHLSLHitObjectType(QT))
12607+
return true;
12608+
12609+
if (CXXRecordDecl *Decl = QT->getAsCXXRecordDecl()) {
12610+
if (!Decl->isCompleteDefinition())
12611+
return false;
12612+
return Decl->hasHLSLHitObject();
12613+
}
12614+
return false;
12615+
}
12616+
1259412617
bool hlsl::ContainsLongVector(QualType QT) {
1259512618
if (QT.isNull() || QT->isDependentType())
1259612619
return false;
@@ -12606,6 +12629,19 @@ bool hlsl::ContainsLongVector(QualType QT) {
1260612629
return false;
1260712630
}
1260812631

12632+
bool hlsl::ContainsLongVecOrHitObject(clang::QualType QT,
12633+
unsigned &DiagTypeIdx) {
12634+
if (ContainsHitObject(QT)) {
12635+
DiagTypeIdx = 1;
12636+
return true;
12637+
}
12638+
if (ContainsLongVector(QT)) {
12639+
DiagTypeIdx = 0;
12640+
return true;
12641+
}
12642+
return false;
12643+
}
12644+
1260912645
bool hlsl::IsConversionToLessOrEqualElements(
1261012646
clang::Sema *self, const clang::ExprResult &sourceExpr,
1261112647
const clang::QualType &targetType, bool explicitConversion) {
@@ -15277,18 +15313,27 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC, Expr *BitWidth,
1527715313
}
1527815314

1527915315
// Disallow long vecs from $Global cbuffers.
15280-
if (isGlobal && !isStatic && !isGroupShared && !IS_BASIC_OBJECT(basicKind)) {
15316+
const unsigned CbuffersOrTbuffersIdx = 4;
15317+
if (isGlobal && !isStatic) {
1528115318
// Suppress actual emitting of errors for incompletable types here
1528215319
// They are redundant to those produced in ActOnUninitializedDecl.
1528315320
struct SilentDiagnoser : public TypeDiagnoser {
1528415321
SilentDiagnoser() : TypeDiagnoser(true) {}
1528515322
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {}
1528615323
} SD;
1528715324
RequireCompleteType(D.getLocStart(), qt, SD);
15288-
if (ContainsLongVector(qt)) {
15289-
unsigned CbuffersOrTbuffersIdx = 4;
15290-
Diag(D.getLocStart(), diag::err_hlsl_unsupported_long_vector)
15291-
<< CbuffersOrTbuffersIdx;
15325+
unsigned DiagTypeIdx = 0;
15326+
bool HasError = false;
15327+
if (!isGroupShared && !IS_BASIC_OBJECT(basicKind) && ContainsLongVector(qt))
15328+
HasError = true;
15329+
else if (ContainsHitObject(qt)) {
15330+
const unsigned HitObjectTypeIdx = 1;
15331+
DiagTypeIdx = HitObjectTypeIdx;
15332+
HasError = true;
15333+
}
15334+
if (HasError) {
15335+
Diag(D.getLocStart(), diag::err_hlsl_unsupported_type)
15336+
<< DiagTypeIdx << CbuffersOrTbuffersIdx;
1529215337
result = false;
1529315338
}
1529415339
}
@@ -16195,10 +16240,11 @@ static bool isRelatedDeclMarkedNointerpolation(Expr *E) {
1619516240

1619616241
// Verify that user-defined intrinsic struct args contain no long vectors
1619716242
static bool CheckUDTIntrinsicArg(Sema *S, Expr *Arg) {
16198-
if (ContainsLongVector(Arg->getType())) {
16243+
unsigned DiagTypeIdx = 0;
16244+
if (ContainsLongVecOrHitObject(Arg->getType(), DiagTypeIdx)) {
1619916245
const unsigned UserDefinedStructParameterIdx = 5;
16200-
S->Diag(Arg->getExprLoc(), diag::err_hlsl_unsupported_long_vector)
16201-
<< UserDefinedStructParameterIdx;
16246+
S->Diag(Arg->getExprLoc(), diag::err_hlsl_unsupported_type)
16247+
<< DiagTypeIdx << UserDefinedStructParameterIdx;
1620216248
return true;
1620316249
}
1620416250
return false;
@@ -16938,17 +16984,19 @@ void DiagnoseEntry(Sema &S, FunctionDecl *FD) {
1693816984
// Would be nice to check for resources here as they crash the compiler now.
1693916985
// See issue #7186.
1694016986
for (const auto *param : FD->params()) {
16941-
if (ContainsLongVector(param->getType())) {
16987+
unsigned DiagTypeIdx = 0;
16988+
if (ContainsLongVecOrHitObject(param->getType(), DiagTypeIdx)) {
1694216989
const unsigned EntryFunctionParametersIdx = 6;
16943-
S.Diag(param->getLocation(), diag::err_hlsl_unsupported_long_vector)
16944-
<< EntryFunctionParametersIdx;
16990+
S.Diag(param->getLocation(), diag::err_hlsl_unsupported_type)
16991+
<< DiagTypeIdx << EntryFunctionParametersIdx;
1694516992
}
1694616993
}
1694716994

16948-
if (ContainsLongVector(FD->getReturnType())) {
16995+
unsigned DiagTypeIdx = 0;
16996+
if (ContainsLongVecOrHitObject(FD->getReturnType(), DiagTypeIdx)) {
1694916997
const unsigned EntryFunctionReturnIdx = 7;
16950-
S.Diag(FD->getLocation(), diag::err_hlsl_unsupported_long_vector)
16951-
<< EntryFunctionReturnIdx;
16998+
S.Diag(FD->getLocation(), diag::err_hlsl_unsupported_type)
16999+
<< DiagTypeIdx << EntryFunctionReturnIdx;
1695217000
}
1695317001

1695417002
DXIL::ShaderKind Stage =

tools/clang/lib/Sema/SemaHLSLDiagnoseTU.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -709,19 +709,20 @@ void hlsl::DiagnoseTranslationUnit(clang::Sema *self) {
709709
<< hullPatchCount.value();
710710
}
711711
}
712-
for (const auto *param : pPatchFnDecl->params())
713-
if (ContainsLongVector(param->getType())) {
714-
const unsigned PatchConstantFunctionParametersIdx = 8;
715-
self->Diag(param->getLocation(),
716-
diag::err_hlsl_unsupported_long_vector)
717-
<< PatchConstantFunctionParametersIdx;
718-
}
712+
for (const auto *param : pPatchFnDecl->params()) {
713+
unsigned TypeDiagIdx = 0;
714+
const unsigned PatchConstantFunctionParametersIdx = 8;
715+
if (ContainsLongVecOrHitObject(param->getType(), TypeDiagIdx))
716+
self->Diag(param->getLocation(), diag::err_hlsl_unsupported_type)
717+
<< TypeDiagIdx << PatchConstantFunctionParametersIdx;
718+
}
719719

720-
if (ContainsLongVector(pPatchFnDecl->getReturnType())) {
720+
unsigned TypeDiagIdx = 0;
721+
if (ContainsLongVecOrHitObject(pPatchFnDecl->getReturnType(),
722+
TypeDiagIdx)) {
721723
const unsigned PatchConstantFunctionReturnIdx = 9;
722-
self->Diag(pPatchFnDecl->getLocation(),
723-
diag::err_hlsl_unsupported_long_vector)
724-
<< PatchConstantFunctionReturnIdx;
724+
self->Diag(pPatchFnDecl->getLocation(), diag::err_hlsl_unsupported_type)
725+
<< TypeDiagIdx << PatchConstantFunctionReturnIdx;
725726
}
726727
}
727728
DXIL::ShaderKind EntrySK = shaderModel->GetKind();
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %dxc -DTYPE=float -T hs_6_9 -verify %s
2+
3+
struct HsConstantData {
4+
float Edges[3] : SV_TessFactor;
5+
dx::HitObject hit;
6+
};
7+
8+
struct LongVec {
9+
float4 f;
10+
dx::HitObject hit;
11+
};
12+
13+
HsConstantData PatchConstantFunction( // expected-error{{HitObjects in patch constant function return type are not supported}}
14+
dx::HitObject hit : V, // expected-error{{HitObjects in patch constant function parameters are not supported}}
15+
LongVec lv : L) { // expected-error{{HitObjects in patch constant function parameters are not supported}}
16+
return (HsConstantData)0;
17+
}
18+
19+
[domain("tri")]
20+
[outputtopology("triangle_cw")]
21+
[outputcontrolpoints(32)]
22+
[patchconstantfunc("PatchConstantFunction")]
23+
void main() {
24+
}

0 commit comments

Comments
 (0)