Skip to content

Commit 4512bbe

Browse files
authored
[HLSL] Collect explicit resource binding information (#111203)
Scans each global variable declaration and its members and collects all required resource bindings in a new `SemaHLSL` data member `Bindings`. New fields are added `HLSLResourceBindingAttr` for storing processed binding information so that it can be used by CodeGen (`Bindings` or any other Sema information is not accessible from CodeGen.) Adjusts the existing register binding attribute handling and diagnostics to: - do not create HLSLResourceBindingAttribute if it is not valid - diagnose only the simple/local errors when a register binding attribute is parsed - additional diagnostic of binding type mismatches is done later and uses the new `Bindings` data Fixes #110719
1 parent 1b4a173 commit 4512bbe

File tree

5 files changed

+352
-117
lines changed

5 files changed

+352
-117
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4593,6 +4593,31 @@ def HLSLResourceBinding: InheritableAttr {
45934593
let LangOpts = [HLSL];
45944594
let Args = [StringArgument<"Slot">, StringArgument<"Space", 1>];
45954595
let Documentation = [HLSLResourceBindingDocs];
4596+
let AdditionalMembers = [{
4597+
public:
4598+
enum class RegisterType : unsigned { SRV, UAV, CBuffer, Sampler, C, I };
4599+
4600+
private:
4601+
RegisterType RegType;
4602+
unsigned SlotNumber;
4603+
unsigned SpaceNumber;
4604+
4605+
public:
4606+
void setBinding(RegisterType RT, unsigned SlotNum, unsigned SpaceNum) {
4607+
RegType = RT;
4608+
SlotNumber = SlotNum;
4609+
SpaceNumber = SpaceNum;
4610+
}
4611+
RegisterType getRegisterType() const {
4612+
return RegType;
4613+
}
4614+
unsigned getSlotNumber() const {
4615+
return SlotNumber;
4616+
}
4617+
unsigned getSpaceNumber() const {
4618+
return SpaceNumber;
4619+
}
4620+
}];
45964621
}
45974622

45984623
def HLSLPackOffset: HLSLAnnotationAttr {

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,60 @@ class AttributeCommonInfo;
2828
class IdentifierInfo;
2929
class ParsedAttr;
3030
class Scope;
31+
class VarDecl;
32+
33+
using llvm::dxil::ResourceClass;
3134

3235
// FIXME: This can be hidden (as static function in SemaHLSL.cpp) once we no
3336
// longer need to create builtin buffer types in HLSLExternalSemaSource.
3437
bool CreateHLSLAttributedResourceType(
3538
Sema &S, QualType Wrapped, ArrayRef<const Attr *> AttrList,
3639
QualType &ResType, HLSLAttributedResourceLocInfo *LocInfo = nullptr);
3740

41+
enum class BindingType : uint8_t { NotAssigned, Explicit, Implicit };
42+
43+
// DeclBindingInfo struct stores information about required/assigned resource
44+
// binding onon a declaration for specific resource class.
45+
struct DeclBindingInfo {
46+
const VarDecl *Decl;
47+
ResourceClass ResClass;
48+
const HLSLResourceBindingAttr *Attr;
49+
BindingType BindType;
50+
51+
DeclBindingInfo(const VarDecl *Decl, ResourceClass ResClass,
52+
BindingType BindType = BindingType::NotAssigned,
53+
const HLSLResourceBindingAttr *Attr = nullptr)
54+
: Decl(Decl), ResClass(ResClass), Attr(Attr), BindType(BindType) {}
55+
56+
void setBindingAttribute(HLSLResourceBindingAttr *A, BindingType BT) {
57+
assert(Attr == nullptr && BindType == BindingType::NotAssigned &&
58+
"binding attribute already assigned");
59+
Attr = A;
60+
BindType = BT;
61+
}
62+
};
63+
64+
// ResourceBindings class stores information about all resource bindings
65+
// in a shader. It is used for binding diagnostics and implicit binding
66+
// assigments.
67+
class ResourceBindings {
68+
public:
69+
DeclBindingInfo *addDeclBindingInfo(const VarDecl *VD,
70+
ResourceClass ResClass);
71+
DeclBindingInfo *getDeclBindingInfo(const VarDecl *VD,
72+
ResourceClass ResClass);
73+
bool hasBindingInfoForDecl(const VarDecl *VD) const;
74+
75+
private:
76+
// List of all resource bindings required by the shader.
77+
// A global declaration can have multiple bindings for different
78+
// resource classes. They are all stored sequentially in this list.
79+
// The DeclToBindingListIndex hashtable maps a declaration to the
80+
// index of the first binding info in the list.
81+
llvm::SmallVector<DeclBindingInfo> BindingsList;
82+
llvm::DenseMap<const VarDecl *, unsigned> DeclToBindingListIndex;
83+
};
84+
3885
class SemaHLSL : public SemaBase {
3986
public:
4087
SemaHLSL(Sema &S);
@@ -55,6 +102,7 @@ class SemaHLSL : public SemaBase {
55102
mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL,
56103
HLSLParamModifierAttr::Spelling Spelling);
57104
void ActOnTopLevelFunction(FunctionDecl *FD);
105+
void ActOnVariableDeclarator(VarDecl *VD);
58106
void CheckEntryPoint(FunctionDecl *FD);
59107
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
60108
const HLSLAnnotationAttr *AnnotationAttr);
@@ -102,6 +150,15 @@ class SemaHLSL : public SemaBase {
102150
llvm::DenseMap<const HLSLAttributedResourceType *,
103151
HLSLAttributedResourceLocInfo>
104152
LocsForHLSLAttributedResources;
153+
154+
// List of all resource bindings
155+
ResourceBindings Bindings;
156+
157+
private:
158+
void collectResourcesOnVarDecl(VarDecl *D);
159+
void collectResourcesOnUserRecordDecl(const VarDecl *VD,
160+
const RecordType *RT);
161+
void processExplicitBindingsOnDecl(VarDecl *D);
105162
};
106163

107164
} // namespace clang

clang/lib/Sema/SemaDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7883,6 +7883,9 @@ NamedDecl *Sema::ActOnVariableDeclarator(
78837883
// Handle attributes prior to checking for duplicates in MergeVarDecl
78847884
ProcessDeclAttributes(S, NewVD, D);
78857885

7886+
if (getLangOpts().HLSL)
7887+
HLSL().ActOnVariableDeclarator(NewVD);
7888+
78867889
// FIXME: This is probably the wrong location to be doing this and we should
78877890
// probably be doing this for more attributes (especially for function
78887891
// pointer attributes such as format, warn_unused_result, etc.). Ideally

0 commit comments

Comments
 (0)