Skip to content

Commit 6775f3d

Browse files
committed
add support for parsing Flag parameters
- use DescriptorRangeFlags to demonstrate valid functionality
1 parent 15a8e59 commit 6775f3d

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
@@ -125,9 +125,13 @@ class RootSignatureParser {
125125
bool ParseDescriptorRangeOffset(rs::DescriptorRangeOffset *X);
126126

127127
// Various flags/enum parsing helpers
128-
template <typename EnumType>
128+
template <bool AllowZero = false, typename EnumType>
129129
bool ParseEnum(llvm::SmallDenseMap<TokenKind, EnumType> EnumMap,
130130
EnumType *Enum);
131+
template <typename FlagType>
132+
bool ParseFlags(llvm::SmallDenseMap<TokenKind, FlagType> EnumMap,
133+
FlagType *Enum);
134+
bool ParseDescriptorRangeFlags(rs::DescriptorRangeFlags *Enum);
131135
bool ParseShaderVisibility(rs::ShaderVisibility *Enum);
132136

133137
// 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
@@ -330,6 +330,8 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
330330
llvm_unreachable("Switch for an expected token was not provided");
331331
return true;
332332
}
333+
Clause.SetDefaultFlags();
334+
333335
if (ConsumeExpectedToken(TokenKind::pu_l_paren))
334336
return true;
335337

@@ -345,6 +347,7 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
345347
{TokenKind::kw_numDescriptors, &Clause.NumDescriptors},
346348
{TokenKind::kw_space, &Clause.Space},
347349
{TokenKind::kw_offset, &Clause.Offset},
350+
{TokenKind::kw_flags, &Clause.Flags},
348351
};
349352
if (ParseOptionalParams({RefMap}))
350353
return true;
@@ -371,6 +374,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
371374
[&](DescriptorRangeOffset *X) {
372375
Error = ParseDescriptorRangeOffset(X);
373376
},
377+
[&](DescriptorRangeFlags *Flags) {
378+
Error = ParseDescriptorRangeFlags(Flags);
379+
},
374380
[&](ShaderVisibility *Enum) {
375381
Error = ParseShaderVisibility(Enum);
376382
},
@@ -454,17 +460,29 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
454460
return false;
455461
}
456462

457-
template <typename EnumType>
463+
template <bool AllowZero, typename EnumType>
458464
bool RootSignatureParser::ParseEnum(
459465
llvm::SmallDenseMap<TokenKind, EnumType> EnumMap, EnumType *Enum) {
460466
SmallVector<TokenKind> EnumToks;
467+
if (AllowZero)
468+
EnumToks.push_back(TokenKind::int_literal); // '0' is a valid flag value
461469
for (auto EnumPair : EnumMap)
462470
EnumToks.push_back(EnumPair.first);
463471

464472
// If invoked we expect to have an enum
465473
if (ConsumeExpectedToken(EnumToks))
466474
return true;
467475

476+
// Handle the edge case when '0' is used to specify None
477+
if (CurTok->Kind == TokenKind::int_literal) {
478+
if (CurTok->NumLiteral.getInt() != 0) {
479+
return true;
480+
}
481+
// Set enum to None equivalent
482+
*Enum = EnumType(0);
483+
return false;
484+
}
485+
468486
// Effectively a switch statement on the token kinds
469487
for (auto EnumPair : EnumMap)
470488
if (CurTok->Kind == EnumPair.first) {
@@ -476,6 +494,36 @@ bool RootSignatureParser::ParseEnum(
476494
return true;
477495
}
478496

497+
template <typename FlagType>
498+
bool RootSignatureParser::ParseFlags(
499+
llvm::SmallDenseMap<TokenKind, FlagType> FlagMap, FlagType *Flags) {
500+
// Override the default value to 0 so that we can correctly 'or' the values
501+
*Flags = FlagType(0);
502+
503+
do {
504+
FlagType Flag;
505+
if (ParseEnum<true>(FlagMap, &Flag))
506+
return true;
507+
// Store the 'or'
508+
*Flags |= Flag;
509+
510+
} while (!TryConsumeExpectedToken(TokenKind::pu_or));
511+
512+
return false;
513+
}
514+
515+
bool RootSignatureParser::ParseDescriptorRangeFlags(
516+
DescriptorRangeFlags *Flags) {
517+
// Define the possible flag kinds
518+
llvm::SmallDenseMap<TokenKind, DescriptorRangeFlags> FlagMap = {
519+
#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) \
520+
{TokenKind::en_##NAME, DescriptorRangeFlags::NAME},
521+
#include "clang/Parse/HLSLRootSignatureTokenKinds.def"
522+
};
523+
524+
return ParseFlags(FlagMap, Flags);
525+
}
526+
479527
bool RootSignatureParser::ParseShaderVisibility(ShaderVisibility *Enum) {
480528
// Define the possible flag kinds
481529
llvm::SmallDenseMap<TokenKind, ShaderVisibility> EnumMap = {

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,13 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
310310
DescriptorTable(
311311
visibility = SHADER_VISIBILITY_PIXEL,
312312
CBV(b0),
313-
SRV(t42, space = 3, offset = 32, numDescriptors = 4),
313+
SRV(t42, space = 3, offset = 32, numDescriptors = 4, flags = 0),
314314
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
315-
UAV(u987234)
315+
UAV(u987234,
316+
flags = Descriptors_Volatile | Data_Volatile
317+
| Data_Static_While_Set_At_Execute | Data_Static
318+
| Descriptors_Static_Keeping_Buffer_Bounds_Checks
319+
)
316320
),
317321
DescriptorTable()
318322
)cc";
@@ -343,6 +347,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
343347
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
344348
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
345349
DescriptorRangeOffset(DescriptorTableOffsetAppend));
350+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
351+
DescriptorRangeFlags::DataStaticWhileSetAtExecute);
346352

347353
Elem = Elements[1];
348354
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -355,6 +361,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
355361
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)3);
356362
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
357363
DescriptorRangeOffset(32));
364+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
365+
DescriptorRangeFlags::None);
358366

359367
Elem = Elements[2];
360368
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -367,6 +375,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
367375
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)2);
368376
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
369377
DescriptorRangeOffset(DescriptorTableOffsetAppend));
378+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
379+
DescriptorRangeFlags::None);
370380

371381
Elem = Elements[3];
372382
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -379,6 +389,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
379389
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
380390
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
381391
DescriptorRangeOffset(DescriptorTableOffsetAppend));
392+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
393+
DescriptorRangeFlags::ValidFlags);
382394

383395
Elem = Elements[4];
384396
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)