Author: Finn Plummer Date: 2025-05-21T14:40:13-07:00 New Revision: b499f7f2b246c284f8deb428f68d0b488b80c630
URL: https://github.com/llvm/llvm-project/commit/b499f7f2b246c284f8deb428f68d0b488b80c630 DIFF: https://github.com/llvm/llvm-project/commit/b499f7f2b246c284f8deb428f68d0b488b80c630.diff LOG: [HLSL][RootSignature] Add parsing for empty RootDescriptors (#140147) - define the RootDescriptor in-memory struct containing its type - add test harness for testing First part of https://github.com/llvm/llvm-project/issues/126577 Added: Modified: clang/include/clang/Parse/ParseHLSLRootSignature.h clang/lib/Parse/ParseHLSLRootSignature.cpp clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h Removed: ################################################################################ diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h b/clang/include/clang/Parse/ParseHLSLRootSignature.h index 915266f8a36ae..939d45e0c01bc 100644 --- a/clang/include/clang/Parse/ParseHLSLRootSignature.h +++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h @@ -73,6 +73,7 @@ class RootSignatureParser { /// Root Element parse methods: std::optional<llvm::hlsl::rootsig::RootFlags> parseRootFlags(); std::optional<llvm::hlsl::rootsig::RootConstants> parseRootConstants(); + std::optional<llvm::hlsl::rootsig::RootDescriptor> parseRootDescriptor(); std::optional<llvm::hlsl::rootsig::DescriptorTable> parseDescriptorTable(); std::optional<llvm::hlsl::rootsig::DescriptorTableClause> parseDescriptorTableClause(); diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp b/clang/lib/Parse/ParseHLSLRootSignature.cpp index 5603900429844..d71f2c22d5d4b 100644 --- a/clang/lib/Parse/ParseHLSLRootSignature.cpp +++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp @@ -47,6 +47,14 @@ bool RootSignatureParser::parse() { return true; Elements.push_back(*Table); } + + if (tryConsumeExpectedToken( + {TokenKind::kw_CBV, TokenKind::kw_SRV, TokenKind::kw_UAV})) { + auto Descriptor = parseRootDescriptor(); + if (!Descriptor.has_value()) + return true; + Elements.push_back(*Descriptor); + } } while (tryConsumeExpectedToken(TokenKind::pu_comma)); return consumeExpectedToken(TokenKind::end_of_stream, @@ -155,6 +163,41 @@ std::optional<RootConstants> RootSignatureParser::parseRootConstants() { return Constants; } +std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() { + assert((CurToken.TokKind == TokenKind::kw_CBV || + CurToken.TokKind == TokenKind::kw_SRV || + CurToken.TokKind == TokenKind::kw_UAV) && + "Expects to only be invoked starting at given keyword"); + + TokenKind DescriptorKind = CurToken.TokKind; + + if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after, + CurToken.TokKind)) + return std::nullopt; + + RootDescriptor Descriptor; + switch (DescriptorKind) { + default: + llvm_unreachable("Switch for consumed token was not provided"); + case TokenKind::kw_CBV: + Descriptor.Type = DescriptorType::CBuffer; + break; + case TokenKind::kw_SRV: + Descriptor.Type = DescriptorType::SRV; + break; + case TokenKind::kw_UAV: + Descriptor.Type = DescriptorType::UAV; + break; + } + + if (consumeExpectedToken(TokenKind::pu_r_paren, + diag::err_hlsl_unexpected_end_of_params, + /*param of=*/TokenKind::kw_RootConstants)) + return std::nullopt; + + return Descriptor; +} + std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() { assert(CurToken.TokKind == TokenKind::kw_DescriptorTable && "Expects to only be invoked starting at given keyword"); diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp index c97f8d0b392d1..7d03dda1f516b 100644 --- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp +++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp @@ -344,6 +344,43 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootFlagsTest) { ASSERT_TRUE(Consumer->isSatisfied()); } +TEST_F(ParseHLSLRootSignatureTest, ValidParseRootDescriptorsTest) { + const llvm::StringLiteral Source = R"cc( + CBV(), + SRV(), + UAV() + )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(), 3u); + + RootElement Elem = Elements[0]; + ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem)); + ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::CBuffer); + + Elem = Elements[1]; + ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem)); + ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::SRV); + + Elem = Elements[2]; + ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem)); + ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::UAV); + + ASSERT_TRUE(Consumer->isSatisfied()); +} + TEST_F(ParseHLSLRootSignatureTest, ValidTrailingCommaTest) { // This test will checks we can handling trailing commas ',' const llvm::StringLiteral Source = R"cc( diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 9fdb40db9c23d..7829b842fa2be 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -85,6 +85,12 @@ struct RootConstants { ShaderVisibility Visibility = ShaderVisibility::All; }; +using DescriptorType = llvm::dxil::ResourceClass; +// Models RootDescriptor : CBV | SRV | UAV, by collecting like parameters +struct RootDescriptor { + DescriptorType Type; +}; + // Models the end of a descriptor table and stores its visibility struct DescriptorTable { ShaderVisibility Visibility = ShaderVisibility::All; @@ -125,8 +131,8 @@ struct DescriptorTableClause { void dump(raw_ostream &OS) const; }; -/// Models RootElement : RootFlags | RootConstants | DescriptorTable -/// | DescriptorTableClause +/// Models RootElement : RootFlags | RootConstants | RootDescriptor +/// | DescriptorTable | DescriptorTableClause /// /// 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. @@ -140,8 +146,8 @@ struct DescriptorTableClause { /// 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, DescriptorTable, - DescriptorTableClause>; +using RootElement = std::variant<RootFlags, RootConstants, RootDescriptor, + DescriptorTable, DescriptorTableClause>; 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