Skip to content

Commit 14bd063

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

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
@@ -299,8 +299,23 @@ bool RootSignatureParser::ParseDescriptorTable() {
299299
return false;
300300
}
301301

302+
bool SeenVisibility = false;
302303
// Iterate through all the defined clauses
303304
do {
305+
// Handle the visibility parameter
306+
if (!TryConsumeExpectedToken(TokenKind::kw_visibility)) {
307+
if (SeenVisibility) {
308+
Diags.Report(CurTok->TokLoc, diag::err_hlsl_rootsig_repeat_param)
309+
<< FormatTokenKinds(CurTok->Kind);
310+
return true;
311+
}
312+
SeenVisibility = true;
313+
if (ParseParam(&Table.Visibility))
314+
return true;
315+
continue;
316+
}
317+
318+
// Otherwise, we expect a clause
304319
if (ParseDescriptorTableClause())
305320
return true;
306321
Table.NumClauses++;
@@ -377,6 +392,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
377392
[&](DescriptorRangeOffset *X) {
378393
Error = ParseDescriptorRangeOffset(X);
379394
},
395+
[&](ShaderVisibility *Enum) {
396+
Error = ParseShaderVisibility(Enum);
397+
},
380398
}, Ref);
381399

382400
return Error;
@@ -457,6 +475,39 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
457475
return false;
458476
}
459477

478+
template <typename EnumType>
479+
bool RootSignatureParser::ParseEnum(
480+
llvm::SmallDenseMap<TokenKind, EnumType> EnumMap, EnumType *Enum) {
481+
SmallVector<TokenKind> EnumToks;
482+
for (auto EnumPair : EnumMap)
483+
EnumToks.push_back(EnumPair.first);
484+
485+
// If invoked we expect to have an enum
486+
if (ConsumeExpectedToken(EnumToks))
487+
return true;
488+
489+
// Effectively a switch statement on the token kinds
490+
for (auto EnumPair : EnumMap)
491+
if (CurTok->Kind == EnumPair.first) {
492+
*Enum = EnumPair.second;
493+
return false;
494+
}
495+
496+
llvm_unreachable("Switch for an expected token was not provided");
497+
return true;
498+
}
499+
500+
bool RootSignatureParser::ParseShaderVisibility(ShaderVisibility *Enum) {
501+
// Define the possible flag kinds
502+
llvm::SmallDenseMap<TokenKind, ShaderVisibility> EnumMap = {
503+
#define SHADER_VISIBILITY_ENUM(NAME, LIT) \
504+
{TokenKind::en_##NAME, ShaderVisibility::NAME},
505+
#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
506+
};
507+
508+
return ParseEnum(EnumMap, Enum);
509+
}
510+
460511
RootSignatureToken RootSignatureParser::PeekNextToken() {
461512
// Create an invalid token
462513
RootSignatureToken Token = RootSignatureToken(SourceLocation());

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
386386
TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
387387
const llvm::StringLiteral Source = R"cc(
388388
DescriptorTable(
389+
visibility = SHADER_VISIBILITY_PIXEL,
389390
CBV(b0),
390391
SRV(t42, space = 3, offset = 32, numDescriptors = 4),
391392
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
@@ -460,11 +461,15 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
460461
Elem = Elements[4];
461462
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
462463
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)4);
464+
ASSERT_EQ(std::get<DescriptorTable>(Elem).Visibility,
465+
ShaderVisibility::Pixel);
463466

464467
Elem = Elements[5];
465468
// Test generated DescriptorTable start has correct default values
466469
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
467470
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)0);
471+
ASSERT_EQ(std::get<DescriptorTable>(Elem).Visibility, ShaderVisibility::All);
472+
468473
ASSERT_TRUE(Consumer->IsSatisfied());
469474
}
470475

@@ -545,4 +550,31 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedParamTest) {
545550
ASSERT_TRUE(Consumer->IsSatisfied());
546551
}
547552

553+
TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedVisibilityTest) {
554+
const llvm::StringLiteral Source = R"cc(
555+
DescriptorTable(
556+
visibility = SHADER_VISIBILITY_GEOMETRY,
557+
visibility = SHADER_VISIBILITY_HULL
558+
)
559+
)cc";
560+
561+
TrivialModuleLoader ModLoader;
562+
auto PP = CreatePP(Source, ModLoader);
563+
auto TokLoc = SourceLocation();
564+
565+
// Test correct diagnostic produced
566+
Consumer->SetExpected(diag::err_hlsl_rootsig_repeat_param);
567+
hlsl::RootSignatureLexer Lexer(Source, TokLoc, *PP);
568+
569+
SmallVector<hlsl::RootSignatureToken> Tokens;
570+
ASSERT_FALSE(Lexer.Lex(Tokens));
571+
572+
SmallVector<RootElement> Elements;
573+
hlsl::RootSignatureParser Parser(Elements, Tokens, Diags);
574+
575+
ASSERT_TRUE(Parser.Parse());
576+
577+
ASSERT_TRUE(Consumer->IsSatisfied());
578+
}
579+
548580
} // 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)