Skip to content

Commit 02342c9

Browse files
committed
[HLSL] Use static create methods to initialize individual resources
1 parent dcbbda4 commit 02342c9

11 files changed

+508
-165
lines changed

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 103 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,14 @@ struct PerVisibilityBindingChecker {
12011201
}
12021202
};
12031203

1204+
static CXXMethodDecl *lookupMethod(CXXRecordDecl *Record, StringRef Name,
1205+
StorageClass SC = SC_None) {
1206+
for (auto *Method : Record->methods())
1207+
if (Method->getStorageClass() == SC && Method->getName() == Name)
1208+
return Method;
1209+
return nullptr;
1210+
}
1211+
12041212
} // end anonymous namespace
12051213

12061214
bool SemaHLSL::handleRootSignatureElements(
@@ -3689,26 +3697,6 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
36893697
deduceAddressSpace(VD);
36903698
}
36913699

3692-
static bool initVarDeclWithCtor(Sema &S, VarDecl *VD,
3693-
MutableArrayRef<Expr *> Args) {
3694-
InitializedEntity Entity = InitializedEntity::InitializeVariable(VD);
3695-
InitializationKind Kind = InitializationKind::CreateDirect(
3696-
VD->getLocation(), SourceLocation(), SourceLocation());
3697-
3698-
InitializationSequence InitSeq(S, Entity, Kind, Args);
3699-
if (InitSeq.Failed())
3700-
return false;
3701-
3702-
ExprResult Init = InitSeq.Perform(S, Entity, Kind, Args);
3703-
if (!Init.get())
3704-
return false;
3705-
3706-
VD->setInit(S.MaybeCreateExprWithCleanups(Init.get()));
3707-
VD->setInitStyle(VarDecl::CallInit);
3708-
S.CheckCompleteVariableDeclaration(VD);
3709-
return true;
3710-
}
3711-
37123700
void SemaHLSL::createResourceRecordCtorArgs(
37133701
const Type *ResourceTy, StringRef VarName, HLSLResourceBindingAttr *RBA,
37143702
HLSLVkBindingAttr *VkBinding, uint32_t ArrayIndex,
@@ -3759,11 +3747,101 @@ void SemaHLSL::createResourceRecordCtorArgs(
37593747
}
37603748

37613749
bool SemaHLSL::initGlobalResourceDecl(VarDecl *VD) {
3762-
SmallVector<Expr *> Args;
3763-
createResourceRecordCtorArgs(VD->getType().getTypePtr(), VD->getName(),
3764-
VD->getAttr<HLSLResourceBindingAttr>(),
3765-
VD->getAttr<HLSLVkBindingAttr>(), 0, Args);
3766-
return initVarDeclWithCtor(SemaRef, VD, Args);
3750+
assert(VD->getType()->isHLSLResourceRecord() &&
3751+
"expected resource record type");
3752+
3753+
ASTContext &AST = SemaRef.getASTContext();
3754+
uint64_t UIntTySize = AST.getTypeSize(AST.UnsignedIntTy);
3755+
uint64_t IntTySize = AST.getTypeSize(AST.IntTy);
3756+
3757+
// Gather resource binding information from attributes.
3758+
HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3759+
HLSLVkBindingAttr *VkBinding = VD->getAttr<HLSLVkBindingAttr>();
3760+
std::optional<uint32_t> RegisterSlot;
3761+
uint32_t SpaceNo = 0;
3762+
if (VkBinding) {
3763+
RegisterSlot = VkBinding->getBinding();
3764+
SpaceNo = VkBinding->getSet();
3765+
} else if (RBA) {
3766+
if (RBA->hasRegisterSlot())
3767+
RegisterSlot = RBA->getSlotNumber();
3768+
SpaceNo = RBA->getSpaceNumber();
3769+
}
3770+
3771+
// Find correct initialization method and create its argumentss.
3772+
QualType ResourceTy = VD->getType();
3773+
CXXRecordDecl *ResourceDecl = ResourceTy->getAsCXXRecordDecl();
3774+
CXXMethodDecl *CreateMethod = nullptr;
3775+
llvm::SmallVector<Expr *> Args;
3776+
3777+
if (RegisterSlot.has_value()) {
3778+
// The resource has explicit binding.
3779+
CreateMethod = lookupMethod(ResourceDecl, "__createFromBinding", SC_Static);
3780+
IntegerLiteral *RegSlot = IntegerLiteral::Create(
3781+
AST, llvm::APInt(UIntTySize, RegisterSlot.value()), AST.UnsignedIntTy,
3782+
SourceLocation());
3783+
Args.push_back(RegSlot);
3784+
} else {
3785+
// The resource has implicit binding.
3786+
CreateMethod =
3787+
lookupMethod(ResourceDecl, "__createFromImplicitBinding", SC_Static);
3788+
uint32_t OrderID = (RBA && RBA->hasImplicitBindingOrderID())
3789+
? RBA->getImplicitBindingOrderID()
3790+
: getNextImplicitBindingOrderID();
3791+
IntegerLiteral *OrderId =
3792+
IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, OrderID),
3793+
AST.UnsignedIntTy, SourceLocation());
3794+
Args.push_back(OrderId);
3795+
}
3796+
3797+
if (!CreateMethod)
3798+
return false;
3799+
3800+
IntegerLiteral *Space =
3801+
IntegerLiteral::Create(AST, llvm::APInt(UIntTySize, SpaceNo),
3802+
AST.UnsignedIntTy, SourceLocation());
3803+
Args.push_back(Space);
3804+
3805+
IntegerLiteral *RangeSize = IntegerLiteral::Create(
3806+
AST, llvm::APInt(IntTySize, 1), AST.IntTy, SourceLocation());
3807+
Args.push_back(RangeSize);
3808+
3809+
IntegerLiteral *Index = IntegerLiteral::Create(
3810+
AST, llvm::APInt(UIntTySize, 0), AST.UnsignedIntTy, SourceLocation());
3811+
Args.push_back(Index);
3812+
3813+
StringRef VarName = VD->getName();
3814+
StringLiteral *Name = StringLiteral::Create(
3815+
AST, VarName, StringLiteralKind::Ordinary, false,
3816+
AST.getStringLiteralArrayType(AST.CharTy.withConst(), VarName.size()),
3817+
SourceLocation());
3818+
ImplicitCastExpr *NameCast = ImplicitCastExpr::Create(
3819+
AST, AST.getPointerType(AST.CharTy.withConst()), CK_ArrayToPointerDecay,
3820+
Name, nullptr, VK_PRValue, FPOptionsOverride());
3821+
Args.push_back(NameCast);
3822+
3823+
// Make sure the create method template is instantiated and emitted.
3824+
if (!CreateMethod->isDefined() && CreateMethod->isTemplateInstantiation())
3825+
SemaRef.InstantiateFunctionDefinition(VD->getLocation(), CreateMethod,
3826+
true);
3827+
3828+
// Create CallExpr with a call to the static method and set it as the decl
3829+
// initialization.
3830+
DeclRefExpr *DRE = DeclRefExpr::Create(
3831+
AST, NestedNameSpecifierLoc(), SourceLocation(), CreateMethod, false,
3832+
CreateMethod->getNameInfo(), CreateMethod->getType(), VK_PRValue);
3833+
3834+
auto *ImpCast = ImplicitCastExpr::Create(
3835+
AST, AST.getPointerType(CreateMethod->getType()),
3836+
CK_FunctionToPointerDecay, DRE, nullptr, VK_PRValue, FPOptionsOverride());
3837+
3838+
CallExpr *InitExpr =
3839+
CallExpr::Create(AST, ImpCast, Args, ResourceTy, VK_PRValue,
3840+
SourceLocation(), FPOptionsOverride());
3841+
VD->setInit(InitExpr);
3842+
VD->setInitStyle(VarDecl::CallInit);
3843+
SemaRef.CheckCompleteVariableDeclaration(VD);
3844+
return true;
37673845
}
37683846

37693847
bool SemaHLSL::initGlobalResourceArrayDecl(VarDecl *VD) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ RESOURCE Buffer;
3434

3535
#endif
3636

37-
// CHECK: CXXRecordDecl {{.*}} implicit referenced <undeserialized declarations> class [[RESOURCE]] definition
37+
// CHECK: CXXRecordDecl {{.*}} implicit referenced class [[RESOURCE]] definition
3838
// CHECK: FinalAttr {{.*}} Implicit final
3939
// CHECK-NEXT: FieldDecl {{.*}} implicit __handle '__hlsl_resource_t
4040
// CHECK-SRV-SAME{LITERAL}: [[hlsl::resource_class(SRV)]]

clang/test/AST/HLSL/vk_binding_attr.hlsl

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,23 @@
22
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.8-library -finclude-default-header -ast-dump -o - %s | FileCheck %s -check-prefixes=DXIL,CHECK
33

44
// CHECK: VarDecl {{.*}} Buf 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
5-
// SPV-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
5+
// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
6+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer<float> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
7+
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
8+
// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
69
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
710
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102
8-
// DXIL-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
911
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
10-
// DXIL-NEXT: IntegerLiteral {{.*}} 'int' 1
12+
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
1113
// SPV: HLSLVkBindingAttr {{.*}} 23 102
1214
// DXIL-NOT: HLSLVkBindingAttr
1315
[[vk::binding(23, 102)]] StructuredBuffer<float> Buf;
1416

1517
// CHECK: VarDecl {{.*}} Buf2 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
16-
// CHECK-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
18+
// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
19+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer<float> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
20+
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
21+
// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
1722
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 14
1823
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
1924
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
@@ -24,7 +29,10 @@
2429
[[vk::binding(14, 1)]] StructuredBuffer<float> Buf2 : register(t23, space102);
2530

2631
// CHECK: VarDecl {{.*}} Buf3 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
27-
// CHECK-NEXT: CXXConstructExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
32+
// CHECK-NEXT: CallExpr {{.*}} 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
33+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::StructuredBuffer<float> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
34+
// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
35+
// CHECK-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::StructuredBuffer<float> (unsigned int, unsigned int, int, unsigned int, const char *)'
2836
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 14
2937
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
3038
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
@@ -43,28 +51,46 @@
4351
}
4452

4553
// CHECK: VarDecl {{.*}} Buf4 'Buffer<int>':'hlsl::Buffer<int>'
46-
// SPV-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
54+
// CHECK-NEXT: CallExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>'
55+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::Buffer<int> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
56+
// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
57+
// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
4758
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 24
4859
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 103
49-
// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
60+
// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
61+
// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
62+
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
63+
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
5064
// SPV: HLSLVkBindingAttr {{.*}} 24 103
5165
// DXIL-NOT: HLSLVkBindingAttr
5266
[[vk::binding(24, 103)]] Buffer<int> Buf4;
5367

5468
// CHECK: VarDecl {{.*}} Buf5 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>'
55-
// SPV-NEXT: CXXConstructExpr {{.*}} 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
69+
// CHECK-NEXT: CallExpr {{.*}} 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>'
70+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::RWBuffer<vector<int, 2>> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
71+
// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::RWBuffer<vector<int, 2>> (unsigned int, unsigned int, int, unsigned int, const char *)'
72+
// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer<int2> (unsigned int, unsigned int, int, unsigned int, const char *)'
5673
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 25
5774
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 104
58-
// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
75+
// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::RWBuffer<vector<int, 2>> (unsigned int, unsigned int, int, unsigned int, const char *)'
76+
// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int2> (unsigned int, unsigned int, int, unsigned int, const char *)'
77+
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
78+
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
5979
// SPV: HLSLVkBindingAttr {{.*}} 25 104
6080
// DXIL-NOT: HLSLVkBindingAttr
6181
[[vk::binding(25, 104)]] RWBuffer<int2> Buf5;
6282

6383
// CHECK: VarDecl {{.*}} Buf6 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>'
64-
// SPV-NEXT: CXXConstructExpr {{.*}} 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>' 'void (unsigned int, unsigned int, int, unsigned int, const char *)'
84+
// CHECK-NEXT: CallExpr {{.*}} 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>'
85+
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::RWStructuredBuffer<int> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
86+
// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
87+
// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
6588
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 26
6689
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 105
67-
// DXL-NEXT: CXXConstructExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>' 'void (unsigned int, int, unsigned int, unsigned int, const char *)'
90+
// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
91+
// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
92+
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 4
93+
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
6894
// SPV: HLSLVkBindingAttr {{.*}} 26 105
6995
// DXIL-NOT: HLSLVkBindingAttr
7096
[[vk::binding(26, 105)]] RWStructuredBuffer<int> Buf6;

clang/test/CodeGenHLSL/GlobalConstructorLib.hlsl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ void SecondEntry() {}
3131
// CHECK: ret void
3232

3333

34-
// Verify the constructor is alwaysinline
34+
// Verify the constructors are alwaysinline
3535
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
36-
// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EjijjPKc({{.*}} [[CtorAttr:\#[0-9]+]]
36+
// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC1EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) {{.*}} [[CtorAttr:\#[0-9]+]]
37+
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
38+
// NOINLINE-NEXT: define linkonce_odr hidden void @_ZN4hlsl8RWBufferIfEC2EU9_Res_u_CTfu17__hlsl_resource_t(ptr {{.*}} %this, target("dx.TypedBuffer", float, 1, 0, 0) %handle) {{.*}} [[CtorAttr]]
3739

3840
// NOINLINE: ; Function Attrs: {{.*}}alwaysinline
3941
// NOINLINE-NEXT: define internal void @_GLOBAL__sub_I_GlobalConstructorLib.hlsl() [[InitAttr:\#[0-9]+]]

clang/test/CodeGenHLSL/debug/rwbuffer_debug_info.hlsl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.6-compute -x hlsl -emit-llvm -disable-llvm-passes -o - -hlsl-entry main %s -debug-info-kind=standalone -dwarf-version=4 | FileCheck %s
22

3-
43
// CHECK: [[DWTag:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "RWBuffer<float>",
4+
// CHECK: [[thisType:![0-9]+]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[DWTag]], size: 32)
55
// CHECK: [[RWBuffer:![0-9]+]] = distinct !DISubprogram(name: "RWBuffer",
66
// CHECK-SAME: scope: [[DWTag]]
7-
// CHECK: [[FirstThis:![0-9]+]] = !DILocalVariable(name: "this", arg: 1, scope: [[RWBuffer]], type: [[thisType:![0-9]+]]
8-
// CHECK: [[thisType]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[DWTag]], size: 32)
7+
// CHECK: [[FirstThis:![0-9]+]] = !DILocalVariable(name: "this", arg: 1, scope: [[RWBuffer]], type: [[thisType]]
98
RWBuffer<float> Out : register(u7, space4);
109

1110
[numthreads(8,1,1)]

0 commit comments

Comments
 (0)