Skip to content

Commit 0259541

Browse files
authored
[HLSL][RootSignature] Add parsing infastructure for StaticSampler (#140180)
- define StaticSampler in-memory representation - implement the infastructure for parsing parameters of StaticSampler - define and implement parsing of the `s` reg to demonstrate functionality - add unit tests First part of #126574
1 parent da4958a commit 0259541

File tree

6 files changed

+110
-7
lines changed

6 files changed

+110
-7
lines changed

clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ KEYWORD(RootSignature) // used only for diagnostic messaging
8080
KEYWORD(RootFlags)
8181
KEYWORD(DescriptorTable)
8282
KEYWORD(RootConstants)
83+
KEYWORD(StaticSampler)
8384

8485
// RootConstants Keywords:
8586
KEYWORD(num32BitConstants)

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class RootSignatureParser {
7777
std::optional<llvm::hlsl::rootsig::DescriptorTable> parseDescriptorTable();
7878
std::optional<llvm::hlsl::rootsig::DescriptorTableClause>
7979
parseDescriptorTableClause();
80+
std::optional<llvm::hlsl::rootsig::StaticSampler> parseStaticSampler();
8081

8182
/// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
8283
/// order and only exactly once. The following methods define a
@@ -108,6 +109,11 @@ class RootSignatureParser {
108109
std::optional<ParsedClauseParams>
109110
parseDescriptorTableClauseParams(RootSignatureToken::Kind RegType);
110111

112+
struct ParsedStaticSamplerParams {
113+
std::optional<llvm::hlsl::rootsig::Register> Reg;
114+
};
115+
std::optional<ParsedStaticSamplerParams> parseStaticSamplerParams();
116+
111117
// Common parsing methods
112118
std::optional<uint32_t> parseUIntParam();
113119
std::optional<llvm::hlsl::rootsig::Register> parseRegister();

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ bool RootSignatureParser::parse() {
5353
return true;
5454
Elements.push_back(*Descriptor);
5555
}
56+
57+
if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) {
58+
auto Sampler = parseStaticSampler();
59+
if (!Sampler.has_value())
60+
return true;
61+
Elements.push_back(*Sampler);
62+
}
5663
} while (tryConsumeExpectedToken(TokenKind::pu_comma));
5764

5865
return consumeExpectedToken(TokenKind::end_of_stream,
@@ -346,6 +353,37 @@ RootSignatureParser::parseDescriptorTableClause() {
346353
return Clause;
347354
}
348355

356+
std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
357+
assert(CurToken.TokKind == TokenKind::kw_StaticSampler &&
358+
"Expects to only be invoked starting at given keyword");
359+
360+
if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
361+
CurToken.TokKind))
362+
return std::nullopt;
363+
364+
StaticSampler Sampler;
365+
366+
auto Params = parseStaticSamplerParams();
367+
if (!Params.has_value())
368+
return std::nullopt;
369+
370+
// Check mandatory parameters were provided
371+
if (!Params->Reg.has_value()) {
372+
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
373+
<< TokenKind::sReg;
374+
return std::nullopt;
375+
}
376+
377+
Sampler.Reg = Params->Reg.value();
378+
379+
if (consumeExpectedToken(TokenKind::pu_r_paren,
380+
diag::err_hlsl_unexpected_end_of_params,
381+
/*param of=*/TokenKind::kw_StaticSampler))
382+
return std::nullopt;
383+
384+
return Sampler;
385+
}
386+
349387
// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
350388
// order and only exactly once. The following methods will parse through as
351389
// many arguments as possible reporting an error if a duplicate is seen.
@@ -604,6 +642,30 @@ RootSignatureParser::parseDescriptorTableClauseParams(TokenKind RegType) {
604642
return Params;
605643
}
606644

645+
std::optional<RootSignatureParser::ParsedStaticSamplerParams>
646+
RootSignatureParser::parseStaticSamplerParams() {
647+
assert(CurToken.TokKind == TokenKind::pu_l_paren &&
648+
"Expects to only be invoked starting at given token");
649+
650+
ParsedStaticSamplerParams Params;
651+
do {
652+
// `s` POS_INT
653+
if (tryConsumeExpectedToken(TokenKind::sReg)) {
654+
if (Params.Reg.has_value()) {
655+
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
656+
<< CurToken.TokKind;
657+
return std::nullopt;
658+
}
659+
auto Reg = parseRegister();
660+
if (!Reg.has_value())
661+
return std::nullopt;
662+
Params.Reg = Reg;
663+
}
664+
} while (tryConsumeExpectedToken(TokenKind::pu_comma));
665+
666+
return Params;
667+
}
668+
607669
std::optional<uint32_t> RootSignatureParser::parseUIntParam() {
608670
assert(CurToken.TokKind == TokenKind::pu_equal &&
609671
"Expects to only be invoked starting at given keyword");

clang/unittests/Lex/LexHLSLRootSignatureTest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ TEST_F(LexHLSLRootSignatureTest, ValidLexAllTokensTest) {
128128
129129
RootSignature
130130
131-
RootFlags DescriptorTable RootConstants
131+
RootFlags DescriptorTable RootConstants StaticSampler
132132
133133
num32BitConstants
134134

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,34 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
223223
ASSERT_TRUE(Consumer->isSatisfied());
224224
}
225225

226+
TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) {
227+
const llvm::StringLiteral Source = R"cc(
228+
StaticSampler(s0)
229+
)cc";
230+
231+
TrivialModuleLoader ModLoader;
232+
auto PP = createPP(Source, ModLoader);
233+
auto TokLoc = SourceLocation();
234+
235+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
236+
SmallVector<RootElement> Elements;
237+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
238+
239+
// Test no diagnostics produced
240+
Consumer->setNoDiag();
241+
242+
ASSERT_FALSE(Parser.parse());
243+
244+
ASSERT_EQ(Elements.size(), 1u);
245+
246+
RootElement Elem = Elements[0];
247+
ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem));
248+
ASSERT_EQ(std::get<StaticSampler>(Elem).Reg.ViewType, RegisterType::SReg);
249+
ASSERT_EQ(std::get<StaticSampler>(Elem).Reg.Number, 0u);
250+
251+
ASSERT_TRUE(Consumer->isSatisfied());
252+
}
253+
226254
TEST_F(ParseHLSLRootSignatureTest, ValidSamplerFlagsTest) {
227255
// This test will checks we can set the valid enum for Sampler descriptor
228256
// range flags

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,23 +155,29 @@ struct DescriptorTableClause {
155155

156156
raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause);
157157

158-
/// Models RootElement : RootFlags | RootConstants | RootDescriptor
159-
/// | DescriptorTable | DescriptorTableClause
158+
struct StaticSampler {
159+
Register Reg;
160+
};
161+
162+
/// Models RootElement : RootFlags | RootConstants | RootParam
163+
/// | DescriptorTable | DescriptorTableClause | StaticSampler
160164
///
161165
/// A Root Signature is modeled in-memory by an array of RootElements. These
162166
/// aim to map closely to their DSL grammar reprsentation defined in the spec.
163167
///
164168
/// Each optional parameter has its default value defined in the struct, and,
165169
/// each mandatory parameter does not have a default initialization.
166170
///
167-
/// For the variants RootFlags, RootConstants and DescriptorTableClause: each
168-
/// data member maps directly to a parameter in the grammar.
171+
/// For the variants RootFlags, RootConstants, RootParam, StaticSampler and
172+
/// DescriptorTableClause: each data member maps directly to a parameter in the
173+
/// grammar.
169174
///
170175
/// The DescriptorTable is modelled by having its Clauses as the previous
171176
/// RootElements in the array, and it holds a data member for the Visibility
172177
/// parameter.
173-
using RootElement = std::variant<RootFlags, RootConstants, RootDescriptor,
174-
DescriptorTable, DescriptorTableClause>;
178+
using RootElement =
179+
std::variant<RootFlags, RootConstants, RootDescriptor, DescriptorTable,
180+
DescriptorTableClause, StaticSampler>;
175181

176182
void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements);
177183

0 commit comments

Comments
 (0)