https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/140180
>From 05cd843e21cd8d93a94914d13843871886146dab Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 15 May 2025 22:35:30 +0000 Subject: [PATCH] [HLSL][RootSignature] Add parsing infastructure for StaticSampler - 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 --- .../clang/Parse/ParseHLSLRootSignature.h | 6 ++ clang/lib/Parse/ParseHLSLRootSignature.cpp | 62 +++++++++++++++++++ .../Parse/ParseHLSLRootSignatureTest.cpp | 28 +++++++++ .../llvm/Frontend/HLSL/HLSLRootSignature.h | 18 ++++-- 4 files changed, 108 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index 3754b4a7b595f..da17388a2aea5 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -77,6 +77,7 @@ class RootSignatureParser { std::optional<llvm::hlsl::rootsig::DescriptorTable> parseDescriptorTable(); std::optional<llvm::hlsl::rootsig::DescriptorTableClause> parseDescriptorTableClause(); + std::optional<llvm::hlsl::rootsig::StaticSampler> parseStaticSampler(); /// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any /// order and only exactly once. The following methods define a @@ -108,6 +109,11 @@ class RootSignatureParser { std::optional<ParsedClauseParams> parseDescriptorTableClauseParams(RootSignatureToken::Kind RegType); + struct ParsedStaticSamplerParams { + std::optional<llvm::hlsl::rootsig::Register> Reg; + }; + std::optional<ParsedStaticSamplerParams> parseStaticSamplerParams(); + // Common parsing methods std::optional<uint32_t> parseUIntParam(); std::optional<llvm::hlsl::rootsig::Register> parseRegister(); diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 5181aae3f2d3b..520676fa0a614 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -55,6 +55,13 @@ bool RootSignatureParser::parse() { return true; Elements.push_back(*Descriptor); } + + if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) { + auto Sampler = parseStaticSampler(); + if (!Sampler.has_value()) + return true; + Elements.push_back(*Sampler); + } } while (tryConsumeExpectedToken(TokenKind::pu_comma)); return consumeExpectedToken(TokenKind::end_of_stream, @@ -348,6 +355,37 @@ RootSignatureParser::parseDescriptorTableClause() { return Clause; } +std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() { + assert(CurToken.TokKind == TokenKind::kw_StaticSampler && + "Expects to only be invoked starting at given keyword"); + + if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after, + CurToken.TokKind)) + return std::nullopt; + + StaticSampler Sampler; + + auto Params = parseStaticSamplerParams(); + if (!Params.has_value()) + return std::nullopt; + + // Check mandatory parameters were provided + if (!Params->Reg.has_value()) { + getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param) + << TokenKind::sReg; + return std::nullopt; + } + + Sampler.Reg = Params->Reg.value(); + + if (consumeExpectedToken(TokenKind::pu_r_paren, + diag::err_hlsl_unexpected_end_of_params, + /*param of=*/TokenKind::kw_StaticSampler)) + return std::nullopt; + + return Sampler; +} + // Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any // order and only exactly once. The following methods will parse through as // many arguments as possible reporting an error if a duplicate is seen. @@ -606,6 +644,30 @@ RootSignatureParser::parseDescriptorTableClauseParams(TokenKind RegType) { return Params; } +std::optional<RootSignatureParser::ParsedStaticSamplerParams> +RootSignatureParser::parseStaticSamplerParams() { + assert(CurToken.TokKind == TokenKind::pu_l_paren && + "Expects to only be invoked starting at given token"); + + ParsedStaticSamplerParams Params; + do { + // `s` POS_INT + if (tryConsumeExpectedToken(TokenKind::sReg)) { + if (Params.Reg.has_value()) { + getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) + << CurToken.TokKind; + return std::nullopt; + } + auto Reg = parseRegister(); + if (!Reg.has_value()) + return std::nullopt; + Params.Reg = Reg; + } + } while (tryConsumeExpectedToken(TokenKind::pu_comma)); + + return Params; +} + std::optional<uint32_t> RootSignatureParser::parseUIntParam() { assert(CurToken.TokKind == TokenKind::pu_equal && "Expects to only be invoked starting at given keyword"); diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index 64e780a61baf8..cd3b12dbe4d24 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -223,6 +223,34 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) { ASSERT_TRUE(Consumer->isSatisfied()); } +TEST_F(ParseHLSLRootSignatureTest, ValidParseStaticSamplerTest) { + const llvm::StringLiteral Source = R"cc( + StaticSampler(s0) + )cc"; + + TrivialModuleLoader ModLoader; + auto PP = createPP(Source, ModLoader); + auto TokLoc = SourceLocation(); + + hlsl::RootSignatureLexer Lexer(Source, TokLoc); + SmallVector<RootElement> Elements; + hlsl::RootSignatureParser Parser(Elements, Lexer, *PP); + + // Test no diagnostics produced + Consumer->setNoDiag(); + + ASSERT_FALSE(Parser.parse()); + + ASSERT_EQ(Elements.size(), 1u); + + RootElement Elem = Elements[0]; + ASSERT_TRUE(std::holds_alternative<StaticSampler>(Elem)); + ASSERT_EQ(std::get<StaticSampler>(Elem).Reg.ViewType, RegisterType::SReg); + ASSERT_EQ(std::get<StaticSampler>(Elem).Reg.Number, 0u); + + ASSERT_TRUE(Consumer->isSatisfied()); +} + TEST_F(ParseHLSLRootSignatureTest, ValidSamplerFlagsTest) { // This test will checks we can set the valid enum for Sampler descriptor // range flags diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index fd0abc9479469..ca2f166479ce7 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -155,8 +155,12 @@ struct DescriptorTableClause { raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause); -/// Models RootElement : RootFlags | RootConstants | RootDescriptor -/// | DescriptorTable | DescriptorTableClause +struct StaticSampler { + Register Reg; +}; + +/// Models RootElement : RootFlags | RootConstants | RootParam +/// | DescriptorTable | DescriptorTableClause | StaticSampler /// /// A Root Signature is modeled in-memory by an array of RootElements. These /// aim to map closely to their DSL grammar reprsentation defined in the spec. @@ -164,14 +168,16 @@ raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause); /// Each optional parameter has its default value defined in the struct, and, /// each mandatory parameter does not have a default initialization. /// -/// For the variants RootFlags, RootConstants and DescriptorTableClause: each -/// data member maps directly to a parameter in the grammar. +/// For the variants RootFlags, RootConstants, RootParam, StaticSampler and +/// DescriptorTableClause: each data member maps directly to a parameter in the +/// grammar. /// /// The DescriptorTable is modelled by having its Clauses as the previous /// RootElements in the array, and it holds a data member for the Visibility /// parameter. -using RootElement = std::variant<RootFlags, RootConstants, RootDescriptor, - DescriptorTable, DescriptorTableClause>; +using RootElement = + std::variant<RootFlags, RootConstants, RootParam, DescriptorTable, + DescriptorTableClause, StaticSampler>; void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits