Skip to content

Commit 0afad1c

Browse files
committed
[HLSL] Rework semantic handling as attributes
Previously, we had 2 level of attributes: - HLSLUnparsedSemantic - N attributes, one for each known system semantic. The first was assigned during parsing, and carried no other meaning than "there is a semantic token". It was then converted to one of the N attributes later during Sema. Those attributes also carried informations like "is indexable" or "is index explicit". This had a few issues: - there was no difference between a semantic attribute applied to a decl, and the effective semantic in the entrypoint use context. - having the indexable bit was not useful. - semantic constraints checks were split between .td files and sema. Also, existing implementation had effective attributes attached to the type decl or parameters, meaning struct decl reuse across entrypoints of in a nested type was not supported, even if legal in HLSL. This PR tried to simplifies semantic attribute by having 3 attributes: - HLSLUnpasedSemantic - HLSLParsedSemantic - HLSLAppliedSemantic Initial parsing emits an `HLSLUnparsedSemantic`. We simply say "here is an HLSL semantic token", but we don't do any semantic check. Then, Sema does initial validation and transforms an UnparseSemantic into a ParsedSemantic. This validates a system semantic is known, or that the associated type is valid (like uint3 for a ThreadIndex). Then, once we parse an actual shader entrypoint, we can know how semantics are used in a real context. This step emits a list of AppliedSemantic. Those are the actual semantic in use for this specific entrypoint. Those attributes are attached to each entrypoint parameter, as a flat list matching the semantic structure flattening HLSL defines. At this stage of sema, index collision or other stage compabitility checkes are carried. This allows codegen to simply iterate over this list and emit the proper DXIL or SPIR-V codegen.
1 parent a96ad13 commit 0afad1c

20 files changed

+269
-361
lines changed

clang/include/clang/AST/Attr.h

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -233,44 +233,19 @@ class HLSLAnnotationAttr : public InheritableAttr {
233233
}
234234
};
235235

236-
class HLSLSemanticAttr : public HLSLAnnotationAttr {
237-
unsigned SemanticIndex = 0;
238-
LLVM_PREFERRED_TYPE(bool)
239-
unsigned SemanticIndexable : 1;
240-
LLVM_PREFERRED_TYPE(bool)
241-
unsigned SemanticExplicitIndex : 1;
242-
243-
Decl *TargetDecl = nullptr;
244-
236+
class HLSLSemanticBaseAttr : public HLSLAnnotationAttr {
245237
protected:
246-
HLSLSemanticAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo,
247-
attr::Kind AK, bool IsLateParsed,
248-
bool InheritEvenIfAlreadyPresent, bool SemanticIndexable)
238+
HLSLSemanticBaseAttr(ASTContext &Context,
239+
const AttributeCommonInfo &CommonInfo, attr::Kind AK,
240+
bool IsLateParsed, bool InheritEvenIfAlreadyPresent)
249241
: HLSLAnnotationAttr(Context, CommonInfo, AK, IsLateParsed,
250-
InheritEvenIfAlreadyPresent) {
251-
this->SemanticIndexable = SemanticIndexable;
252-
this->SemanticExplicitIndex = false;
253-
}
242+
InheritEvenIfAlreadyPresent) {}
254243

255244
public:
256-
bool isSemanticIndexable() const { return SemanticIndexable; }
257-
258-
void setSemanticIndex(unsigned SemanticIndex) {
259-
this->SemanticIndex = SemanticIndex;
260-
this->SemanticExplicitIndex = true;
261-
}
262-
263-
unsigned getSemanticIndex() const { return SemanticIndex; }
264-
265-
bool isSemanticIndexExplicit() const { return SemanticExplicitIndex; }
266-
267-
void setTargetDecl(Decl *D) { TargetDecl = D; }
268-
Decl *getTargetDecl() const { return TargetDecl; }
269-
270245
// Implement isa/cast/dyncast/etc.
271246
static bool classof(const Attr *A) {
272-
return A->getKind() >= attr::FirstHLSLSemanticAttr &&
273-
A->getKind() <= attr::LastHLSLSemanticAttr;
247+
return A->getKind() >= attr::FirstHLSLSemanticBaseAttr &&
248+
A->getKind() <= attr::LastHLSLSemanticBaseAttr;
274249
}
275250
};
276251

clang/include/clang/Basic/Attr.td

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -779,18 +779,6 @@ class DeclOrStmtAttr : InheritableAttr;
779779
/// An attribute class for HLSL Annotations.
780780
class HLSLAnnotationAttr : InheritableAttr;
781781

782-
class HLSLSemanticAttr<bit Indexable> : HLSLAnnotationAttr {
783-
bit SemanticIndexable = Indexable;
784-
int SemanticIndex = 0;
785-
bit SemanticExplicitIndex = 0;
786-
787-
let Spellings = [];
788-
let Subjects = SubjectList<[ParmVar, Field, Function]>;
789-
let LangOpts = [HLSL];
790-
let Args = [DeclArgument<Named, "Target">, IntArgument<"SemanticIndex">,
791-
BoolArgument<"SemanticExplicitIndex">];
792-
}
793-
794782
/// A target-specific attribute. This class is meant to be used as a mixin
795783
/// with InheritableAttr or Attr depending on the attribute's needs.
796784
class TargetSpecificAttr<TargetSpec target> {
@@ -5017,28 +5005,30 @@ def HLSLUnparsedSemantic : HLSLAnnotationAttr {
50175005
let Documentation = [InternalOnly];
50185006
}
50195007

5020-
def HLSLUserSemantic : HLSLSemanticAttr</* Indexable= */ 1> {
5021-
let Documentation = [InternalOnly];
5022-
}
5008+
class HLSLSemanticBaseAttr : HLSLAnnotationAttr {
5009+
int SemanticIndex = 0;
50235010

5024-
def HLSLSV_Position : HLSLSemanticAttr</* Indexable= */ 1> {
5025-
let Documentation = [HLSLSV_PositionDocs];
5011+
let Spellings = [];
5012+
let Subjects = SubjectList<[ParmVar, Field, Function]>;
5013+
let LangOpts = [HLSL];
50265014
}
50275015

5028-
def HLSLSV_GroupThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
5029-
let Documentation = [HLSLSV_GroupThreadIDDocs];
5030-
}
5016+
def HLSLParsedSemantic : HLSLSemanticBaseAttr {
5017+
let Spellings = [];
5018+
let Subjects = SubjectList<[ParmVar, Field, Function]>;
5019+
let LangOpts = [HLSL];
5020+
let Documentation = [InternalOnly];
50315021

5032-
def HLSLSV_GroupID : HLSLSemanticAttr</* Indexable= */ 0> {
5033-
let Documentation = [HLSLSV_GroupIDDocs];
5022+
let Args = [StringArgument<"SemanticName">, IntArgument<"SemanticIndex">];
50345023
}
50355024

5036-
def HLSLSV_GroupIndex : HLSLSemanticAttr</* Indexable= */ 0> {
5037-
let Documentation = [HLSLSV_GroupIndexDocs];
5038-
}
5025+
def HLSLAppliedSemantic : HLSLSemanticBaseAttr {
5026+
let Spellings = [];
5027+
let Subjects = SubjectList<[ParmVar, Field, Function]>;
5028+
let LangOpts = [HLSL];
5029+
let Documentation = [InternalOnly];
50395030

5040-
def HLSLSV_DispatchThreadID : HLSLSemanticAttr</* Indexable= */ 0> {
5041-
let Documentation = [HLSLSV_DispatchThreadIDDocs];
5031+
let Args = [StringArgument<"SemanticName">, IntArgument<"SemanticIndex">];
50425032
}
50435033

50445034
def HLSLPackOffset: HLSLAnnotationAttr {

clang/include/clang/Basic/AttrDocs.td

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -8672,38 +8672,6 @@ randomized.
86728672
}];
86738673
}
86748674

8675-
def HLSLSV_GroupThreadIDDocs : Documentation {
8676-
let Category = DocHLSLSemantics;
8677-
let Content = [{
8678-
The ``SV_GroupThreadID`` semantic, when applied to an input parameter, specifies which
8679-
individual thread within a thread group is executing in. This attribute is
8680-
only supported in compute shaders.
8681-
8682-
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupthreadid
8683-
}];
8684-
}
8685-
8686-
def HLSLSV_GroupIDDocs : Documentation {
8687-
let Category = DocHLSLSemantics;
8688-
let Content = [{
8689-
The ``SV_GroupID`` semantic, when applied to an input parameter, specifies which
8690-
thread group a shader is executing in. This attribute is only supported in compute shaders.
8691-
8692-
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupid
8693-
}];
8694-
}
8695-
8696-
def HLSLSV_GroupIndexDocs : Documentation {
8697-
let Category = DocHLSLSemantics;
8698-
let Content = [{
8699-
The ``SV_GroupIndex`` semantic, when applied to an input parameter, specifies a
8700-
data binding to map the group index to the specified parameter. This attribute
8701-
is only supported in compute shaders.
8702-
8703-
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-groupindex
8704-
}];
8705-
}
8706-
87078675
def HLSLResourceBindingDocs : Documentation {
87088676
let Category = DocCatFunction;
87098677
let Content = [{
@@ -8750,35 +8718,6 @@ The full documentation is available here: https://learn.microsoft.com/en-us/wind
87508718
}];
87518719
}
87528720

8753-
def HLSLSV_DispatchThreadIDDocs : Documentation {
8754-
let Category = DocHLSLSemantics;
8755-
let Content = [{
8756-
The ``SV_DispatchThreadID`` semantic, when applied to an input parameter,
8757-
specifies a data binding to map the global thread offset within the Dispatch
8758-
call (per dimension of the group) to the specified parameter.
8759-
When applied to a field of a struct, the data binding is specified to the field
8760-
when the struct is used as a parameter type.
8761-
The semantic on the field is ignored when not used as a parameter.
8762-
This attribute is only supported in compute shaders.
8763-
8764-
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sv-dispatchthreadid
8765-
}];
8766-
}
8767-
8768-
def HLSLSV_PositionDocs : Documentation {
8769-
let Category = DocHLSLSemantics;
8770-
let Content = [{
8771-
The ``SV_Position`` semantic, when applied to an input parameter in a pixel
8772-
shader, contains the location of the pixel center (x, y) in screen space.
8773-
This semantic can be applied to the parameter, or a field in a struct used
8774-
as an input parameter.
8775-
This attribute is supported as an input in pixel, hull, domain and mesh shaders.
8776-
This attribute is supported as an output in vertex, geometry and domain shaders.
8777-
8778-
The full documentation is available here: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics
8779-
}];
8780-
}
8781-
87828721
def HLSLGroupSharedAddressSpaceDocs : Documentation {
87838722
let Category = DocCatVariable;
87848723
let Content = [{

clang/include/clang/Sema/SemaHLSL.h

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -178,18 +178,11 @@ class SemaHLSL : public SemaBase {
178178
bool handleResourceTypeAttr(QualType T, const ParsedAttr &AL);
179179

180180
template <typename T>
181-
T *createSemanticAttr(const AttributeCommonInfo &ACI, NamedDecl *TargetDecl,
181+
T *createSemanticAttr(const AttributeCommonInfo &ACI,
182182
std::optional<unsigned> Location) {
183-
T *Attr =
184-
::new (getASTContext()) T(getASTContext(), ACI, TargetDecl,
185-
Location.value_or(0), Location.has_value());
186-
187-
if (!Attr->isSemanticIndexable() && Location.has_value()) {
188-
Diag(Attr->getLocation(), diag::err_hlsl_semantic_indexing_not_supported)
189-
<< Attr->getAttrName()->getName();
190-
return nullptr;
191-
}
192-
return Attr;
183+
return ::new (getASTContext())
184+
T(getASTContext(), ACI, ACI.getAttrName()->getName(),
185+
Location.value_or(0));
193186
}
194187

195188
void diagnoseSystemSemanticAttr(Decl *D, const ParsedAttr &AL,
@@ -247,7 +240,7 @@ class SemaHLSL : public SemaBase {
247240
IdentifierInfo *RootSigOverrideIdent = nullptr;
248241

249242
struct SemanticInfo {
250-
HLSLSemanticAttr *Semantic;
243+
HLSLParsedSemanticAttr *Semantic;
251244
std::optional<uint32_t> Index;
252245
};
253246

@@ -257,14 +250,14 @@ class SemaHLSL : public SemaBase {
257250
const RecordType *RT);
258251

259252
void checkSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
260-
const HLSLSemanticAttr *SemanticAttr);
261-
HLSLSemanticAttr *createSemantic(const SemanticInfo &Semantic,
262-
DeclaratorDecl *TargetDecl);
263-
bool determineActiveSemanticOnScalar(FunctionDecl *FD, DeclaratorDecl *D,
253+
const HLSLAppliedSemanticAttr *SemanticAttr);
254+
bool determineActiveSemanticOnScalar(FunctionDecl *FD,
255+
DeclaratorDecl *OutputDecl,
256+
DeclaratorDecl *D,
264257
SemanticInfo &ActiveSemantic,
265258
llvm::StringSet<> &ActiveInputSemantics);
266-
bool determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *D,
267-
SemanticInfo &ActiveSemantic,
259+
bool determineActiveSemantic(FunctionDecl *FD, DeclaratorDecl *OutputDecl,
260+
DeclaratorDecl *D, SemanticInfo &ActiveSemantic,
268261
llvm::StringSet<> &ActiveInputSemantics);
269262

270263
void processExplicitBindingsOnDecl(VarDecl *D);

0 commit comments

Comments
 (0)