Skip to content

Commit 1d0b2c8

Browse files
committed
add support for parsing Flag parameters
- use DescriptorRangeFlags to demonstrate valid functionality
1 parent 14bd063 commit 1d0b2c8

File tree

4 files changed

+121
-5
lines changed

4 files changed

+121
-5
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,13 @@ class RootSignatureParser {
138138
bool ParseDescriptorRangeOffset(rs::DescriptorRangeOffset *X);
139139

140140
// Various flags/enum parsing helpers
141-
template <typename EnumType>
141+
template <bool AllowZero = false, typename EnumType>
142142
bool ParseEnum(llvm::SmallDenseMap<TokenKind, EnumType> EnumMap,
143143
EnumType *Enum);
144+
template <typename FlagType>
145+
bool ParseFlags(llvm::SmallDenseMap<TokenKind, FlagType> EnumMap,
146+
FlagType *Enum);
147+
bool ParseDescriptorRangeFlags(rs::DescriptorRangeFlags *Enum);
144148
bool ParseShaderVisibility(rs::ShaderVisibility *Enum);
145149

146150
// Increment the token iterator if we have not reached the end.

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,8 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
351351
llvm_unreachable("Switch for an expected token was not provided");
352352
return true;
353353
}
354+
Clause.SetDefaultFlags();
355+
354356
if (ConsumeExpectedToken(TokenKind::pu_l_paren))
355357
return true;
356358

@@ -366,6 +368,7 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
366368
{TokenKind::kw_numDescriptors, &Clause.NumDescriptors},
367369
{TokenKind::kw_space, &Clause.Space},
368370
{TokenKind::kw_offset, &Clause.Offset},
371+
{TokenKind::kw_flags, &Clause.Flags},
369372
};
370373
if (ParseOptionalParams({RefMap}))
371374
return true;
@@ -392,6 +395,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
392395
[&](DescriptorRangeOffset *X) {
393396
Error = ParseDescriptorRangeOffset(X);
394397
},
398+
[&](DescriptorRangeFlags *Flags) {
399+
Error = ParseDescriptorRangeFlags(Flags);
400+
},
395401
[&](ShaderVisibility *Enum) {
396402
Error = ParseShaderVisibility(Enum);
397403
},
@@ -475,17 +481,29 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
475481
return false;
476482
}
477483

478-
template <typename EnumType>
484+
template <bool AllowZero, typename EnumType>
479485
bool RootSignatureParser::ParseEnum(
480486
llvm::SmallDenseMap<TokenKind, EnumType> EnumMap, EnumType *Enum) {
481487
SmallVector<TokenKind> EnumToks;
488+
if (AllowZero)
489+
EnumToks.push_back(TokenKind::int_literal); // '0' is a valid flag value
482490
for (auto EnumPair : EnumMap)
483491
EnumToks.push_back(EnumPair.first);
484492

485493
// If invoked we expect to have an enum
486494
if (ConsumeExpectedToken(EnumToks))
487495
return true;
488496

497+
// Handle the edge case when '0' is used to specify None
498+
if (CurTok->Kind == TokenKind::int_literal) {
499+
if (CurTok->NumLiteral.getInt() != 0) {
500+
return true;
501+
}
502+
// Set enum to None equivalent
503+
*Enum = EnumType(0);
504+
return false;
505+
}
506+
489507
// Effectively a switch statement on the token kinds
490508
for (auto EnumPair : EnumMap)
491509
if (CurTok->Kind == EnumPair.first) {
@@ -497,6 +515,36 @@ bool RootSignatureParser::ParseEnum(
497515
return true;
498516
}
499517

518+
template <typename FlagType>
519+
bool RootSignatureParser::ParseFlags(
520+
llvm::SmallDenseMap<TokenKind, FlagType> FlagMap, FlagType *Flags) {
521+
// Override the default value to 0 so that we can correctly 'or' the values
522+
*Flags = FlagType(0);
523+
524+
do {
525+
FlagType Flag;
526+
if (ParseEnum<true>(FlagMap, &Flag))
527+
return true;
528+
// Store the 'or'
529+
*Flags |= Flag;
530+
531+
} while (!TryConsumeExpectedToken(TokenKind::pu_or));
532+
533+
return false;
534+
}
535+
536+
bool RootSignatureParser::ParseDescriptorRangeFlags(
537+
DescriptorRangeFlags *Flags) {
538+
// Define the possible flag kinds
539+
llvm::SmallDenseMap<TokenKind, DescriptorRangeFlags> FlagMap = {
540+
#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) \
541+
{TokenKind::en_##NAME, DescriptorRangeFlags::NAME},
542+
#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
543+
};
544+
545+
return ParseFlags(FlagMap, Flags);
546+
}
547+
500548
bool RootSignatureParser::ParseShaderVisibility(ShaderVisibility *Enum) {
501549
// Define the possible flag kinds
502550
llvm::SmallDenseMap<TokenKind, ShaderVisibility> EnumMap = {

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,13 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
388388
DescriptorTable(
389389
visibility = SHADER_VISIBILITY_PIXEL,
390390
CBV(b0),
391-
SRV(t42, space = 3, offset = 32, numDescriptors = 4),
391+
SRV(t42, space = 3, offset = 32, numDescriptors = 4, flags = 0),
392392
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
393-
UAV(u987234)
393+
UAV(u987234,
394+
flags = Descriptors_Volatile | Data_Volatile
395+
| Data_Static_While_Set_At_Execute | Data_Static
396+
| Descriptors_Static_Keeping_Buffer_Bounds_Checks
397+
)
394398
),
395399
DescriptorTable()
396400
)cc";
@@ -421,6 +425,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
421425
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
422426
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
423427
DescriptorRangeOffset(DescriptorTableOffsetAppend));
428+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
429+
DescriptorRangeFlags::DataStaticWhileSetAtExecute);
424430

425431
Elem = Elements[1];
426432
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -433,6 +439,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
433439
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)3);
434440
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
435441
DescriptorRangeOffset(32));
442+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
443+
DescriptorRangeFlags::None);
436444

437445
Elem = Elements[2];
438446
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -445,6 +453,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
445453
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)2);
446454
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
447455
DescriptorRangeOffset(DescriptorTableOffsetAppend));
456+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
457+
DescriptorRangeFlags::None);
448458

449459
Elem = Elements[3];
450460
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -457,6 +467,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
457467
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
458468
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
459469
DescriptorRangeOffset(DescriptorTableOffsetAppend));
470+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
471+
DescriptorRangeFlags::ValidFlags);
460472

461473
Elem = Elements[4];
462474
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,43 @@ namespace llvm {
2121
namespace hlsl {
2222
namespace root_signature {
2323

24+
#define RS_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(Class) \
25+
inline Class operator|(Class a, Class b) { \
26+
return static_cast<Class>(llvm::to_underlying(a) | \
27+
llvm::to_underlying(b)); \
28+
} \
29+
inline Class operator&(Class a, Class b) { \
30+
return static_cast<Class>(llvm::to_underlying(a) & \
31+
llvm::to_underlying(b)); \
32+
} \
33+
inline Class operator~(Class a) { \
34+
return static_cast<Class>(~llvm::to_underlying(a)); \
35+
} \
36+
inline Class &operator|=(Class &a, Class b) { \
37+
a = a | b; \
38+
return a; \
39+
} \
40+
inline Class &operator&=(Class &a, Class b) { \
41+
a = a & b; \
42+
return a; \
43+
}
44+
2445
// Definition of the various enumerations and flags
2546

2647
enum class DescriptorRangeOffset : uint32_t;
2748

49+
enum class DescriptorRangeFlags : unsigned {
50+
None = 0,
51+
DescriptorsVolatile = 0x1,
52+
DataVolatile = 0x2,
53+
DataStaticWhileSetAtExecute = 0x4,
54+
DataStatic = 0x8,
55+
DescriptorsStaticKeepingBufferBoundsChecks = 0x10000,
56+
ValidFlags = 0x1000f,
57+
ValidSamplerFlags = DescriptorsVolatile,
58+
};
59+
RS_DEFINE_ENUM_CLASS_FLAGS_OPERATORS(DescriptorRangeFlags)
60+
2861
enum class ShaderVisibility {
2962
All = 0,
3063
Vertex = 1,
@@ -61,6 +94,24 @@ struct DescriptorTableClause {
6194
uint32_t NumDescriptors = 1;
6295
uint32_t Space = 0;
6396
DescriptorRangeOffset Offset = DescriptorTableOffsetAppend;
97+
DescriptorRangeFlags Flags;
98+
99+
void SetDefaultFlags() {
100+
switch (Type) {
101+
case ClauseType::CBuffer:
102+
Flags = DescriptorRangeFlags::DataStaticWhileSetAtExecute;
103+
break;
104+
case ClauseType::SRV:
105+
Flags = DescriptorRangeFlags::DataStaticWhileSetAtExecute;
106+
break;
107+
case ClauseType::UAV:
108+
Flags = DescriptorRangeFlags::DataVolatile;
109+
break;
110+
case ClauseType::Sampler:
111+
Flags = DescriptorRangeFlags::None;
112+
break;
113+
}
114+
}
64115
};
65116

66117
// Models RootElement : DescriptorTable | DescriptorTableClause
@@ -69,7 +120,8 @@ using RootElement = std::variant<DescriptorTable, DescriptorTableClause>;
69120
// Models a reference to all assignment parameter types that any RootElement
70121
// may have. Things of the form: Keyword = Param
71122
using ParamType = std::variant<uint32_t *, DescriptorRangeOffset *,
72-
ShaderVisibility *>;
123+
DescriptorRangeFlags *, ShaderVisibility *>;
124+
73125
} // namespace root_signature
74126
} // namespace hlsl
75127
} // namespace llvm

0 commit comments

Comments
 (0)