Skip to content

Commit 15a8e59

Browse files
committed
add support for shader visibility
- introduces the ParseEnum function that will parse any of the ENUM token definitions
1 parent 20bec7f commit 15a8e59

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
@@ -124,6 +124,12 @@ class RootSignatureParser {
124124
bool ParseUInt(uint32_t *X);
125125
bool ParseDescriptorRangeOffset(rs::DescriptorRangeOffset *X);
126126

127+
// Various flags/enum parsing helpers
128+
template <typename EnumType>
129+
bool ParseEnum(llvm::SmallDenseMap<TokenKind, EnumType> EnumMap,
130+
EnumType *Enum);
131+
bool ParseShaderVisibility(rs::ShaderVisibility *Enum);
132+
127133
// Increment the token iterator if we have not reached the end.
128134
// Return value denotes if we were already at the last token.
129135
bool ConsumeNextToken();

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,23 @@ bool RootSignatureParser::ParseDescriptorTable() {
278278
return false;
279279
}
280280

281+
bool SeenVisibility = false;
281282
// Iterate through all the defined clauses
282283
do {
284+
// Handle the visibility parameter
285+
if (!TryConsumeExpectedToken(TokenKind::kw_visibility)) {
286+
if (SeenVisibility) {
287+
Diags.Report(CurTok->TokLoc, diag::err_hlsl_rootsig_repeat_param)
288+
<< FormatTokenKinds(CurTok->Kind);
289+
return true;
290+
}
291+
SeenVisibility = true;
292+
if (ParseParam(&Table.Visibility))
293+
return true;
294+
continue;
295+
}
296+
297+
// Otherwise, we expect a clause
283298
if (ParseDescriptorTableClause())
284299
return true;
285300
Table.NumClauses++;
@@ -356,6 +371,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
356371
[&](DescriptorRangeOffset *X) {
357372
Error = ParseDescriptorRangeOffset(X);
358373
},
374+
[&](ShaderVisibility *Enum) {
375+
Error = ParseShaderVisibility(Enum);
376+
},
359377
}, Ref);
360378

361379
return Error;
@@ -436,6 +454,39 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
436454
return false;
437455
}
438456

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

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
308308
TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
309309
const llvm::StringLiteral Source = R"cc(
310310
DescriptorTable(
311+
visibility = SHADER_VISIBILITY_PIXEL,
311312
CBV(b0),
312313
SRV(t42, space = 3, offset = 32, numDescriptors = 4),
313314
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
@@ -382,11 +383,15 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
382383
Elem = Elements[4];
383384
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
384385
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)4);
386+
ASSERT_EQ(std::get<DescriptorTable>(Elem).Visibility,
387+
ShaderVisibility::Pixel);
385388

386389
Elem = Elements[5];
387390
// Test generated DescriptorTable start has correct default values
388391
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
389392
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)0);
393+
ASSERT_EQ(std::get<DescriptorTable>(Elem).Visibility, ShaderVisibility::All);
394+
390395
ASSERT_TRUE(Consumer->IsSatisfied());
391396
}
392397

@@ -467,4 +472,31 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedParamTest) {
467472
ASSERT_TRUE(Consumer->IsSatisfied());
468473
}
469474

475+
TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedVisibilityTest) {
476+
const llvm::StringLiteral Source = R"cc(
477+
DescriptorTable(
478+
visibility = SHADER_VISIBILITY_GEOMETRY,
479+
visibility = SHADER_VISIBILITY_HULL
480+
)
481+
)cc";
482+
483+
TrivialModuleLoader ModLoader;
484+
auto PP = CreatePP(Source, ModLoader);
485+
auto TokLoc = SourceLocation();
486+
487+
// Test correct diagnostic produced
488+
Consumer->SetExpected(diag::err_hlsl_rootsig_repeat_param);
489+
hlsl::RootSignatureLexer Lexer(Source, TokLoc, *PP);
490+
491+
SmallVector<hlsl::RootSignatureToken> Tokens;
492+
ASSERT_FALSE(Lexer.Lex(Tokens));
493+
494+
SmallVector<RootElement> Elements;
495+
hlsl::RootSignatureParser Parser(Elements, Tokens, Diags);
496+
497+
ASSERT_TRUE(Parser.Parse());
498+
499+
ASSERT_TRUE(Consumer->IsSatisfied());
500+
}
501+
470502
} // 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)