Skip to content

Commit 3c928d5

Browse files
committed
add support for parsing Flag parameters
- use DescriptorRangeFlags to demonstrate valid functionality
1 parent 4ed3abf commit 3c928d5

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
@@ -323,6 +323,8 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
323323
llvm_unreachable("Switch for an expected token was not provided");
324324
return true;
325325
}
326+
Clause.SetDefaultFlags();
327+
326328
if (ConsumeExpectedToken(TokenKind::pu_l_paren))
327329
return true;
328330

@@ -338,6 +340,7 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
338340
{TokenKind::kw_numDescriptors, &Clause.NumDescriptors},
339341
{TokenKind::kw_space, &Clause.Space},
340342
{TokenKind::kw_offset, &Clause.Offset},
343+
{TokenKind::kw_flags, &Clause.Flags},
341344
};
342345
if (ParseOptionalParams({RefMap}))
343346
return true;
@@ -364,6 +367,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
364367
[&](DescriptorRangeOffset *X) {
365368
Error = ParseDescriptorRangeOffset(X);
366369
},
370+
[&](DescriptorRangeFlags *Flags) {
371+
Error = ParseDescriptorRangeFlags(Flags);
372+
},
367373
[&](ShaderVisibility *Enum) {
368374
Error = ParseShaderVisibility(Enum);
369375
},
@@ -447,17 +453,29 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
447453
return false;
448454
}
449455

450-
template <typename EnumType>
456+
template <bool AllowZero, typename EnumType>
451457
bool RootSignatureParser::ParseEnum(
452458
llvm::SmallDenseMap<TokenKind, EnumType> EnumMap, EnumType *Enum) {
453459
SmallVector<TokenKind> EnumToks;
460+
if (AllowZero)
461+
EnumToks.push_back(TokenKind::int_literal); // '0' is a valid flag value
454462
for (auto EnumPair : EnumMap)
455463
EnumToks.push_back(EnumPair.first);
456464

457465
// If invoked we expect to have an enum
458466
if (ConsumeExpectedToken(EnumToks))
459467
return true;
460468

469+
// Handle the edge case when '0' is used to specify None
470+
if (CurTok->Kind == TokenKind::int_literal) {
471+
if (CurTok->NumLiteral.getInt() != 0) {
472+
return true;
473+
}
474+
// Set enum to None equivalent
475+
*Enum = EnumType(0);
476+
return false;
477+
}
478+
461479
// Effectively a switch statement on the token kinds
462480
for (auto EnumPair : EnumMap)
463481
if (CurTok->Kind == EnumPair.first) {
@@ -469,6 +487,36 @@ bool RootSignatureParser::ParseEnum(
469487
return true;
470488
}
471489

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

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,13 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
337337
DescriptorTable(
338338
visibility = SHADER_VISIBILITY_PIXEL,
339339
CBV(b0),
340-
SRV(t42, space = 3, offset = 32, numDescriptors = 4),
340+
SRV(t42, space = 3, offset = 32, numDescriptors = 4, flags = 0),
341341
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
342-
UAV(u987234)
342+
UAV(u987234,
343+
flags = Descriptors_Volatile | Data_Volatile
344+
| Data_Static_While_Set_At_Execute | Data_Static
345+
| Descriptors_Static_Keeping_Buffer_Bounds_Checks
346+
)
343347
),
344348
DescriptorTable()
345349
)cc";
@@ -370,6 +374,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
370374
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
371375
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
372376
DescriptorRangeOffset(DescriptorTableOffsetAppend));
377+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
378+
DescriptorRangeFlags::DataStaticWhileSetAtExecute);
373379

374380
Elem = Elements[1];
375381
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -382,6 +388,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
382388
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)3);
383389
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
384390
DescriptorRangeOffset(32));
391+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
392+
DescriptorRangeFlags::None);
385393

386394
Elem = Elements[2];
387395
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -394,6 +402,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
394402
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)2);
395403
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
396404
DescriptorRangeOffset(DescriptorTableOffsetAppend));
405+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
406+
DescriptorRangeFlags::None);
397407

398408
Elem = Elements[3];
399409
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -406,6 +416,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
406416
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
407417
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
408418
DescriptorRangeOffset(DescriptorTableOffsetAppend));
419+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
420+
DescriptorRangeFlags::ValidFlags);
409421

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