[llvm] 9cdd33d - [HLSL][RootSignature] Metadata generation of RootFlags, RootConstants, RootDescriptors (#142010)

via llvm-commits llvm-commits at lists.llvm.org
Fri May 30 16:52:23 PDT 2025


Author: Finn Plummer
Date: 2025-05-30T16:52:19-07:00
New Revision: 9cdd33db169d0ba9853f2c9538cb15ec4b506793

URL: https://github.com/llvm/llvm-project/commit/9cdd33db169d0ba9853f2c9538cb15ec4b506793
DIFF: https://github.com/llvm/llvm-project/commit/9cdd33db169d0ba9853f2c9538cb15ec4b506793.diff

LOG: [HLSL][RootSignature] Metadata generation of RootFlags, RootConstants, RootDescriptors (#142010)

Implements metadata generation of a Root Signature from its in-memory
representation. It follows the same style as:
https://github.com/llvm/llvm-project/pull/139633.

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.

Added: 
    

Modified: 
    clang/test/CodeGenHLSL/RootSignature.hlsl
    llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
    llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp

Removed: 
    


################################################################################
diff  --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl
index 60e0dec175b8f..34caa3eb6b714 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 42, i32 3, i32 2}
+// CHECK: ![[#ROOT_SRV]] = !{!"RootSRV", i32 4, i32 0, i32 0, i32 2}
+
+#define SampleRootDescriptors \
+  "CBV(b0), " \
+  "UAV(space = 3, u42), " \
+  "SRV(t0, visibility = Shader_Visibility_Geometry, flags = Data_Volatile)"
+[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 7c8ddef4144e6..cbecf37d01f0d 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -230,6 +230,9 @@ class MetadataBuilder {
 
 private:
   /// Define the various builders for the 
diff erent 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..b8d6e229006d0 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Frontend/HLSL/HLSLRootSignature.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Metadata.h"
@@ -171,9 +172,15 @@ void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
 MDNode *MetadataBuilder::BuildRootSignature() {
   for (const RootElement &Element : Elements) {
     MDNode *ElementMD = nullptr;
-    if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
+    if (const auto &Flags = std::get_if<RootFlags>(&Element))
+      ElementMD = BuildRootFlags(*Flags);
+    else if (const auto &Constants = std::get_if<RootConstants>(&Element))
+      ElementMD = BuildRootConstants(*Constants);
+    else if (const auto &Descriptor = std::get_if<RootDescriptor>(&Element))
+      ElementMD = BuildRootDescriptor(*Descriptor);
+    else if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
       ElementMD = BuildDescriptorTableClause(*Clause);
-    if (const auto &Table = std::get_if<DescriptorTable>(&Element))
+    else if (const auto &Table = std::get_if<DescriptorTable>(&Element))
       ElementMD = BuildDescriptorTable(*Table);
 
     // FIXME(#126586): remove once all RootElemnt variants are handled in a
@@ -187,6 +194,46 @@ MDNode *MetadataBuilder::BuildRootSignature() {
   return MDNode::get(Ctx, GeneratedMetadata);
 }
 
+MDNode *MetadataBuilder::BuildRootFlags(const RootFlags &Flags) {
+  IRBuilder<> Builder(Ctx);
+  Metadata *Operands[] = {
+      MDString::get(Ctx, "RootFlags"),
+      ConstantAsMetadata::get(Builder.getInt32(llvm::to_underlying(Flags))),
+  };
+  return MDNode::get(Ctx, Operands);
+}
+
+MDNode *MetadataBuilder::BuildRootConstants(const RootConstants &Constants) {
+  IRBuilder<> Builder(Ctx);
+  Metadata *Operands[] = {
+      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)),
+  };
+  return MDNode::get(Ctx, Operands);
+}
+
+MDNode *MetadataBuilder::BuildRootDescriptor(const RootDescriptor &Descriptor) {
+  IRBuilder<> Builder(Ctx);
+  llvm::SmallString<7> Name;
+  llvm::raw_svector_ostream OS(Name);
+  OS << "Root" << ClauseType(llvm::to_underlying(Descriptor.Type));
+
+  Metadata *Operands[] = {
+      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))),
+  };
+  return MDNode::get(Ctx, Operands);
+}
+
 MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
   IRBuilder<> Builder(Ctx);
   SmallVector<Metadata *> TableOperands;


        


More information about the llvm-commits mailing list