[clang] [llvm] [NFC][HLSL][RootSignature] Split up `HLSLRootSignatureUtils` (PR #146124)

Finn Plummer via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 3 17:41:59 PDT 2025


================
@@ -0,0 +1,194 @@
+//===- RootSignatureMetadata.h - HLSL Root Signature helpers --------------===//
+//
+// 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 implements a library for working with HLSL Root Signatures
+/// and their metadata representation.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/HLSL/RootSignatureMetadata.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+namespace llvm {
+namespace hlsl {
+namespace rootsig {
+
+static const EnumEntry<dxil::ResourceClass> ResourceClassNames[] = {
+    {"CBV", dxil::ResourceClass::CBuffer},
+    {"SRV", dxil::ResourceClass::SRV},
+    {"UAV", dxil::ResourceClass::UAV},
+    {"Sampler", dxil::ResourceClass::Sampler},
+};
+
+static std::optional<StringRef> getResourceName(dxil::ResourceClass Class) {
+  for (const auto &ClassEnum : ResourceClassNames)
+    if (ClassEnum.Value == Class)
+      return ClassEnum.Name;
+  return std::nullopt;
+}
+
+namespace {
+
+// We use the OverloadVisit with std::visit to ensure the compiler catches if a
+// new RootElement variant type is added but it's metadata generation isn't
+// handled.
+template <class... Ts> struct OverloadedVisit : Ts... {
+  using Ts::operator()...;
+};
+template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;
+
+} // namespace
+
+MDNode *MetadataBuilder::BuildRootSignature() {
+  const auto Visitor = OverloadedVisit{
+      [this](const dxbc::RootFlags &Flags) -> MDNode * {
+        return BuildRootFlags(Flags);
+      },
+      [this](const RootConstants &Constants) -> MDNode * {
+        return BuildRootConstants(Constants);
+      },
+      [this](const RootDescriptor &Descriptor) -> MDNode * {
+        return BuildRootDescriptor(Descriptor);
+      },
+      [this](const DescriptorTableClause &Clause) -> MDNode * {
+        return BuildDescriptorTableClause(Clause);
+      },
+      [this](const DescriptorTable &Table) -> MDNode * {
+        return BuildDescriptorTable(Table);
+      },
+      [this](const StaticSampler &Sampler) -> MDNode * {
+        return BuildStaticSampler(Sampler);
+      },
+  };
+
+  for (const RootElement &Element : Elements) {
+    MDNode *ElementMD = std::visit(Visitor, Element);
+    assert(ElementMD != nullptr &&
+           "Root Element must be initialized and validated");
+    GeneratedMetadata.push_back(ElementMD);
+  }
+
+  return MDNode::get(Ctx, GeneratedMetadata);
+}
+
+MDNode *MetadataBuilder::BuildRootFlags(const dxbc::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);
+  std::optional<StringRef> ResName = getResourceName(
+      dxil::ResourceClass(llvm::to_underlying(Descriptor.Type)));
+  assert(ResName && "Provided an invalid Resource Class");
+  llvm::SmallString<7> Name({"Root", *ResName});
----------------
inbelic wrote:

7 is sufficient, there are only three possible values of `ResName`: "CBV", "UAV" or "SRV"

https://github.com/llvm/llvm-project/pull/146124


More information about the llvm-commits mailing list