Skip to content

Commit 5dc371e

Browse files
bob80905damyanp
andauthored
[HLSL] Split out resource class data from resource attribute (#98419)
The ability to spell out and specify the resource class is necessary for testing various resource binding behaviors. Though it is not intended for users to use this in customized HLSL source code, the ability to specify the resource class via an attribute is immensely helpful for writing thorough tests. This PR introduces a new attribute, hlsl::resource_attribute, that can only be applied on structs. This attribute only has 1 required argument, and must be one of: ``` SRV UAV CBuffer Sampler ``` By applying this attribute to a struct, the struct will have the `HLSLResourceClassAttr` attribute attached to it in the AST representation, which provides information on the type of resource class the struct is meant to be. The resource class data that was originally contained within the `HLSLResourceAttr` attribute has been removed in favor of this new attribute, and so certain ast-dump tests need to be modified so that the same information can be represented via 2 attributes instead of one. Fixes #98193 --------- Co-authored-by: Damyan Pepper <[email protected]>
1 parent eb27256 commit 5dc371e

File tree

10 files changed

+105
-18
lines changed

10 files changed

+105
-18
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4561,11 +4561,7 @@ def HLSLResource : InheritableAttr {
45614561
let Spellings = [];
45624562
let Subjects = SubjectList<[Struct]>;
45634563
let LangOpts = [HLSL];
4564-
let Args = [
4565-
EnumArgument<"ResourceClass", "llvm::hlsl::ResourceClass",
4566-
/*is_string=*/0, ["SRV", "UAV", "CBuffer", "Sampler"],
4567-
["SRV", "UAV", "CBuffer", "Sampler"],
4568-
/*opt=*/0, /*fake=*/0, /*isExternalType=*/1>,
4564+
let Args = [
45694565
EnumArgument<
45704566
"ResourceKind", "llvm::hlsl::ResourceKind",
45714567
/*is_string=*/0,
@@ -4589,6 +4585,19 @@ def HLSLResource : InheritableAttr {
45894585
let Documentation = [InternalOnly];
45904586
}
45914587

4588+
def HLSLResourceClass : InheritableAttr {
4589+
let Spellings = [CXX11<"hlsl", "resource_class">];
4590+
let Subjects = SubjectList<[Struct]>;
4591+
let LangOpts = [HLSL];
4592+
let Args = [
4593+
EnumArgument<"ResourceClass", "llvm::hlsl::ResourceClass",
4594+
/*is_string=*/true, ["SRV", "UAV", "CBuffer", "Sampler"],
4595+
["SRV", "UAV", "CBuffer", "Sampler"],
4596+
/*opt=*/0, /*fake=*/0, /*isExternalType=*/1>
4597+
];
4598+
let Documentation = [InternalOnly];
4599+
}
4600+
45924601
def HLSLGroupSharedAddressSpace : TypeAttr {
45934602
let Spellings = [CustomKeyword<"groupshared">];
45944603
let Subjects = SubjectList<[Var]>;

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class SemaHLSL : public SemaBase {
5656
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
5757
void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
5858
void handleShaderAttr(Decl *D, const ParsedAttr &AL);
59+
void handleResourceClassAttr(Decl *D, const ParsedAttr &AL);
5960
void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
6061
void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
6162

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -280,13 +280,14 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
280280
const auto *RD = Ty->getAsCXXRecordDecl();
281281
if (!RD)
282282
return;
283-
const auto *Attr = RD->getAttr<HLSLResourceAttr>();
284-
if (!Attr)
283+
const auto *HLSLResAttr = RD->getAttr<HLSLResourceAttr>();
284+
const auto *HLSLResClassAttr = RD->getAttr<HLSLResourceClassAttr>();
285+
if (!HLSLResAttr || !HLSLResClassAttr)
285286
return;
286287

287-
llvm::hlsl::ResourceClass RC = Attr->getResourceClass();
288-
llvm::hlsl::ResourceKind RK = Attr->getResourceKind();
289-
bool IsROV = Attr->getIsROV();
288+
llvm::hlsl::ResourceClass RC = HLSLResClassAttr->getResourceClass();
289+
llvm::hlsl::ResourceKind RK = HLSLResAttr->getResourceKind();
290+
bool IsROV = HLSLResAttr->getIsROV();
290291
llvm::hlsl::ElementType ET = calculateElementType(CGM.getContext(), Ty);
291292

292293
BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>());

clang/lib/Sema/HLSLExternalSemaSource.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,14 @@ struct BuiltinTypeDeclBuilder {
115115
return addMemberVariable("h", Ty, Access);
116116
}
117117

118-
BuiltinTypeDeclBuilder &annotateResourceClass(ResourceClass RC,
119-
ResourceKind RK, bool IsROV) {
118+
BuiltinTypeDeclBuilder &annotateHLSLResource(ResourceClass RC,
119+
ResourceKind RK, bool IsROV) {
120120
if (Record->isCompleteDefinition())
121121
return *this;
122-
Record->addAttr(HLSLResourceAttr::CreateImplicit(Record->getASTContext(),
123-
RC, RK, IsROV));
122+
Record->addAttr(
123+
HLSLResourceClassAttr::CreateImplicit(Record->getASTContext(), RC));
124+
Record->addAttr(
125+
HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RK, IsROV));
124126
return *this;
125127
}
126128

@@ -171,7 +173,6 @@ struct BuiltinTypeDeclBuilder {
171173

172174
DeclRefExpr *Fn =
173175
lookupBuiltinFunction(AST, S, "__builtin_hlsl_create_handle");
174-
175176
Expr *RCExpr = emitResourceClassExpr(AST, RC);
176177
Expr *Call = CallExpr::Create(AST, Fn, {RCExpr}, AST.VoidPtrTy, VK_PRValue,
177178
SourceLocation(), FPOptionsOverride());
@@ -496,7 +497,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S,
496497
return BuiltinTypeDeclBuilder(Decl)
497498
.addHandleMember()
498499
.addDefaultHandleConstructor(S, RC)
499-
.annotateResourceClass(RC, RK, IsROV);
500+
.annotateHLSLResource(RC, RK, IsROV);
500501
}
501502

502503
void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7053,6 +7053,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
70537053
case ParsedAttr::AT_HLSLResourceBinding:
70547054
S.HLSL().handleResourceBindingAttr(D, AL);
70557055
break;
7056+
case ParsedAttr::AT_HLSLResourceClass:
7057+
S.HLSL().handleResourceClassAttr(D, AL);
7058+
break;
70567059
case ParsedAttr::AT_HLSLParamModifier:
70577060
S.HLSL().handleParamModifierAttr(D, AL);
70587061
break;

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,28 @@ void SemaHLSL::handleShaderAttr(Decl *D, const ParsedAttr &AL) {
437437
D->addAttr(NewAttr);
438438
}
439439

440+
void SemaHLSL::handleResourceClassAttr(Decl *D, const ParsedAttr &AL) {
441+
if (!AL.isArgIdent(0)) {
442+
Diag(AL.getLoc(), diag::err_attribute_argument_type)
443+
<< AL << AANT_ArgumentIdentifier;
444+
return;
445+
}
446+
447+
IdentifierLoc *Loc = AL.getArgAsIdent(0);
448+
StringRef Identifier = Loc->Ident->getName();
449+
SourceLocation ArgLoc = Loc->Loc;
450+
451+
// Validate.
452+
llvm::dxil::ResourceClass RC;
453+
if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
454+
Diag(ArgLoc, diag::warn_attribute_type_not_supported)
455+
<< "ResourceClass" << Identifier;
456+
return;
457+
}
458+
459+
D->addAttr(HLSLResourceClassAttr::Create(getASTContext(), RC, ArgLoc));
460+
}
461+
440462
void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) {
441463
StringRef Space = "space0";
442464
StringRef Slot = "";

clang/test/AST/HLSL/RWBuffer-AST.hlsl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ RWBuffer<float> Buffer;
3434
// CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit class RWBuffer definition
3535

3636
// CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
37-
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV TypedBuffer
37+
// CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV
38+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
3839
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit h 'element_type *'
3940

4041
// CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> operator[] 'element_type &const (unsigned int) const'
@@ -62,5 +63,6 @@ RWBuffer<float> Buffer;
6263
// CHECK: TemplateArgument type 'float'
6364
// CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float'
6465
// CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
65-
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV TypedBuffer
66+
// CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit UAV
67+
// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit TypedBuffer
6668
// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> implicit referenced h 'float *'

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
// CHECK-NEXT: FunctionReturnThunks (SubjectMatchRule_function)
8282
// CHECK-NEXT: GNUInline (SubjectMatchRule_function)
8383
// CHECK-NEXT: HIPManaged (SubjectMatchRule_variable)
84+
// CHECK-NEXT: HLSLResourceClass (SubjectMatchRule_record_not_is_union)
8485
// CHECK-NEXT: Hot (SubjectMatchRule_function)
8586
// CHECK-NEXT: IBAction (SubjectMatchRule_objc_method_is_instance)
8687
// CHECK-NEXT: IFunc (SubjectMatchRule_function)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s | FileCheck %s
2+
3+
4+
// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> SRV
5+
struct [[hlsl::resource_class(SRV)]] Eg1 {
6+
int i;
7+
};
8+
9+
Eg1 e1;
10+
11+
// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} <line:13:1, line:15:1> line:13:38 referenced struct Eg2 definition
12+
// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> UAV
13+
struct [[hlsl::resource_class(UAV)]] Eg2 {
14+
int i;
15+
};
16+
Eg2 e2;
17+
18+
// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} <line:20:1, line:22:1> line:20:42 referenced struct Eg3 definition
19+
// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> CBuffer
20+
struct [[hlsl::resource_class(CBuffer)]] Eg3 {
21+
int i;
22+
};
23+
Eg3 e3;
24+
25+
// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} <line:27:1, line:29:1> line:27:42 referenced struct Eg4 definition
26+
// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> Sampler
27+
struct [[hlsl::resource_class(Sampler)]] Eg4 {
28+
int i;
29+
};
30+
Eg4 e4;
31+
32+
RWBuffer<int> In : register(u1);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o - %s -verify
2+
3+
// expected-error@+1{{'resource_class' attribute takes one argument}}
4+
struct [[hlsl::resource_class()]] Eg1 {
5+
int i;
6+
};
7+
8+
Eg1 e1;
9+
10+
// expected-warning@+1{{ResourceClass attribute argument not supported: gibberish}}
11+
struct [[hlsl::resource_class(gibberish)]] Eg2 {
12+
int i;
13+
};
14+
15+
Eg2 e2;

0 commit comments

Comments
 (0)