Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[HLSL] Define the HLSLRootSignature Attr #123985

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/AST/Attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "clang/Basic/SourceLocation.h"
#include "clang/Support/Compiler.h"
#include "llvm/Frontend/HLSL/HLSLResource.h"
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/VersionTuple.h"
Expand Down
20 changes: 20 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4643,6 +4643,26 @@ def Error : InheritableAttr {
let Documentation = [ErrorAttrDocs];
}

/// HLSL Root Signature Attribute
def HLSLRootSignature : Attr {
/// [RootSignature(Signature)]
let Spellings = [Microsoft<"RootSignature">];
let Args = [StringArgument<"Signature">];
let Subjects = SubjectList<[Function],
ErrorDiag, "'function'">;
let LangOpts = [HLSL];
let Documentation = [HLSLRootSignatureDocs];
let AdditionalMembers = [{
private:
ArrayRef<llvm::hlsl::rootsig::RootElement> RootElements;
public:
void setElements(ArrayRef<llvm::hlsl::rootsig::RootElement> Elements) {
RootElements = Elements;
}
auto getElements() const { return RootElements; }
}];
}

def HLSLNumThreads: InheritableAttr {
let Spellings = [Microsoft<"numthreads">];
let Args = [IntArgument<"X">, IntArgument<"Y">, IntArgument<"Z">];
Expand Down
11 changes: 11 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -7783,6 +7783,17 @@ and https://microsoft.github.io/hlsl-specs/proposals/0013-wave-size-range.html
}];
}

def HLSLRootSignatureDocs : 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 = [{
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class SemaHLSL : public SemaBase {
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);
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7149,6 +7149,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
break;

// HLSL attributes:
case ParsedAttr::AT_HLSLRootSignature:
S.HLSL().handleRootSignatureAttr(D, AL);
break;
case ParsedAttr::AT_HLSLNumThreads:
S.HLSL().handleNumThreadsAttr(D, AL);
break;
Expand Down
33 changes: 33 additions & 0 deletions clang/lib/Sema/SemaHLSL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/ParseHLSLRootSignature.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/ParsedAttr.h"
#include "clang/Sema/Sema.h"
Expand Down Expand Up @@ -647,6 +648,38 @@ 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;
}

StringRef Signature;
if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Signature))
return;

SourceLocation Loc = AL.getArgAsExpr(0)->getExprLoc();
// TODO(#126565): pass down below to lexer when fp is supported
// llvm::RoundingMode RM = SemaRef.CurFPFeatures.getRoundingMode();
hlsl::RootSignatureLexer Lexer(Signature, Loc, SemaRef.getPreprocessor());
SmallVector<llvm::hlsl::rootsig::RootElement> Elements;
hlsl::RootSignatureParser Parser(Elements, Lexer,
SemaRef.getPreprocessor().getDiagnostics());
if (Parser.Parse())
return;

unsigned N = Elements.size();
auto RootElements = MutableArrayRef<llvm::hlsl::rootsig::RootElement>(
::new (getASTContext()) llvm::hlsl::rootsig::RootElement[N], N);
for (unsigned I = 0; I < N; ++I)
RootElements[I] = Elements[I];

auto *Result = ::new (getASTContext())
HLSLRootSignatureAttr(getASTContext(), AL, Signature);
Result->setElements(ArrayRef<llvm::hlsl::rootsig::RootElement>(RootElements));
D->addAttr(Result);
}

void SemaHLSL::handleNumThreadsAttr(Decl *D, const ParsedAttr &AL) {
llvm::VersionTuple SMVersion =
getASTContext().getTargetInfo().getTriple().getOSVersion();
Expand Down
28 changes: 28 additions & 0 deletions clang/test/AST/HLSL/RootSignatures-AST.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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: HLSLRootSignatureAttr
// CHECK-SAME: "DescriptorTable(
// CHECK-SAME: CBV(b1),
// CHECK-SAME: SRV(t1, numDescriptors = 8,
// CHECK-SAME: flags = DESCRIPTORS_VOLATILE),
// CHECK-SAME: UAV(u1, numDescriptors = 0,
// CHECK-SAME: flags = DESCRIPTORS_VOLATILE)
// CHECK-SAME: ),
// CHECK-SAME: DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
[RootSignature(SampleRS)]
void main() {}
62 changes: 62 additions & 0 deletions clang/test/SemaHLSL/RootSignature-err.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify

// This file mirrors the diagnostics testing in ParseHLSLRootSignatureTest.cpp
// to verify that the correct diagnostics strings are output

// Attr test

[RootSignature()] // expected-error {{'RootSignature' attribute takes one argument}}
void bad_root_signature_0() {}

// Lexer related tests

#define InvalidToken \
"DescriptorTable( " \
" invalid " \
")"

[RootSignature(InvalidToken)] // expected-error {{expected one of the following token kinds: CBV, SRV, UAV, Sampler}}
void bad_root_signature_1() {}

#define InvalidEmptyNumber \
"DescriptorTable( " \
" CBV(t32, space = +) " \
")"

// expected-error@+1 {{expected the following token kind: integer literal}}
[RootSignature(InvalidEmptyNumber)]
void bad_root_signature_2() {}

#define InvalidOverflowNumber \
"DescriptorTable( " \
" CBV(t32, space = 98273498327498273487) " \
")"

// expected-error@+1 {{integer literal '98273498327498273487' is too large to be represented in a 32-bit integer type}}
[RootSignature(InvalidOverflowNumber)]
void bad_root_signature_3() {}

// Parser related tests

#define InvalidEOS \
"DescriptorTable( " \
" CBV("

[RootSignature(InvalidEOS)] // expected-error {{expected one of the following token kinds: b register, t register, u register, s register}}
void bad_root_signature_4() {}

#define InvalidTokenKind \
"DescriptorTable( " \
" SRV(s0, CBV())" \
")"

[RootSignature(InvalidTokenKind)] // expected-error {{expected one of the following token kinds: offset, numDescriptors, space, flags}}
void bad_root_signature_5() {}

#define InvalidRepeat \
"DescriptorTable( " \
" CBV(t0, space = 1, space = 2)" \
")"

[RootSignature(InvalidRepeat)] // expected-error {{specified the same parameter 'space' multiple times}}
void bad_root_signature_6() {}