[llvm] [HLSL][RootSignature] Implement serialized dump of Descriptor Tables (PR #138326)
via llvm-commits
llvm-commits at lists.llvm.org
Fri May 2 12:15:29 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-hlsl
Author: Finn Plummer (inbelic)
<details>
<summary>Changes</summary>
- defines the `dump` method for in-memory descriptor table data structs in `Frontend/HLSLRootSignature`
- creates unit test infrastructure to support unit tests of the dump methods
Resolves https://github.com/llvm/llvm-project/issues/138189
---
Full diff: https://github.com/llvm/llvm-project/pull/138326.diff
5 Files Affected:
- (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+7)
- (modified) llvm/lib/Frontend/HLSL/CMakeLists.txt (+1)
- (added) llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp (+154)
- (modified) llvm/unittests/Frontend/CMakeLists.txt (+2)
- (added) llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp (+111)
``````````diff
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index 818caccfe1998..6d3ecd166f461 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -15,6 +15,7 @@
#define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
#include "llvm/Support/DXILABI.h"
+#include "llvm/Support/raw_ostream.h"
#include <variant>
namespace llvm {
@@ -52,12 +53,16 @@ enum class RegisterType { BReg, TReg, UReg, SReg };
struct Register {
RegisterType ViewType;
uint32_t Number;
+
+ void dump(raw_ostream &OS) const;
};
// Models the end of a descriptor table and stores its visibility
struct DescriptorTable {
ShaderVisibility Visibility = ShaderVisibility::All;
uint32_t NumClauses = 0; // The number of clauses in the table
+
+ void dump(raw_ostream &OS) const;
};
static const uint32_t NumDescriptorsUnbounded = 0xffffffff;
@@ -86,6 +91,8 @@ struct DescriptorTableClause {
break;
}
}
+
+ void dump(raw_ostream &OS) const;
};
// Models RootElement : DescriptorTable | DescriptorTableClause
diff --git a/llvm/lib/Frontend/HLSL/CMakeLists.txt b/llvm/lib/Frontend/HLSL/CMakeLists.txt
index 07a0c845ceef6..dd987544fe80b 100644
--- a/llvm/lib/Frontend/HLSL/CMakeLists.txt
+++ b/llvm/lib/Frontend/HLSL/CMakeLists.txt
@@ -1,6 +1,7 @@
add_llvm_component_library(LLVMFrontendHLSL
CBuffer.cpp
HLSLResource.cpp
+ HLSLRootSignature.cpp
ADDITIONAL_HEADER_DIRS
${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
new file mode 100644
index 0000000000000..a5f0313138521
--- /dev/null
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -0,0 +1,154 @@
+//===- HLSLRootSignature.cpp - HLSL Root Signature helper objects ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This file contains helpers for working with HLSL Root Signatures.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
+#include "llvm/ADT/bit.h"
+
+namespace llvm {
+namespace hlsl {
+namespace rootsig {
+
+static void dumpRegType(raw_ostream &OS, RegisterType Type) {
+ switch (Type) {
+ case RegisterType::BReg:
+ OS << "b";
+ break;
+ case RegisterType::TReg:
+ OS << "t";
+ break;
+ case RegisterType::UReg:
+ OS << "u";
+ break;
+ case RegisterType::SReg:
+ OS << "s";
+ break;
+ }
+}
+
+void Register::dump(raw_ostream &OS) const {
+ dumpRegType(OS, ViewType);
+ OS << Number;
+}
+
+static void dumpVisibility(raw_ostream &OS, ShaderVisibility Visibility) {
+ switch (Visibility) {
+ case ShaderVisibility::All:
+ OS << "All";
+ break;
+ case ShaderVisibility::Vertex:
+ OS << "Vertex";
+ break;
+ case ShaderVisibility::Hull:
+ OS << "Hull";
+ break;
+ case ShaderVisibility::Domain:
+ OS << "Domain";
+ break;
+ case ShaderVisibility::Geometry:
+ OS << "Geometry";
+ break;
+ case ShaderVisibility::Pixel:
+ OS << "Pixel";
+ break;
+ case ShaderVisibility::Amplification:
+ OS << "Amplification";
+ break;
+ case ShaderVisibility::Mesh:
+ OS << "Mesh";
+ break;
+ }
+}
+
+void DescriptorTable::dump(raw_ostream &OS) const {
+ OS << "DescriptorTable(numClauses = " << NumClauses;
+ OS << ", visibility = ";
+ dumpVisibility(OS, Visibility);
+ OS << ")";
+}
+
+static void dumpClauseType(raw_ostream &OS, ClauseType Type) {
+ switch (Type) {
+ case ClauseType::CBuffer:
+ OS << "CBV";
+ break;
+ case ClauseType::SRV:
+ OS << "SRV";
+ break;
+ case ClauseType::UAV:
+ OS << "UAV";
+ break;
+ case ClauseType::Sampler:
+ OS << "Sampler";
+ break;
+ }
+}
+
+static void dumpDescriptorRangeFlag(raw_ostream &OS, unsigned Bit) {
+ switch (static_cast<DescriptorRangeFlags>(Bit)) {
+ case DescriptorRangeFlags::DescriptorsVolatile:
+ OS << "DescriptorsVolatile";
+ break;
+ case DescriptorRangeFlags::DataVolatile:
+ OS << "DataVolatile";
+ break;
+ case DescriptorRangeFlags::DataStaticWhileSetAtExecute:
+ OS << "DataStaticWhileSetAtExecute";
+ break;
+ case DescriptorRangeFlags::DataStatic:
+ OS << "DataStatic";
+ break;
+ case DescriptorRangeFlags::DescriptorsStaticKeepingBufferBoundsChecks:
+ OS << "DescriptorsStaticKeepingBufferBoundsChecks";
+ break;
+ default:
+ OS << "invalid: " << Bit;
+ break;
+ }
+}
+
+static void dumpDescriptorRangeFlags(raw_ostream &OS,
+ DescriptorRangeFlags Flags) {
+ bool FlagSet = false;
+ unsigned Remaining = llvm::to_underlying(Flags);
+ while (Remaining) {
+ unsigned Bit = 1u << llvm::countr_zero(Remaining);
+ if (Remaining & Bit) {
+ if (FlagSet)
+ OS << " | ";
+ dumpDescriptorRangeFlag(OS, Bit);
+ FlagSet = true;
+ }
+ Remaining &= ~Bit;
+ }
+ if (!FlagSet)
+ OS << "None";
+}
+
+void DescriptorTableClause::dump(raw_ostream &OS) const {
+ dumpClauseType(OS, Type);
+ OS << "(";
+ Reg.dump(OS);
+ OS << ", numDescriptors = " << NumDescriptors;
+ OS << ", space = " << Space;
+ OS << ", offset = ";
+ if (Offset == DescriptorTableOffsetAppend)
+ OS << "DescriptorTableOffsetAppend";
+ else
+ OS << Offset;
+ OS << ", flags = ";
+ dumpDescriptorRangeFlags(OS, Flags);
+ OS << ")";
+}
+
+} // namespace rootsig
+} // namespace hlsl
+} // namespace llvm
diff --git a/llvm/unittests/Frontend/CMakeLists.txt b/llvm/unittests/Frontend/CMakeLists.txt
index 85e113816e3bc..2119642769e3d 100644
--- a/llvm/unittests/Frontend/CMakeLists.txt
+++ b/llvm/unittests/Frontend/CMakeLists.txt
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS
Analysis
Core
+ FrontendHLSL
FrontendOpenACC
FrontendOpenMP
Passes
@@ -10,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
)
add_llvm_unittest(LLVMFrontendTests
+ HLSLRootSignatureDumpTest.cpp
OpenACCTest.cpp
OpenMPContextTest.cpp
OpenMPIRBuilderTest.cpp
diff --git a/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
new file mode 100644
index 0000000000000..ba1fbfd1f8708
--- /dev/null
+++ b/llvm/unittests/Frontend/HLSLRootSignatureDumpTest.cpp
@@ -0,0 +1,111 @@
+//===-------- HLSLRootSignatureDumpTest.cpp - RootSignature dump tests ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::hlsl::rootsig;
+
+namespace {
+
+TEST(HLSLRootSignatureTest, DescriptorCBVClauseDump) {
+ DescriptorTableClause Clause;
+ Clause.Type = ClauseType::CBuffer;
+ Clause.Reg = {RegisterType::BReg, 0};
+ Clause.setDefaultFlags();
+
+ std::string Out;
+ llvm::raw_string_ostream OS(Out);
+ Clause.dump(OS);
+ OS.flush();
+
+ std::string Expected = "CBV(b0, numDescriptors = 1, space = 0, "
+ "offset = DescriptorTableOffsetAppend, "
+ "flags = DataStaticWhileSetAtExecute)";
+ EXPECT_EQ(Out, Expected);
+}
+
+TEST(HLSLRootSignatureTest, DescriptorSRVClauseDump) {
+ DescriptorTableClause Clause;
+ Clause.Type = ClauseType::SRV;
+ Clause.Reg = {RegisterType::TReg, 0};
+ Clause.NumDescriptors = 2;
+ Clause.Space = 42;
+ Clause.Offset = 3;
+ Clause.Flags = DescriptorRangeFlags::None;
+
+ std::string Out;
+ llvm::raw_string_ostream OS(Out);
+ Clause.dump(OS);
+ OS.flush();
+
+ std::string Expected =
+ "SRV(t0, numDescriptors = 2, space = 42, offset = 3, flags = None)";
+ EXPECT_EQ(Out, Expected);
+}
+
+TEST(HLSLRootSignatureTest, DescriptorUAVClauseDump) {
+ DescriptorTableClause Clause;
+ Clause.Type = ClauseType::UAV;
+ Clause.Reg = {RegisterType::UReg, 92374};
+ Clause.NumDescriptors = 3298;
+ Clause.Space = 932847;
+ Clause.Offset = 1;
+ Clause.Flags = DescriptorRangeFlags::ValidFlags;
+
+ std::string Out;
+ llvm::raw_string_ostream OS(Out);
+ Clause.dump(OS);
+ OS.flush();
+
+ std::string Expected =
+ "UAV(u92374, numDescriptors = 3298, space = 932847, offset = 1, flags = "
+ "DescriptorsVolatile | "
+ "DataVolatile | "
+ "DataStaticWhileSetAtExecute | "
+ "DataStatic | "
+ "DescriptorsStaticKeepingBufferBoundsChecks)";
+ EXPECT_EQ(Out, Expected);
+}
+
+TEST(HLSLRootSignatureTest, DescriptorSamplerClauseDump) {
+ DescriptorTableClause Clause;
+ Clause.Type = ClauseType::Sampler;
+ Clause.Reg = {RegisterType::SReg, 0};
+ Clause.NumDescriptors = 2;
+ Clause.Space = 42;
+ Clause.Offset = DescriptorTableOffsetAppend;
+ Clause.Flags = DescriptorRangeFlags::ValidSamplerFlags;
+
+ std::string Out;
+ llvm::raw_string_ostream OS(Out);
+ Clause.dump(OS);
+ OS.flush();
+
+ std::string Expected = "Sampler(s0, numDescriptors = 2, space = 42, offset = "
+ "DescriptorTableOffsetAppend, "
+ "flags = DescriptorsVolatile)";
+ EXPECT_EQ(Out, Expected);
+}
+
+TEST(HLSLRootSignatureTest, DescriptorTableDump) {
+ DescriptorTable Table;
+ Table.NumClauses = 4;
+ Table.Visibility = ShaderVisibility::Geometry;
+
+ std::string Out;
+ llvm::raw_string_ostream OS(Out);
+ Table.dump(OS);
+ OS.flush();
+
+ std::string Expected =
+ "DescriptorTable(numClauses = 4, visibility = Geometry)";
+ EXPECT_EQ(Out, Expected);
+}
+
+} // namespace
``````````
</details>
https://github.com/llvm/llvm-project/pull/138326
More information about the llvm-commits
mailing list