[HLSL][RootSignature] Define and integrate rootsig clang attr and decl (#137690)
- Defines a new declaration node `HLSLRootSignature` in `DeclNodes.td` that will consist of a `TrailingObjects` of the in-memory construction of the root signature, namely an array of `hlsl::rootsig::RootElement`s - Defines a new clang attr `RootSignature` which simply holds an identifier to a corresponding root signature declaration as above - Integrate the `HLSLRootSignatureParser` to construct the decl node in `ParseMicrosoftAttributes` and then attach the parsed attr with an identifier to the entry point function declaration. - Defines the various required declaration methods - Add testing that the declaration and reference attr are created correctly, and some syntactical error tests. It was previously proposed that we could have the root elements reference be stored directly as an additional member of the attribute and to not have a separate root signature decl. In contrast, by defining them separately as this change proposes, we will allow a unique root signature to have its own declaration in the AST tree. This allows us to only construct a single root signature for all duplicate root signature attributes. Having it located directly as a declaration might also prove advantageous when we consider root signature libraries. Resolves https://github.com/llvm/llvm-project/issues/119011
This commit is contained in:
parent
fb9b43a0c5
commit
dd3d7cfe2e
@ -41,6 +41,7 @@
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/TrailingObjects.h"
|
||||
@ -5178,6 +5179,42 @@ public:
|
||||
friend class ASTDeclWriter;
|
||||
};
|
||||
|
||||
class HLSLRootSignatureDecl final
|
||||
: public NamedDecl,
|
||||
private llvm::TrailingObjects<HLSLRootSignatureDecl,
|
||||
llvm::hlsl::rootsig::RootElement> {
|
||||
friend TrailingObjects;
|
||||
|
||||
unsigned NumElems;
|
||||
|
||||
llvm::hlsl::rootsig::RootElement *getElems() {
|
||||
return getTrailingObjects<llvm::hlsl::rootsig::RootElement>();
|
||||
}
|
||||
|
||||
const llvm::hlsl::rootsig::RootElement *getElems() const {
|
||||
return getTrailingObjects<llvm::hlsl::rootsig::RootElement>();
|
||||
}
|
||||
|
||||
HLSLRootSignatureDecl(DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID,
|
||||
unsigned NumElems);
|
||||
|
||||
public:
|
||||
static HLSLRootSignatureDecl *
|
||||
Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID,
|
||||
ArrayRef<llvm::hlsl::rootsig::RootElement> RootElements);
|
||||
|
||||
static HLSLRootSignatureDecl *CreateDeserialized(ASTContext &C,
|
||||
GlobalDeclID ID);
|
||||
|
||||
ArrayRef<llvm::hlsl::rootsig::RootElement> getRootElements() const {
|
||||
return {getElems(), NumElems};
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||
static bool classofKind(Kind K) { return K == HLSLRootSignature; }
|
||||
};
|
||||
|
||||
/// Insertion operator for diagnostics. This allows sending NamedDecl's
|
||||
/// into a diagnostic with <<.
|
||||
inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &PD,
|
||||
|
@ -1599,6 +1599,8 @@ DEF_TRAVERSE_DECL(EmptyDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(HLSLBufferDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(HLSLRootSignatureDecl, {})
|
||||
|
||||
DEF_TRAVERSE_DECL(LifetimeExtendedTemporaryDecl, {
|
||||
TRY_TO(TraverseStmt(D->getTemporaryExpr()));
|
||||
})
|
||||
|
@ -408,6 +408,7 @@ public:
|
||||
void
|
||||
VisitLifetimeExtendedTemporaryDecl(const LifetimeExtendedTemporaryDecl *D);
|
||||
void VisitHLSLBufferDecl(const HLSLBufferDecl *D);
|
||||
void VisitHLSLRootSignatureDecl(const HLSLRootSignatureDecl *D);
|
||||
void VisitHLSLOutArgExpr(const HLSLOutArgExpr *E);
|
||||
void VisitOpenACCConstructStmt(const OpenACCConstructStmt *S);
|
||||
void VisitOpenACCLoopConstruct(const OpenACCLoopConstruct *S);
|
||||
|
@ -4735,6 +4735,17 @@ def Error : InheritableAttr {
|
||||
let Documentation = [ErrorAttrDocs];
|
||||
}
|
||||
|
||||
/// HLSL Root Signature Attribute
|
||||
def RootSignature : Attr {
|
||||
/// [RootSignature(Signature)]
|
||||
let Spellings = [Microsoft<"RootSignature">];
|
||||
let Args = [IdentifierArgument<"Signature">];
|
||||
let Subjects = SubjectList<[Function],
|
||||
ErrorDiag, "'function'">;
|
||||
let LangOpts = [HLSL];
|
||||
let Documentation = [RootSignatureDocs];
|
||||
}
|
||||
|
||||
def HLSLNumThreads: InheritableAttr {
|
||||
let Spellings = [Microsoft<"numthreads">];
|
||||
let Args = [IntArgument<"X">, IntArgument<"Y">, IntArgument<"Z">];
|
||||
|
@ -8195,6 +8195,17 @@ and https://microsoft.github.io/hlsl-specs/proposals/0013-wave-size-range.html
|
||||
}];
|
||||
}
|
||||
|
||||
def RootSignatureDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
The ``RootSignature`` attribute applies to HLSL entry functions to define what
|
||||
types of resources are bound to the graphics pipeline.
|
||||
|
||||
For details about the use and specification of Root Signatures please see here:
|
||||
https://learn.microsoft.com/en-us/windows/win32/direct3d12/root-signatures
|
||||
}];
|
||||
}
|
||||
|
||||
def NumThreadsDocs : Documentation {
|
||||
let Category = DocCatFunction;
|
||||
let Content = [{
|
||||
|
@ -111,5 +111,6 @@ def Empty : DeclNode<Decl>;
|
||||
def RequiresExprBody : DeclNode<Decl>, DeclContext;
|
||||
def LifetimeExtendedTemporary : DeclNode<Decl>;
|
||||
def HLSLBuffer : DeclNode<Named, "HLSLBuffer">, DeclContext;
|
||||
def HLSLRootSignature : DeclNode<Named, "HLSLRootSignature">;
|
||||
def OpenACCDeclare : DeclNode<Decl, "#pragma acc declare">;
|
||||
def OpenACCRoutine : DeclNode<Decl, "#pragma acc routine">;
|
||||
|
@ -3093,6 +3093,7 @@ private:
|
||||
return AttrsParsed;
|
||||
}
|
||||
void ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs);
|
||||
void ParseMicrosoftRootSignatureAttributeArgs(ParsedAttributes &Attrs);
|
||||
void ParseMicrosoftAttributes(ParsedAttributes &Attrs);
|
||||
bool MaybeParseMicrosoftDeclSpecs(ParsedAttributes &Attrs) {
|
||||
if (getLangOpts().DeclSpecKeyword && Tok.is(tok::kw___declspec)) {
|
||||
|
@ -119,6 +119,7 @@ public:
|
||||
bool IsCompAssign);
|
||||
void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc);
|
||||
|
||||
void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
|
||||
void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
|
||||
void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
|
||||
void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
|
||||
|
@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS
|
||||
BinaryFormat
|
||||
Core
|
||||
FrontendOpenMP
|
||||
FrontendHLSL
|
||||
Support
|
||||
TargetParser
|
||||
)
|
||||
|
@ -5847,6 +5847,38 @@ bool HLSLBufferDecl::buffer_decls_empty() {
|
||||
return DefaultBufferDecls.empty() && decls_empty();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// HLSLRootSignatureDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
HLSLRootSignatureDecl::HLSLRootSignatureDecl(DeclContext *DC,
|
||||
SourceLocation Loc,
|
||||
IdentifierInfo *ID,
|
||||
unsigned NumElems)
|
||||
: NamedDecl(Decl::Kind::HLSLRootSignature, DC, Loc, DeclarationName(ID)),
|
||||
NumElems(NumElems) {}
|
||||
|
||||
HLSLRootSignatureDecl *HLSLRootSignatureDecl::Create(
|
||||
ASTContext &C, DeclContext *DC, SourceLocation Loc, IdentifierInfo *ID,
|
||||
ArrayRef<llvm::hlsl::rootsig::RootElement> RootElements) {
|
||||
HLSLRootSignatureDecl *RSDecl =
|
||||
new (C, DC,
|
||||
additionalSizeToAlloc<llvm::hlsl::rootsig::RootElement>(
|
||||
RootElements.size()))
|
||||
HLSLRootSignatureDecl(DC, Loc, ID, RootElements.size());
|
||||
auto *StoredElems = RSDecl->getElems();
|
||||
std::uninitialized_copy(RootElements.begin(), RootElements.end(),
|
||||
StoredElems);
|
||||
return RSDecl;
|
||||
}
|
||||
|
||||
HLSLRootSignatureDecl *
|
||||
HLSLRootSignatureDecl::CreateDeserialized(ASTContext &C, GlobalDeclID ID) {
|
||||
HLSLRootSignatureDecl *Result = new (C, ID)
|
||||
HLSLRootSignatureDecl(nullptr, SourceLocation(), nullptr, /*NumElems=*/0);
|
||||
return Result;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ImportDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -886,6 +886,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||
case ObjCProperty:
|
||||
case MSProperty:
|
||||
case HLSLBuffer:
|
||||
case HLSLRootSignature:
|
||||
return IDNS_Ordinary;
|
||||
case Label:
|
||||
return IDNS_Label;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TypeTraits.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
@ -3037,6 +3038,12 @@ void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
|
||||
dumpName(D);
|
||||
}
|
||||
|
||||
void TextNodeDumper::VisitHLSLRootSignatureDecl(
|
||||
const HLSLRootSignatureDecl *D) {
|
||||
dumpName(D);
|
||||
llvm::hlsl::rootsig::dumpRootElements(OS, D->getRootElements());
|
||||
}
|
||||
|
||||
void TextNodeDumper::VisitHLSLOutArgExpr(const HLSLOutArgExpr *E) {
|
||||
OS << (E->isInOut() ? " inout" : " out");
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ void CodeGenFunction::EmitDecl(const Decl &D, bool EvaluateConditionDecl) {
|
||||
case Decl::Binding:
|
||||
case Decl::UnresolvedUsingIfExists:
|
||||
case Decl::HLSLBuffer:
|
||||
case Decl::HLSLRootSignature:
|
||||
llvm_unreachable("Declaration should not be in declstmts!");
|
||||
case Decl::Record: // struct/union/class X;
|
||||
case Decl::CXXRecord: // struct/union/class X; [C++]
|
||||
|
@ -21,10 +21,12 @@
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
#include "clang/Lex/LiteralSupport.h"
|
||||
#include "clang/Parse/ParseHLSLRootSignature.h"
|
||||
#include "clang/Parse/Parser.h"
|
||||
#include "clang/Parse/RAIIObjectsForParser.h"
|
||||
#include "clang/Sema/DeclSpec.h"
|
||||
#include "clang/Sema/EnterExpressionEvaluationContext.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/ParsedTemplate.h"
|
||||
#include "clang/Sema/Scope.h"
|
||||
#include "clang/Sema/SemaCodeCompletion.h"
|
||||
@ -5311,6 +5313,90 @@ void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) {
|
||||
}
|
||||
}
|
||||
|
||||
void Parser::ParseMicrosoftRootSignatureAttributeArgs(ParsedAttributes &Attrs) {
|
||||
assert(Tok.is(tok::identifier) &&
|
||||
"Expected an identifier to denote which MS attribute to consider");
|
||||
IdentifierInfo *RootSignatureIdent = Tok.getIdentifierInfo();
|
||||
assert(RootSignatureIdent->getName() == "RootSignature" &&
|
||||
"Expected RootSignature identifier for root signature attribute");
|
||||
|
||||
SourceLocation RootSignatureLoc = Tok.getLocation();
|
||||
ConsumeToken();
|
||||
|
||||
// Ignore the left paren location for now.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren);
|
||||
if (T.consumeOpen()) {
|
||||
Diag(Tok, diag::err_expected) << tok::l_paren;
|
||||
return;
|
||||
}
|
||||
|
||||
auto ProcessStringLiteral = [this]() -> std::optional<StringLiteral *> {
|
||||
if (!isTokenStringLiteral())
|
||||
return std::nullopt;
|
||||
|
||||
ExprResult StringResult = ParseUnevaluatedStringLiteralExpression();
|
||||
if (StringResult.isInvalid())
|
||||
return std::nullopt;
|
||||
|
||||
if (auto Lit = dyn_cast<StringLiteral>(StringResult.get()))
|
||||
return Lit;
|
||||
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
auto StrLiteral = ProcessStringLiteral();
|
||||
if (!StrLiteral.has_value()) {
|
||||
Diag(Tok, diag::err_expected_string_literal)
|
||||
<< /*in attributes...*/ 4 << RootSignatureIdent->getName();
|
||||
SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
|
||||
T.consumeClose();
|
||||
return;
|
||||
}
|
||||
|
||||
// Construct our identifier
|
||||
StringRef Signature = StrLiteral.value()->getString();
|
||||
auto Hash = llvm::hash_value(Signature);
|
||||
std::string IdStr = "__hlsl_rootsig_decl_" + std::to_string(Hash);
|
||||
IdentifierInfo *DeclIdent = &(Actions.getASTContext().Idents.get(IdStr));
|
||||
|
||||
LookupResult R(Actions, DeclIdent, SourceLocation(),
|
||||
Sema::LookupOrdinaryName);
|
||||
// Check if we have already found a decl of the same name, if we haven't
|
||||
// then parse the root signature string and construct the in-memory elements
|
||||
if (!Actions.LookupQualifiedName(R, Actions.CurContext)) {
|
||||
SourceLocation SignatureLoc =
|
||||
StrLiteral.value()->getExprLoc().getLocWithOffset(
|
||||
1); // offset 1 for '"'
|
||||
// Invoke the root signature parser to construct the in-memory constructs
|
||||
hlsl::RootSignatureLexer Lexer(Signature, SignatureLoc);
|
||||
SmallVector<llvm::hlsl::rootsig::RootElement> RootElements;
|
||||
hlsl::RootSignatureParser Parser(RootElements, Lexer, PP);
|
||||
if (Parser.parse()) {
|
||||
T.consumeClose();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the Root Signature
|
||||
auto *SignatureDecl = HLSLRootSignatureDecl::Create(
|
||||
Actions.getASTContext(), /*DeclContext=*/Actions.CurContext,
|
||||
RootSignatureLoc, DeclIdent, RootElements);
|
||||
SignatureDecl->setImplicit();
|
||||
Actions.PushOnScopeChains(SignatureDecl, getCurScope());
|
||||
}
|
||||
|
||||
// Create the arg for the ParsedAttr
|
||||
IdentifierLoc *ILoc = ::new (Actions.getASTContext())
|
||||
IdentifierLoc(RootSignatureLoc, DeclIdent);
|
||||
|
||||
ArgsVector Args = {ILoc};
|
||||
|
||||
if (!T.consumeClose())
|
||||
Attrs.addNew(RootSignatureIdent,
|
||||
SourceRange(RootSignatureLoc, T.getCloseLocation()), nullptr,
|
||||
SourceLocation(), Args.data(), Args.size(),
|
||||
ParsedAttr::Form::Microsoft());
|
||||
}
|
||||
|
||||
/// ParseMicrosoftAttributes - Parse Microsoft attributes [Attr]
|
||||
///
|
||||
/// [MS] ms-attribute:
|
||||
@ -5345,6 +5431,8 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs) {
|
||||
break;
|
||||
if (Tok.getIdentifierInfo()->getName() == "uuid")
|
||||
ParseMicrosoftUuidAttributeArgs(Attrs);
|
||||
else if (Tok.getIdentifierInfo()->getName() == "RootSignature")
|
||||
ParseMicrosoftRootSignatureAttributeArgs(Attrs);
|
||||
else {
|
||||
IdentifierInfo *II = Tok.getIdentifierInfo();
|
||||
SourceLocation NameLoc = Tok.getLocation();
|
||||
|
@ -7481,6 +7481,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
|
||||
break;
|
||||
|
||||
// HLSL attributes:
|
||||
case ParsedAttr::AT_RootSignature:
|
||||
S.HLSL().handleRootSignatureAttr(D, AL);
|
||||
break;
|
||||
case ParsedAttr::AT_HLSLNumThreads:
|
||||
S.HLSL().handleNumThreadsAttr(D, AL);
|
||||
break;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Sema/Initialization.h"
|
||||
#include "clang/Sema/Lookup.h"
|
||||
#include "clang/Sema/ParsedAttr.h"
|
||||
#include "clang/Sema/Sema.h"
|
||||
#include "clang/Sema/Template.h"
|
||||
@ -950,6 +951,33 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS,
|
||||
<< NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
|
||||
}
|
||||
|
||||
void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
|
||||
if (AL.getNumArgs() != 1) {
|
||||
Diag(AL.getLoc(), diag::err_attribute_wrong_number_arguments) << AL << 1;
|
||||
return;
|
||||
}
|
||||
|
||||
IdentifierInfo *Ident = AL.getArgAsIdent(0)->getIdentifierInfo();
|
||||
if (auto *RS = D->getAttr<RootSignatureAttr>()) {
|
||||
if (RS->getSignature() != Ident) {
|
||||
Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << RS;
|
||||
return;
|
||||
}
|
||||
|
||||
Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << RS;
|
||||
return;
|
||||
}
|
||||
|
||||
LookupResult R(SemaRef, Ident, SourceLocation(), Sema::LookupOrdinaryName);
|
||||
if (SemaRef.LookupQualifiedName(R, D->getDeclContext()))
|
||||
if (auto *SignatureDecl =
|
||||
dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) {
|
||||
// Perform validation of constructs here
|
||||
D->addAttr(::new (getASTContext())
|
||||
RootSignatureAttr(getASTContext(), AL, Ident));
|
||||
}
|
||||
}
|
||||
|
||||
void SemaHLSL::handleNumThreadsAttr(Decl *D, const ParsedAttr &AL) {
|
||||
llvm::VersionTuple SMVersion =
|
||||
getASTContext().getTargetInfo().getTriple().getOSVersion();
|
||||
|
@ -999,6 +999,11 @@ Decl *TemplateDeclInstantiator::VisitHLSLBufferDecl(HLSLBufferDecl *Decl) {
|
||||
llvm_unreachable("HLSL buffer declarations cannot be instantiated");
|
||||
}
|
||||
|
||||
Decl *TemplateDeclInstantiator::VisitHLSLRootSignatureDecl(
|
||||
HLSLRootSignatureDecl *Decl) {
|
||||
llvm_unreachable("HLSL root signature declarations cannot be instantiated");
|
||||
}
|
||||
|
||||
Decl *
|
||||
TemplateDeclInstantiator::VisitPragmaCommentDecl(PragmaCommentDecl *D) {
|
||||
llvm_unreachable("pragma comment cannot be instantiated");
|
||||
|
@ -458,6 +458,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
||||
case Decl::RequiresExprBody:
|
||||
case Decl::UnresolvedUsingIfExists:
|
||||
case Decl::HLSLBuffer:
|
||||
case Decl::HLSLRootSignature:
|
||||
case Decl::OpenACCDeclare:
|
||||
case Decl::OpenACCRoutine:
|
||||
return false;
|
||||
|
75
clang/test/AST/HLSL/RootSignatures-AST.hlsl
Normal file
75
clang/test/AST/HLSL/RootSignatures-AST.hlsl
Normal file
@ -0,0 +1,75 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \
|
||||
// RUN: -disable-llvm-passes -o - %s | FileCheck %s
|
||||
|
||||
// This test ensures that the sample root signature is parsed without error and
|
||||
// the Attr AST Node is created succesfully. If an invalid root signature was
|
||||
// passed in then we would exit out of Sema before the Attr is created.
|
||||
|
||||
#define SampleRS \
|
||||
"DescriptorTable( " \
|
||||
" CBV(b1), " \
|
||||
" SRV(t1, numDescriptors = 8, " \
|
||||
" flags = DESCRIPTORS_VOLATILE), " \
|
||||
" UAV(u1, numDescriptors = 0, " \
|
||||
" flags = DESCRIPTORS_VOLATILE) " \
|
||||
"), " \
|
||||
"DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
|
||||
|
||||
// CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[SAMPLE_RS_DECL:__hlsl_rootsig_decl_\d*]]
|
||||
// CHECK-SAME: RootElements{
|
||||
// CHECK-SAME: CBV(b1, numDescriptors = 1, space = 0,
|
||||
// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DataStaticWhileSetAtExecute),
|
||||
// CHECK-SAME: SRV(t1, numDescriptors = 8, space = 0,
|
||||
// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile),
|
||||
// CHECK-SAME: UAV(u1, numDescriptors = 0, space = 0,
|
||||
// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = DescriptorsVolatile),
|
||||
// CHECK-SAME: DescriptorTable(numClauses = 3, visibility = All),
|
||||
// CHECK-SAME: Sampler(s0, numDescriptors = 4, space = 1,
|
||||
// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = None),
|
||||
// CHECK-SAME: DescriptorTable(numClauses = 1, visibility = All)
|
||||
// CHECK-SAME: }
|
||||
|
||||
// CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[SAMPLE_RS_DECL]]
|
||||
[RootSignature(SampleRS)]
|
||||
void rs_main() {}
|
||||
|
||||
// Ensure that if multiple root signatures are specified at different entry
|
||||
// points that we point to the correct root signature
|
||||
|
||||
// CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[SAMPLE_RS_DECL]]
|
||||
[RootSignature(SampleRS)]
|
||||
void same_rs_main() {}
|
||||
|
||||
// Define the same root signature to ensure that the entry point will still
|
||||
// link to the same root signature declaration
|
||||
|
||||
#define SampleSameRS \
|
||||
"DescriptorTable( " \
|
||||
" CBV(b1), " \
|
||||
" SRV(t1, numDescriptors = 8, " \
|
||||
" flags = DESCRIPTORS_VOLATILE), " \
|
||||
" UAV(u1, numDescriptors = 0, " \
|
||||
" flags = DESCRIPTORS_VOLATILE) " \
|
||||
"), " \
|
||||
"DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
|
||||
|
||||
// CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[SAMPLE_RS_DECL]]
|
||||
[RootSignature(SampleSameRS)]
|
||||
void same_rs_string_main() {}
|
||||
|
||||
#define SampleDifferentRS \
|
||||
"DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
|
||||
|
||||
// Ensure that when we define a different type root signature that it creates
|
||||
// a seperate decl and identifier to reference
|
||||
|
||||
// CHECK: -HLSLRootSignatureDecl 0x{{.*}} {{.*}} implicit [[DIFF_RS_DECL:__hlsl_rootsig_decl_\d*]]
|
||||
// CHECK-SAME: RootElements{
|
||||
// CHECK-SAME: Sampler(s0, numDescriptors = 4, space = 1,
|
||||
// CHECK-SAME: offset = DescriptorTableOffsetAppend, flags = None),
|
||||
// CHECK-SAME: DescriptorTable(numClauses = 1, visibility = All)
|
||||
// CHECK-SAME: }
|
||||
|
||||
// CHECK: -RootSignatureAttr 0x{{.*}} {{.*}} [[DIFF_RS_DECL]]
|
||||
[RootSignature(SampleDifferentRS)]
|
||||
void different_rs_string_main() {}
|
20
clang/test/SemaHLSL/RootSignature-err.hlsl
Normal file
20
clang/test/SemaHLSL/RootSignature-err.hlsl
Normal file
@ -0,0 +1,20 @@
|
||||
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify
|
||||
|
||||
// Attr test
|
||||
|
||||
[RootSignature()] // expected-error {{expected string literal as argument of 'RootSignature' attribute}}
|
||||
void bad_root_signature_0() {}
|
||||
|
||||
// expected-error@+2 {{expected ')'}}
|
||||
// expected-note@+1 {{to match this '('}}
|
||||
[RootSignature("", "")]
|
||||
void bad_root_signature_1() {}
|
||||
|
||||
[RootSignature(""), RootSignature("DescriptorTable()")] // expected-error {{attribute 'RootSignature' cannot appear more than once on a declaration}}
|
||||
void bad_root_signature_2() {}
|
||||
|
||||
[RootSignature(""), RootSignature("")] // expected-warning {{attribute 'RootSignature' is already applied}}
|
||||
void bad_root_signature_3() {}
|
||||
|
||||
[RootSignature("DescriptorTable(), invalid")] // expected-error {{expected end of stream to denote end of parameters, or, another valid parameter of RootSignature}}
|
||||
void bad_root_signature_4() {}
|
@ -7229,6 +7229,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
||||
case Decl::MSProperty:
|
||||
case Decl::MSGuid:
|
||||
case Decl::HLSLBuffer:
|
||||
case Decl::HLSLRootSignature:
|
||||
case Decl::UnnamedGlobalConstant:
|
||||
case Decl::TemplateParamObject:
|
||||
case Decl::IndirectField:
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
|
||||
#define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/DXILABI.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <variant>
|
||||
@ -122,6 +123,8 @@ struct DescriptorTableClause {
|
||||
using RootElement = std::variant<RootFlags, RootConstants, DescriptorTable,
|
||||
DescriptorTableClause>;
|
||||
|
||||
void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements);
|
||||
|
||||
} // namespace rootsig
|
||||
} // namespace hlsl
|
||||
} // namespace llvm
|
||||
|
@ -144,6 +144,22 @@ void DescriptorTableClause::dump(raw_ostream &OS) const {
|
||||
OS << ", flags = " << Flags << ")";
|
||||
}
|
||||
|
||||
void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
|
||||
OS << "RootElements{";
|
||||
bool First = true;
|
||||
for (const RootElement &Element : Elements) {
|
||||
if (!First)
|
||||
OS << ",";
|
||||
OS << " ";
|
||||
First = false;
|
||||
if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
|
||||
Clause->dump(OS);
|
||||
if (const auto &Table = std::get_if<DescriptorTable>(&Element))
|
||||
Table->dump(OS);
|
||||
}
|
||||
OS << "}";
|
||||
}
|
||||
|
||||
} // namespace rootsig
|
||||
} // namespace hlsl
|
||||
} // namespace llvm
|
||||
|
Loading…
x
Reference in New Issue
Block a user