Skip to content

Commit 1f75248

Browse files
committed
add support for parsing Flag parameters
- use DescriptorRangeFlags to demonstrate valid functionality
1 parent 847974b commit 1f75248

File tree

4 files changed

+120
-4
lines changed

4 files changed

+120
-4
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ class RootSignatureParser {
139139
template <bool AllowZero = false, typename EnumType>
140140
bool ParseEnum(llvm::SmallDenseMap<TokenKind, EnumType> &EnumMap,
141141
EnumType *Enum);
142+
template <typename FlagType>
143+
bool ParseFlags(llvm::SmallDenseMap<TokenKind, FlagType> &EnumMap,
144+
FlagType *Enum);
145+
bool
146+
ParseDescriptorRangeFlags(llvm::hlsl::rootsig::DescriptorRangeFlags *Enum);
142147
bool ParseShaderVisibility(llvm::hlsl::rootsig::ShaderVisibility *Enum);
143148

144149
/// Invoke the lexer to consume a token and update CurToken with the result

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
325325
default:
326326
llvm_unreachable("Switch for an expected token was not provided");
327327
}
328+
Clause.SetDefaultFlags();
329+
328330
if (ConsumeExpectedToken(TokenKind::pu_l_paren))
329331
return true;
330332

@@ -340,6 +342,7 @@ bool RootSignatureParser::ParseDescriptorTableClause() {
340342
{TokenKind::kw_numDescriptors, &Clause.NumDescriptors},
341343
{TokenKind::kw_space, &Clause.Space},
342344
{TokenKind::kw_offset, &Clause.Offset},
345+
{TokenKind::kw_flags, &Clause.Flags},
343346
};
344347
if (ParseOptionalParams({RefMap}))
345348
return true;
@@ -366,6 +369,9 @@ bool RootSignatureParser::ParseParam(ParamType Ref) {
366369
[&](DescriptorRangeOffset *X) {
367370
Error = ParseDescriptorRangeOffset(X);
368371
},
372+
[&](DescriptorRangeFlags *Flags) {
373+
Error = ParseDescriptorRangeFlags(Flags);
374+
},
369375
[&](ShaderVisibility *Enum) {
370376
Error = ParseShaderVisibility(Enum);
371377
},
@@ -450,17 +456,29 @@ bool RootSignatureParser::ParseRegister(Register *Register) {
450456
return false;
451457
}
452458

453-
template <typename EnumType>
459+
template <bool AllowZero, typename EnumType>
454460
bool RootSignatureParser::ParseEnum(
455461
llvm::SmallDenseMap<TokenKind, EnumType> &EnumMap, EnumType *Enum) {
456462
SmallVector<TokenKind> EnumToks;
463+
if (AllowZero)
464+
EnumToks.push_back(TokenKind::int_literal); // '0' is a valid flag value
457465
for (auto EnumPair : EnumMap)
458466
EnumToks.push_back(EnumPair.first);
459467

460468
// If invoked we expect to have an enum
461469
if (ConsumeExpectedToken(EnumToks))
462470
return true;
463471

472+
// Handle the edge case when '0' is used to specify None
473+
if (CurTok->Kind == TokenKind::int_literal) {
474+
if (CurTok->NumLiteral.getInt() != 0) {
475+
return true;
476+
}
477+
// Set enum to None equivalent
478+
*Enum = EnumType(0);
479+
return false;
480+
}
481+
464482
// Effectively a switch statement on the token kinds
465483
for (auto EnumPair : EnumMap)
466484
if (CurToken.Kind == EnumPair.first) {
@@ -472,6 +490,36 @@ bool RootSignatureParser::ParseEnum(
472490
return true;
473491
}
474492

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

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -340,9 +340,13 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
340340
DescriptorTable(
341341
visibility = SHADER_VISIBILITY_PIXEL,
342342
CBV(b0),
343-
SRV(t42, space = 3, offset = 32, numDescriptors = +4),
343+
SRV(t42, space = 3, offset = 32, numDescriptors = +4, flags = 0),
344344
Sampler(s987, space = 2, offset = DESCRIPTOR_RANGE_OFFSET_APPEND),
345-
UAV(u987234)
345+
UAV(u987234,
346+
flags = Descriptors_Volatile | Data_Volatile
347+
| Data_Static_While_Set_At_Execute | Data_Static
348+
| Descriptors_Static_Keeping_Buffer_Bounds_Checks
349+
)
346350
),
347351
DescriptorTable()
348352
)cc";
@@ -369,6 +373,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
369373
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
370374
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
371375
DescriptorRangeOffset(DescriptorTableOffsetAppend));
376+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
377+
DescriptorRangeFlags::DataStaticWhileSetAtExecute);
372378

373379
Elem = Elements[1];
374380
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -381,6 +387,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
381387
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)3);
382388
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
383389
DescriptorRangeOffset(32));
390+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
391+
DescriptorRangeFlags::None);
384392

385393
Elem = Elements[2];
386394
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -393,6 +401,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
393401
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)2);
394402
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
395403
DescriptorRangeOffset(DescriptorTableOffsetAppend));
404+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
405+
DescriptorRangeFlags::None);
396406

397407
Elem = Elements[3];
398408
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
@@ -405,6 +415,8 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
405415
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Space, (uint32_t)0);
406416
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Offset,
407417
DescriptorRangeOffset(DescriptorTableOffsetAppend));
418+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Flags,
419+
DescriptorRangeFlags::ValidFlags);
408420

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

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

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,43 @@ namespace llvm {
2121
namespace hlsl {
2222
namespace rootsig {
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,7 @@ 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 *>;
73124

74125
} // namespace rootsig
75126
} // namespace hlsl

0 commit comments

Comments
 (0)