Skip to content

Commit 847974b

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

File tree

4 files changed

+99
-1
lines changed

4 files changed

+99
-1
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ class RootSignatureParser {
135135
bool
136136
ParseDescriptorRangeOffset(llvm::hlsl::rootsig::DescriptorRangeOffset *X);
137137

138+
// Various flags/enum parsing helpers
139+
template <bool AllowZero = false, typename EnumType>
140+
bool ParseEnum(llvm::SmallDenseMap<TokenKind, EnumType> &EnumMap,
141+
EnumType *Enum);
142+
bool ParseShaderVisibility(llvm::hlsl::rootsig::ShaderVisibility *Enum);
143+
138144
/// Invoke the lexer to consume a token and update CurToken with the result
139145
///
140146
/// Return value denotes if we were already at the last token.

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,23 @@ bool RootSignatureParser::ParseDescriptorTable() {
274274
return false;
275275
}
276276

277+
bool SeenVisibility = false;
277278
// Iterate through all the defined clauses
278279
do {
280+
// Handle the visibility parameter
281+
if (!TryConsumeExpectedToken(TokenKind::kw_visibility)) {
282+
if (SeenVisibility) {
283+
Diags.Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
284+
<< FormatTokenKinds(CurToken.Kind);
285+
return true;
286+
}
287+
SeenVisibility = true;
288+
if (ParseParam(&Table.Visibility))
289+
return true;
290+
continue;
291+
}
292+
293+
// Otherwise, we expect a clause
279294
if (ParseDescriptorTableClause())
280295
return true;
281296
Table.NumClauses++;
@@ -351,6 +366,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
351366
[&](DescriptorRangeOffset *X) {
352367
Error = ParseDescriptorRangeOffset(X);
353368
},
369+
[&](ShaderVisibility *Enum) {
370+
Error = ParseShaderVisibility(Enum);
371+
},
354372
}, Ref);
355373

356374
return Error;
@@ -432,6 +450,39 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
432450
return false;
433451
}
434452

453+
template <typename EnumType>
454+
bool RootSignatureParser::ParseEnum(
455+
llvm::SmallDenseMap<TokenKind, EnumType> &EnumMap, EnumType *Enum) {
456+
SmallVector<TokenKind> EnumToks;
457+
for (auto EnumPair : EnumMap)
458+
EnumToks.push_back(EnumPair.first);
459+
460+
// If invoked we expect to have an enum
461+
if (ConsumeExpectedToken(EnumToks))
462+
return true;
463+
464+
// Effectively a switch statement on the token kinds
465+
for (auto EnumPair : EnumMap)
466+
if (CurToken.Kind == EnumPair.first) {
467+
*Enum = EnumPair.second;
468+
return false;
469+
}
470+
471+
llvm_unreachable("Switch for an expected token was not provided");
472+
return true;
473+
}
474+
475+
bool RootSignatureParser::ParseShaderVisibility(ShaderVisibility *Enum) {
476+
// Define the possible flag kinds
477+
llvm::SmallDenseMap<TokenKind, ShaderVisibility> EnumMap = {
478+
#define SHADER_VISIBILITY_ENUM(NAME, LIT) \
479+
{TokenKind::en_##NAME, ShaderVisibility::NAME},
480+
#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
481+
};
482+
483+
return ParseEnum(EnumMap, Enum);
484+
}
485+
435486
// Is given token one of the expected kinds
436487
static bool IsExpectedToken(TokenKind Kind, ArrayRef<TokenKind> AnyExpected) {
437488
for (auto Expected : AnyExpected)

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
338338
TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
339339
const llvm::StringLiteral Source = R"cc(
340340
DescriptorTable(
341+
visibility = SHADER_VISIBILITY_PIXEL,
341342
CBV(b0),
342343
SRV(t42, space = 3, offset = 32, numDescriptors = +4),
343344
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
@@ -408,11 +409,15 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
408409
Elem = Elements[4];
409410
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
410411
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)4);
412+
ASSERT_EQ(std::get<DescriptorTable>(Elem).Visibility,
413+
ShaderVisibility::Pixel);
411414

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

@@ -501,4 +506,27 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedParamTest) {
501506
ASSERT_TRUE(Consumer->IsSatisfied());
502507
}
503508

509+
TEST_F(ParseHLSLRootSignatureTest, InvalidParseRepeatedVisibilityTest) {
510+
const llvm::StringLiteral Source = R"cc(
511+
DescriptorTable(
512+
visibility = SHADER_VISIBILITY_GEOMETRY,
513+
visibility = SHADER_VISIBILITY_HULL
514+
)
515+
)cc";
516+
517+
TrivialModuleLoader ModLoader;
518+
auto PP = CreatePP(Source, ModLoader);
519+
auto TokLoc = SourceLocation();
520+
521+
hlsl::RootSignatureLexer Lexer(Source, TokLoc, *PP);
522+
SmallVector<RootElement> Elements;
523+
hlsl::RootSignatureParser Parser(Elements, Lexer, Diags);
524+
525+
// Test correct diagnostic produced
526+
Consumer->SetExpected(diag::err_hlsl_rootsig_repeat_param);
527+
ASSERT_TRUE(Parser.Parse());
528+
529+
ASSERT_TRUE(Consumer->IsSatisfied());
530+
}
531+
504532
} // 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 rootsig {
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

6174
} // namespace rootsig
6275
} // namespace hlsl

0 commit comments

Comments
 (0)