https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/125131
>From abe7e6703a008608e19ce3f9bdcbd1b613fab60d Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 29 Jan 2025 19:40:08 +0000 Subject: [PATCH 1/7] add basic empty root signature --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 21 +++++++++++++++++++++ clang/test/CodeGenHLSL/RootSignature.hlsl | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 clang/test/CodeGenHLSL/RootSignature.hlsl diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index c354e58e15f4b..ff608323e9ac3 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -119,6 +119,20 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) { return CBGV; } +void addRootSignature(llvm::Function *Fn, llvm::Module &M) { + auto &Ctx = M.getContext(); + IRBuilder<> B(M.getContext()); + + MDNode *ExampleRootSignature = MDNode::get(Ctx, {}); + + MDNode *ExamplePairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), + ExampleRootSignature}); + + StringRef RootSignatureValKey = "dx.rootsignatures"; + auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey); + RootSignatureValMD->addOperand(ExamplePairing); +} + } // namespace llvm::Type *CGHLSLRuntime::convertHLSLSpecificType(const Type *T) { @@ -453,6 +467,13 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, // FIXME: Handle codegen for return type semantics. // See: https://github.com/llvm/llvm-project/issues/57875 B.CreateRetVoid(); + + // Add and identify root signature to function, if applicable + const AttrVec &Attrs = FD->getAttrs(); + for (const Attr *Attr : Attrs) { + if (isa<HLSLRootSignatureAttr>(Attr)) + addRootSignature(EntryFn, M); + } } void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD, diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl new file mode 100644 index 0000000000000..1ea9ab7aaa2c3 --- /dev/null +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s + +// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]} +// CHECK-DAG: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#RS:]]} +// CHECK-DAG: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#RS:]]} +// CHECK-DAG: ![[#RS]] = !{} + +[shader("compute"), RootSignature("")] +[numthreads(1,1,1)] +void FirstEntry() {} + +[shader("compute"), RootSignature("DescriptorTable()")] +[numthreads(1,1,1)] +void SecondEntry() {} + +// Sanity test to ensure to root is added for this function +[shader("compute")] +[numthreads(1,1,1)] +void ThirdEntry() {} >From 671f099d3d58995677c47b4226481b72295e525d Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 29 Jan 2025 19:57:48 +0000 Subject: [PATCH 2/7] pass down the actual root elements - test that we have the correct number of elements --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 17 ++++++++++++----- clang/test/CodeGenHLSL/RootSignature.hlsl | 9 +++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index ff608323e9ac3..4c9adcd8a9053 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -119,11 +119,18 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) { return CBGV; } -void addRootSignature(llvm::Function *Fn, llvm::Module &M) { +void addRootSignature( + ArrayRef<llvm::hlsl::root_signature::RootElement> Elements, + llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); - IRBuilder<> B(M.getContext()); - MDNode *ExampleRootSignature = MDNode::get(Ctx, {}); + SmallVector<Metadata *> GeneratedMetadata; + for (auto Element : Elements) { + MDNode *ExampleRootElement = MDNode::get(Ctx, {}); + GeneratedMetadata.push_back(ExampleRootElement); + } + + MDNode *ExampleRootSignature = MDNode::get(Ctx, GeneratedMetadata); MDNode *ExamplePairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), ExampleRootSignature}); @@ -471,8 +478,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, // Add and identify root signature to function, if applicable const AttrVec &Attrs = FD->getAttrs(); for (const Attr *Attr : Attrs) { - if (isa<HLSLRootSignatureAttr>(Attr)) - addRootSignature(EntryFn, M); + if (const auto *RSAttr = dyn_cast<HLSLRootSignatureAttr>(Attr)) + addRootSignature(RSAttr->getElements(), EntryFn, M); } } diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 1ea9ab7aaa2c3..63c0505e224f0 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -1,9 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s -// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]} -// CHECK-DAG: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#RS:]]} -// CHECK-DAG: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#RS:]]} -// CHECK-DAG: ![[#RS]] = !{} +// CHECK-DAG: ![[#EMPTY:]] = !{} +// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#EMPTY]]} +// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]} +// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]} +// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]} [shader("compute"), RootSignature("")] [numthreads(1,1,1)] >From d02cb5562f9ee18c529546f298fe6c0b054d97e4 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 29 Jan 2025 22:50:13 +0000 Subject: [PATCH 3/7] introduce a MetadataBuilder to handle the construction of nodes --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 16 ++-- clang/test/CodeGenHLSL/RootSignature.hlsl | 17 ++-- .../llvm/Frontend/HLSL/HLSLRootSignature.h | 24 ++++++ llvm/lib/Frontend/HLSL/CMakeLists.txt | 1 + llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 77 +++++++++++++++++++ 5 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 4c9adcd8a9053..168bda18eb720 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -124,20 +124,14 @@ void addRootSignature( llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); - SmallVector<Metadata *> GeneratedMetadata; - for (auto Element : Elements) { - MDNode *ExampleRootElement = MDNode::get(Ctx, {}); - GeneratedMetadata.push_back(ExampleRootElement); - } - - MDNode *ExampleRootSignature = MDNode::get(Ctx, GeneratedMetadata); - - MDNode *ExamplePairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), - ExampleRootSignature}); + llvm::hlsl::root_signature::MetadataBuilder Builder(Ctx, Elements); + MDNode *RootSignature = Builder.BuildRootSignature(); + MDNode *FnPairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), + RootSignature}); StringRef RootSignatureValKey = "dx.rootsignatures"; auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey); - RootSignatureValMD->addOperand(ExamplePairing); + RootSignatureValMD->addOperand(FnPairing); } } // namespace diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 63c0505e224f0..659631133ad9b 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-DAG: ![[#EMPTY:]] = !{} -// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#EMPTY]]} -// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]} -// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]} -// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]} - [shader("compute"), RootSignature("")] [numthreads(1,1,1)] void FirstEntry() {} -[shader("compute"), RootSignature("DescriptorTable()")] +// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable"} +// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]} + +#define SampleDescriptorTable \ + "DescriptorTable( " \ + ")" +[shader("compute"), RootSignature(SampleDescriptorTable)] [numthreads(1,1,1)] void SecondEntry() {} @@ -18,3 +19,7 @@ void SecondEntry() {} [shader("compute")] [numthreads(1,1,1)] void ThirdEntry() {} + +// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]} +// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]} +// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]} diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index f999a0b5eef33..30c45c7c8a5b9 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -14,10 +14,16 @@ #ifndef LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H #define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/Support/DXILABI.h" #include <variant> namespace llvm { +class LLVMContext; +class MDNode; +class Metadata; + namespace hlsl { namespace rootsig { @@ -122,6 +128,24 @@ using RootElement = std::variant<DescriptorTable, DescriptorTableClause>; using ParamType = std::variant<uint32_t *, DescriptorRangeOffset *, DescriptorRangeFlags *, ShaderVisibility *>; +class MetadataBuilder { + public: + MetadataBuilder(llvm::LLVMContext &Ctx, ArrayRef<RootElement> Elements) + : Ctx(Ctx), Elements(Elements) {} + + // Iterates through the elements and builds the respective nodes + MDNode *BuildRootSignature(); + + private: + // Define the various builders for the different metadata types + MDNode *BuildDescriptorTable(const DescriptorTable &Table); + MDNode *BuildDescriptorTableClause(const DescriptorTableClause &Clause); + + llvm::LLVMContext &Ctx; + ArrayRef<RootElement> Elements; + SmallVector<Metadata *> GeneratedMetadata; +}; + } // namespace rootsig } // namespace hlsl } // namespace llvm diff --git a/llvm/lib/Frontend/HLSL/CMakeLists.txt b/llvm/lib/Frontend/HLSL/CMakeLists.txt index eda6cb8e69a49..739bfef8dbc37 100644 --- a/llvm/lib/Frontend/HLSL/CMakeLists.txt +++ b/llvm/lib/Frontend/HLSL/CMakeLists.txt @@ -1,5 +1,6 @@ add_llvm_component_library(LLVMFrontendHLSL 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..91df8ab639972 --- /dev/null +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -0,0 +1,77 @@ +//===- 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/IR/IRBuilder.h" +#include "llvm/IR/Metadata.h" +#include "llvm/IR/Module.h" + +namespace llvm { +namespace hlsl { +namespace root_signature { + +static MDString *ClauseTypeToName(LLVMContext &Ctx, ClauseType Type) { + StringRef Name; + switch (Type) { + case ClauseType::CBuffer: + Name = "CBV"; + break; + case ClauseType::SRV: + Name = "SRV"; + break; + case ClauseType::UAV: + Name = "UAV"; + break; + case ClauseType::Sampler: + Name = "Sampler"; + break; + } + return MDString::get(Ctx, Name); +} + +// Helper struct so that we can use the overloaded notation of std::visit +template <class... Ts> struct OverloadBuilds : Ts... { + using Ts::operator()...; +}; +template <class... Ts> OverloadBuilds(Ts...) -> OverloadBuilds<Ts...>; + +MDNode *MetadataBuilder::BuildRootSignature() { + for (const RootElement &Element : Elements) { + MDNode *ElementMD = + std::visit( + OverloadBuilds{ + [&](DescriptorTable Table) -> MDNode * { + return BuildDescriptorTable(Table); + }, + [&](DescriptorTableClause Clause) -> MDNode * { + return BuildDescriptorTableClause(Clause); + }, + }, + Element); + GeneratedMetadata.push_back(ElementMD); + } + + return MDNode::get(Ctx, GeneratedMetadata); +} + +MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { + return MDNode::get(Ctx, {MDString::get(Ctx, "DescriptorTable")}); +} + +MDNode *MetadataBuilder::BuildDescriptorTableClause(const DescriptorTableClause &Clause) { + return MDNode::get(Ctx, {ClauseTypeToName(Ctx, Clause.Type)}); +} + +} // namespace root_signature +} // namespace hlsl +} // namespace llvm + >From 28c6dfa85fc881083acdd489af5544bc1ca2bf5e Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 30 Jan 2025 22:45:58 +0000 Subject: [PATCH 4/7] add support for DescriptorTableClauses --- clang/test/CodeGenHLSL/RootSignature.hlsl | 2 ++ llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 10 +++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 659631133ad9b..da8f2e5e24df1 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -5,11 +5,13 @@ [numthreads(1,1,1)] void FirstEntry() {} +// CHECK-DAG: ![[#CBV:]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} // CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable"} // CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]} #define SampleDescriptorTable \ "DescriptorTable( " \ + " CBV(b0) " \ ")" [shader("compute"), RootSignature(SampleDescriptorTable)] [numthreads(1,1,1)] diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 91df8ab639972..0dbb3f0410a88 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -68,7 +68,15 @@ MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { } MDNode *MetadataBuilder::BuildDescriptorTableClause(const DescriptorTableClause &Clause) { - return MDNode::get(Ctx, {ClauseTypeToName(Ctx, Clause.Type)}); + IRBuilder<> B(Ctx); + return MDNode::get(Ctx, { + ClauseTypeToName(Ctx, Clause.Type), + ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)), + ConstantAsMetadata::get(B.getInt32(Clause.Register.Number)), + ConstantAsMetadata::get(B.getInt32(Clause.Space)), + ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Clause.Offset))), + ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Clause.Flags))), + }); } } // namespace root_signature >From 9bdf703443cb975c5b88f9a43e9bfd3c7d77491b Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 30 Jan 2025 22:51:42 +0000 Subject: [PATCH 5/7] add support for associating DescriptorTables with their clauses --- clang/test/CodeGenHLSL/RootSignature.hlsl | 6 ++++-- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index da8f2e5e24df1..2bbf4bf09093e 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -6,12 +6,14 @@ void FirstEntry() {} // CHECK-DAG: ![[#CBV:]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} -// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable"} +// CHECK-DAG: ![[#SRV:]] = !{!"SRV", i32 4, i32 42, i32 3, i32 32, i32 0} +// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable", i32 0, ![[#CBV]], ![[#SRV]]} // CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]} #define SampleDescriptorTable \ "DescriptorTable( " \ - " CBV(b0) " \ + " CBV(b0), " \ + " SRV(t42, space = 3, offset = 32, numDescriptors = 4, flags = 0) " \ ")" [shader("compute"), RootSignature(SampleDescriptorTable)] [numthreads(1,1,1)] diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 0dbb3f0410a88..0e88046a83444 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -64,7 +64,16 @@ MDNode *MetadataBuilder::BuildRootSignature() { } MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { - return MDNode::get(Ctx, {MDString::get(Ctx, "DescriptorTable")}); + IRBuilder<> B(Ctx); + SmallVector<Metadata *> TableOperands; + TableOperands.push_back(MDString::get(Ctx, "DescriptorTable")); + TableOperands.push_back(ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Table.Visibility)))); + + assert(Table.NumClauses <= GeneratedMetadata.size() && "Table expected all owned clauses to be generated already"); + TableOperands.append(GeneratedMetadata.end() - Table.NumClauses, GeneratedMetadata.end()); + GeneratedMetadata.pop_back_n(Table.NumClauses); + + return MDNode::get(Ctx, TableOperands); } MDNode *MetadataBuilder::BuildDescriptorTableClause(const DescriptorTableClause &Clause) { >From 05e7c0fc6f8618f31d732d166ba3cb1d8b5f4cf2 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 30 Jan 2025 23:14:00 +0000 Subject: [PATCH 6/7] self-review: misc clean up --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 14 ++-- clang/test/CodeGenHLSL/RootSignature.hlsl | 2 +- .../llvm/Frontend/HLSL/HLSLRootSignature.h | 13 ++-- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 66 +++++++++++-------- 4 files changed, 55 insertions(+), 40 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 168bda18eb720..62d062be91046 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -119,15 +119,14 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) { return CBGV; } -void addRootSignature( - ArrayRef<llvm::hlsl::root_signature::RootElement> Elements, - llvm::Function *Fn, llvm::Module &M) { +void addRootSignature(ArrayRef<llvm::hlsl::rootsig::RootElement> Elements, + llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); - llvm::hlsl::root_signature::MetadataBuilder Builder(Ctx, Elements); + llvm::hlsl::rootsig::MetadataBuilder Builder(Ctx, Elements); MDNode *RootSignature = Builder.BuildRootSignature(); - MDNode *FnPairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), - RootSignature}); + MDNode *FnPairing = + MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature}); StringRef RootSignatureValKey = "dx.rootsignatures"; auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey); @@ -471,10 +470,9 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, // Add and identify root signature to function, if applicable const AttrVec &Attrs = FD->getAttrs(); - for (const Attr *Attr : Attrs) { + for (const Attr *Attr : Attrs) if (const auto *RSAttr = dyn_cast<HLSLRootSignatureAttr>(Attr)) addRootSignature(RSAttr->getElements(), EntryFn, M); - } } void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD, diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 2bbf4bf09093e..76aa2690b96a7 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -19,7 +19,7 @@ void FirstEntry() {} [numthreads(1,1,1)] void SecondEntry() {} -// Sanity test to ensure to root is added for this function +// Sanity test to ensure no root is added for this function [shader("compute")] [numthreads(1,1,1)] void ThirdEntry() {} diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 30c45c7c8a5b9..d1c39b720d213 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -129,15 +129,18 @@ using ParamType = std::variant<uint32_t *, DescriptorRangeOffset *, DescriptorRangeFlags *, ShaderVisibility *>; class MetadataBuilder { - public: +public: MetadataBuilder(llvm::LLVMContext &Ctx, ArrayRef<RootElement> Elements) - : Ctx(Ctx), Elements(Elements) {} + : Ctx(Ctx), Elements(Elements) {} - // Iterates through the elements and builds the respective nodes + /// Iterates through the elements and dispatches onto the correct Build method + /// + /// Accumulates the root signature and returns the Metadata node that is just + /// a list of all the elements MDNode *BuildRootSignature(); - private: - // Define the various builders for the different metadata types +private: + /// Define the various builders for the different metadata types 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 0e88046a83444..fb1a2ddc72640 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -1,4 +1,5 @@ -//===- HLSLRootSignature.cpp - HLSL Root Signature helper objects ----------===// +//===- 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. @@ -17,7 +18,9 @@ namespace llvm { namespace hlsl { -namespace root_signature { +namespace rootsig { + +// Static helper functions static MDString *ClauseTypeToName(LLVMContext &Ctx, ClauseType Type) { StringRef Name; @@ -47,16 +50,15 @@ template <class... Ts> OverloadBuilds(Ts...) -> OverloadBuilds<Ts...>; MDNode *MetadataBuilder::BuildRootSignature() { for (const RootElement &Element : Elements) { MDNode *ElementMD = - std::visit( - OverloadBuilds{ - [&](DescriptorTable Table) -> MDNode * { - return BuildDescriptorTable(Table); - }, - [&](DescriptorTableClause Clause) -> MDNode * { - return BuildDescriptorTableClause(Clause); - }, - }, - Element); + std::visit(OverloadBuilds{ + [&](DescriptorTable Table) -> MDNode * { + return BuildDescriptorTable(Table); + }, + [&](DescriptorTableClause Clause) -> MDNode * { + return BuildDescriptorTableClause(Clause); + }, + }, + Element); GeneratedMetadata.push_back(ElementMD); } @@ -66,29 +68,41 @@ MDNode *MetadataBuilder::BuildRootSignature() { MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { IRBuilder<> B(Ctx); SmallVector<Metadata *> TableOperands; + // Set the mandatory arguments TableOperands.push_back(MDString::get(Ctx, "DescriptorTable")); - TableOperands.push_back(ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Table.Visibility)))); + TableOperands.push_back(ConstantAsMetadata::get( + B.getInt32(llvm::to_underlying(Table.Visibility)))); - assert(Table.NumClauses <= GeneratedMetadata.size() && "Table expected all owned clauses to be generated already"); - TableOperands.append(GeneratedMetadata.end() - Table.NumClauses, GeneratedMetadata.end()); + // Remaining operands are references to the table's clauses. The in-memory + // representation of the Root Elements created from parsing will ensure that + // the previous N elements are the clauses for this table. + assert(Table.NumClauses <= GeneratedMetadata.size() && + "Table expected all owned clauses to be generated already"); + // So, add a refence to each clause to our operands + TableOperands.append(GeneratedMetadata.end() - Table.NumClauses, + GeneratedMetadata.end()); + // Then, remove those clauses from the general list of Root Elements GeneratedMetadata.pop_back_n(Table.NumClauses); return MDNode::get(Ctx, TableOperands); } -MDNode *MetadataBuilder::BuildDescriptorTableClause(const DescriptorTableClause &Clause) { +MDNode *MetadataBuilder::BuildDescriptorTableClause( + const DescriptorTableClause &Clause) { IRBuilder<> B(Ctx); - return MDNode::get(Ctx, { - ClauseTypeToName(Ctx, Clause.Type), - ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)), - ConstantAsMetadata::get(B.getInt32(Clause.Register.Number)), - ConstantAsMetadata::get(B.getInt32(Clause.Space)), - ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Clause.Offset))), - ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Clause.Flags))), - }); + return MDNode::get( + Ctx, { + ClauseTypeToName(Ctx, Clause.Type), + ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)), + ConstantAsMetadata::get(B.getInt32(Clause.Register.Number)), + ConstantAsMetadata::get(B.getInt32(Clause.Space)), + ConstantAsMetadata::get( + B.getInt32(llvm::to_underlying(Clause.Offset))), + ConstantAsMetadata::get( + B.getInt32(llvm::to_underlying(Clause.Flags))), + }); } -} // namespace root_signature +} // namespace rootsig } // namespace hlsl } // namespace llvm - >From e96c6d7843963461f176118c0563c01661aceea7 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 5 Mar 2025 17:56:51 +0000 Subject: [PATCH 7/7] review: remove use of CHECK-DAG --- clang/test/CodeGenHLSL/RootSignature.hlsl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 76aa2690b96a7..60e0dec175b8f 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -1,14 +1,19 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s -// CHECK-DAG: ![[#EMPTY:]] = !{} +// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]} + +// CHECK: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#EMPTY:]]} +// CHECK: ![[#EMPTY]] = !{} + [shader("compute"), RootSignature("")] [numthreads(1,1,1)] void FirstEntry() {} -// CHECK-DAG: ![[#CBV:]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} -// CHECK-DAG: ![[#SRV:]] = !{!"SRV", i32 4, i32 42, i32 3, i32 32, i32 0} -// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable", i32 0, ![[#CBV]], ![[#SRV]]} -// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]} +// CHECK: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#SECOND_RS:]]} +// CHECK: ![[#SECOND_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} #define SampleDescriptorTable \ "DescriptorTable( " \ @@ -19,11 +24,8 @@ void FirstEntry() {} [numthreads(1,1,1)] void SecondEntry() {} -// Sanity test to ensure no root is added for this function +// 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() {} - -// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]} -// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]} -// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]} _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits