[clang] [llvm] [HLSL][RootSignature] Metadata generation of RootFlags, RootConstants, RootDescriptors (PR #142010)
via cfe-commits
cfe-commits at lists.llvm.org
Thu May 29 11:41:19 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Finn Plummer (inbelic)
<details>
<summary>Changes</summary>
Implements metadata generation of a Root Signature from its in-memory representation.
This pr handles RootFlags, RootConstants and RootDescriptors.
The metadata follows the format described [here](https://github.com/llvm/wg-hlsl/blob/main/proposals/0002-root-signature-in-clang.md#metadata-schema).
- Implement `BuildRoot[Flags|Constants|Descriptors]` into `HLSLRootSignature.h`
- Add sample testcases demonstrating functionality
Note: there is no validation of metadata nodes as the `llvm::hlsl::rootsig::RootElement` that generates it will have already been validated.
First part of https://github.com/llvm/llvm-project/issues/126586.
---
Full diff: https://github.com/llvm/llvm-project/pull/142010.diff
3 Files Affected:
- (modified) clang/test/CodeGenHLSL/RootSignature.hlsl (+49-7)
- (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+3)
- (modified) llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp (+46)
``````````diff
diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl
index 60e0dec175b8f..85f47727ce91f 100644
--- a/clang/test/CodeGenHLSL/RootSignature.hlsl
+++ b/clang/test/CodeGenHLSL/RootSignature.hlsl
@@ -1,16 +1,17 @@
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s
-// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]}
+// CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]], ![[#DT_ENTRY:]],
+// CHECK-SAME: ![[#RF_ENTRY:]], ![[#RC_ENTRY:]], ![[#RD_ENTRY:]]}
-// CHECK: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#EMPTY:]]}
+// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]]}
// CHECK: ![[#EMPTY]] = !{}
[shader("compute"), RootSignature("")]
[numthreads(1,1,1)]
-void FirstEntry() {}
+void EmptyEntry() {}
-// CHECK: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#SECOND_RS:]]}
-// CHECK: ![[#SECOND_RS]] = !{![[#TABLE:]]}
+// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]]}
+// CHECK: ![[#DT_RS]] = !{![[#TABLE:]]}
// CHECK: ![[#TABLE]] = !{!"DescriptorTable", i32 0, ![[#CBV:]], ![[#SRV:]]}
// CHECK: ![[#CBV]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4}
// CHECK: ![[#SRV]] = !{!"SRV", i32 4, i32 42, i32 3, i32 32, i32 0}
@@ -22,10 +23,51 @@ void FirstEntry() {}
")"
[shader("compute"), RootSignature(SampleDescriptorTable)]
[numthreads(1,1,1)]
-void SecondEntry() {}
+void DescriptorTableEntry() {}
+
+// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]]}
+// CHECK: ![[#RF_RS]] = !{![[#ROOT_FLAGS:]]}
+// CHECK: ![[#ROOT_FLAGS]] = !{!"RootFlags", i32 2114}
+
+#define SampleRootFlags \
+ "RootFlags( " \
+ " Deny_Vertex_Shader_Root_Access | Allow_Stream_Output | " \
+ " sampler_heap_directly_indexed " \
+ ")"
+[shader("compute"), RootSignature(SampleRootFlags)]
+[numthreads(1,1,1)]
+void RootFlagsEntry() {}
+
+// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]]}
+// CHECK: ![[#RC_RS]] = !{![[#ROOT_CONSTANTS:]]}
+// CHECK: ![[#ROOT_CONSTANTS]] = !{!"RootConstants", i32 5, i32 1, i32 2, i32 1}
+
+#define SampleRootConstants \
+ "RootConstants(" \
+ " space = 2, " \
+ " visibility = Shader_Visibility_Pixel, " \
+ " b1, num32BitConstants = 1 " \
+ ")"
+[shader("compute"), RootSignature(SampleRootConstants)]
+[numthreads(1,1,1)]
+void RootConstantsEntry() {}
+
+// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]]}
+// CHECK: ![[#RD_RS]] = !{![[#ROOT_CBV:]], ![[#ROOT_UAV:]], ![[#ROOT_SRV:]]}
+// CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4}
+// CHECK: ![[#ROOT_UAV]] = !{!"RootUAV", i32 0, i32 0, i32 0, i32 2}
+// CHECK: ![[#ROOT_SRV]] = !{!"RootSRV", i32 0, i32 0, i32 0, i32 4}
+
+#define SampleRootDescriptors \
+ "CBV(b0), " \
+ "UAV(u0), " \
+ "SRV(t0)"
+[shader("compute"), RootSignature(SampleRootDescriptors)]
+[numthreads(1,1,1)]
+void RootDescriptorsEntry() {}
// Sanity test to ensure no root is added for this function as there is only
// two entries in !dx.roosignatures
[shader("compute")]
[numthreads(1,1,1)]
-void ThirdEntry() {}
+void NoRSEntry() {}
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index fd0abc9479469..d020dc413f0af 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -188,6 +188,9 @@ class MetadataBuilder {
private:
/// Define the various builders for the different metadata types
+ MDNode *BuildRootFlags(const RootFlags &Flags);
+ MDNode *BuildRootConstants(const RootConstants &Constants);
+ MDNode *BuildRootDescriptor(const RootDescriptor &Descriptor);
MDNode *BuildDescriptorTable(const DescriptorTable &Table);
MDNode *BuildDescriptorTableClause(const DescriptorTableClause &Clause);
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
index ec0d130a6767c..cd606e61fcebf 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -171,6 +171,12 @@ void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
MDNode *MetadataBuilder::BuildRootSignature() {
for (const RootElement &Element : Elements) {
MDNode *ElementMD = nullptr;
+ if (const auto &Flags = std::get_if<RootFlags>(&Element))
+ ElementMD = BuildRootFlags(*Flags);
+ if (const auto &Constants = std::get_if<RootConstants>(&Element))
+ ElementMD = BuildRootConstants(*Constants);
+ if (const auto &Descriptor = std::get_if<RootDescriptor>(&Element))
+ ElementMD = BuildRootDescriptor(*Descriptor);
if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
ElementMD = BuildDescriptorTableClause(*Clause);
if (const auto &Table = std::get_if<DescriptorTable>(&Element))
@@ -187,6 +193,46 @@ MDNode *MetadataBuilder::BuildRootSignature() {
return MDNode::get(Ctx, GeneratedMetadata);
}
+MDNode *MetadataBuilder::BuildRootFlags(const RootFlags &Flags) {
+ IRBuilder<> Builder(Ctx);
+ return MDNode::get(Ctx, {
+ MDString::get(Ctx, "RootFlags"),
+ ConstantAsMetadata::get(
+ Builder.getInt32(llvm::to_underlying(Flags))),
+ });
+}
+
+MDNode *MetadataBuilder::BuildRootConstants(const RootConstants &Constants) {
+ IRBuilder<> Builder(Ctx);
+ return MDNode::get(
+ Ctx, {
+ MDString::get(Ctx, "RootConstants"),
+ ConstantAsMetadata::get(
+ Builder.getInt32(llvm::to_underlying(Constants.Visibility))),
+ ConstantAsMetadata::get(Builder.getInt32(Constants.Reg.Number)),
+ ConstantAsMetadata::get(Builder.getInt32(Constants.Space)),
+ ConstantAsMetadata::get(Builder.getInt32(
+ Constants.Num32BitConstants)),
+ });
+}
+
+MDNode *MetadataBuilder::BuildRootDescriptor(const RootDescriptor &Descriptor) {
+ IRBuilder<> Builder(Ctx);
+ std::string Name;
+ llvm::raw_string_ostream OS(Name);
+ OS << "Root" << ClauseType(llvm::to_underlying(Descriptor.Type));
+ return MDNode::get(
+ Ctx, {
+ MDString::get(Ctx, OS.str()),
+ ConstantAsMetadata::get(
+ Builder.getInt32(llvm::to_underlying(Descriptor.Visibility))),
+ ConstantAsMetadata::get(Builder.getInt32(Descriptor.Reg.Number)),
+ ConstantAsMetadata::get(Builder.getInt32(Descriptor.Space)),
+ ConstantAsMetadata::get(
+ Builder.getInt32(llvm::to_underlying(Descriptor.Flags))),
+ });
+}
+
MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
IRBuilder<> Builder(Ctx);
SmallVector<Metadata *> TableOperands;
``````````
</details>
https://github.com/llvm/llvm-project/pull/142010
More information about the cfe-commits
mailing list