Skip to content

Commit 4ed3abf

Browse files
committed
add support for shader visibility
- introduces the ParseEnum function that will parse any of the ENUM token definitions
1 parent e8e074a commit 4ed3abf

File tree

4 files changed

+103
-1
lines changed

4 files changed

+103
-1
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ class RootSignatureParser {
137137
bool ParseUInt(uint32_t *X);
138138
bool ParseDescriptorRangeOffset(rs::DescriptorRangeOffset *X);
139139

140+
// Various flags/enum parsing helpers
141+
template <typename EnumType>
142+
bool ParseEnum(llvm::SmallDenseMap<TokenKind, EnumType> EnumMap,
143+
EnumType *Enum);
144+
bool ParseShaderVisibility(rs::ShaderVisibility *Enum);
145+
140146
// Increment the token iterator if we have not reached the end.
141147
// Return value denotes if we were already at the last token.
142148
bool ConsumeNextToken();

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,23 @@ bool RootSignatureParser::ParseDescriptorTable() {
271271
return false;
272272
}
273273

274+
bool SeenVisibility = false;
274275
// Iterate through all the defined clauses
275276
do {
277+
// Handle the visibility parameter
278+
if (!TryConsumeExpectedToken(TokenKind::kw_visibility)) {
279+
if (SeenVisibility) {
280+
Diags.Report(CurTok->TokLoc, diag::err_hlsl_rootsig_repeat_param)
281+
<< FormatTokenKinds(CurTok->Kind);
282+
return true;
283+
}
284+
SeenVisibility = true;
285+
if (ParseParam(&Table.Visibility))
286+
return true;
287+
continue;
288+
}
289+
290+
// Otherwise, we expect a clause
276291
if (ParseDescriptorTableClause())
277292
return true;
278293
Table.NumClauses++;
@@ -349,6 +364,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
349364
[&](DescriptorRangeOffset *X) {
350365
Error = ParseDescriptorRangeOffset(X);
351366
},
367+
[&](ShaderVisibility *Enum) {
368+
Error = ParseShaderVisibility(Enum);
369+
},
352370
}, Ref);
353371

354372
return Error;
@@ -429,6 +447,39 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
429447
return false;
430448
}
431449

450+
template <typename EnumType>
451+
bool RootSignatureParser::ParseEnum(
452+
llvm::SmallDenseMap<TokenKind, EnumType> EnumMap, EnumType *Enum) {
453+
SmallVector<TokenKind> EnumToks;
454+
for (auto EnumPair : EnumMap)
455+
EnumToks.push_back(EnumPair.first);
456+
457+
// If invoked we expect to have an enum
458+
if (ConsumeExpectedToken(EnumToks))
459+
return true;
460+
461+
// Effectively a switch statement on the token kinds
462+
for (auto EnumPair : EnumMap)
463+
if (CurTok->Kind == EnumPair.first) {
464+
*Enum = EnumPair.second;
465+
return false;
466+
}
467+
468+
llvm_unreachable("Switch for an expected token was not provided");
469+
return true;
470+
}
471+
472+
bool RootSignatureParser::ParseShaderVisibility(ShaderVisibility *Enum) {
473+
// Define the possible flag kinds
474+
llvm::SmallDenseMap<TokenKind, ShaderVisibility> EnumMap = {
475+
#define SHADER_VISIBILITY_ENUM(NAME, LIT) \
476+
{TokenKind::en_##NAME, ShaderVisibility::NAME},
477+
#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
478+
};
479+
480+
return ParseEnum(EnumMap, Enum);
481+
}
482+
432483
RootSignatureToken RootSignatureParser::PeekNextToken() {
433484
// Create an invalid token
434485
RootSignatureToken Token = RootSignatureToken(SourceLocation());

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
335335
TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
336336
const llvm::StringLiteral Source = R"cc(
337337
DescriptorTable(
338+
visibility = SHADER_VISIBILITY_PIXEL,
338339
CBV(b0),
339340
SRV(t42, space = 3, offset = 32, numDescriptors = 4),
340341
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
@@ -409,11 +410,15 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
409410
Elem = Elements[4];
410411
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
411412
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)4);
413+
ASSERT_EQ(std::get<DescriptorTable>(Elem).Visibility,
414+
ShaderVisibility::Pixel);
412415

413416
Elem = Elements[5];
414417
// Test generated DescriptorTable start has correct default values
415418
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
416419
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)0);
420+
ASSERT_EQ(std::get<DescriptorTable>(Elem).Visibility, ShaderVisibility::All);
421+
417422
ASSERT_TRUE(Consumer->IsSatisfied());
418423
}
419424

@@ -494,4 +499,31 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedParamTest) {
494499
ASSERT_TRUE(Consumer->IsSatisfied());
495500
}
496501

502+
TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedVisibilityTest) {
503+
const llvm::StringLiteral Source = R"cc(
504+
DescriptorTable(
505+
visibility = SHADER_VISIBILITY_GEOMETRY,
506+
visibility = SHADER_VISIBILITY_HULL
507+
)
508+
)cc";
509+
510+
TrivialModuleLoader ModLoader;
511+
auto PP = CreatePP(Source, ModLoader);
512+
auto TokLoc = SourceLocation();
513+
514+
// Test correct diagnostic produced
515+
Consumer->SetExpected(diag::err_hlsl_rootsig_repeat_param);
516+
hlsl::RootSignatureLexer Lexer(Source, TokLoc, *PP);
517+
518+
SmallVector<hlsl::RootSignatureToken> Tokens;
519+
ASSERT_FALSE(Lexer.Lex(Tokens));
520+
521+
SmallVector<RootElement> Elements;
522+
hlsl::RootSignatureParser Parser(Elements, Tokens, Diags);
523+
524+
ASSERT_TRUE(Parser.Parse());
525+
526+
ASSERT_TRUE(Consumer->IsSatisfied());
527+
}
528+
497529
} // anonymous namespace

llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ namespace root_signature {
2525

2626
enum class DescriptorRangeOffset : uint32_t;
2727

28+
enum class ShaderVisibility {
29+
All = 0,
30+
Vertex = 1,
31+
Hull = 2,
32+
Domain = 3,
33+
Geometry = 4,
34+
Pixel = 5,
35+
Amplification = 6,
36+
Mesh = 7,
37+
};
38+
2839
// Definitions of the in-memory data layout structures
2940

3041
// Models the different registers: bReg | tReg | uReg | sReg
@@ -36,6 +47,7 @@ struct Register {
3647

3748
// Models the end of a descriptor table and stores its visibility
3849
struct DescriptorTable {
50+
ShaderVisibility Visibility = ShaderVisibility::All;
3951
uint32_t NumClauses = 0; // The number of clauses in the table
4052
};
4153

@@ -56,7 +68,8 @@ using RootElement = std::variant<DescriptorTable, DescriptorTableClause>;
5668

5769
// Models a reference to all assignment parameter types that any RootElement
5870
// may have. Things of the form: Keyword = Param
59-
using ParamType = std::variant<uint32_t *, DescriptorRangeOffset *>;
71+
using ParamType = std::variant<uint32_t *, DescriptorRangeOffset *,
72+
ShaderVisibility *>;
6073
} // namespace root_signature
6174
} // namespace hlsl
6275
} // namespace llvm

0 commit comments

Comments
 (0)