Skip to content

Commit 9cdd33d

Browse files
authored
[HLSL][RootSignature] Metadata generation of RootFlags, RootConstants, RootDescriptors (llvm#142010)
Implements metadata generation of a Root Signature from its in-memory representation. It follows the same style as: llvm#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 llvm#126586.
1 parent 1d338a0 commit 9cdd33d

File tree

3 files changed

+101
-9
lines changed

3 files changed

+101
-9
lines changed
Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s
22

3-
// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]}
3+
// CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]], ![[#DT_ENTRY:]],
4+
// CHECK-SAME: ![[#RF_ENTRY:]], ![[#RC_ENTRY:]], ![[#RD_ENTRY:]]}
45

5-
// CHECK: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#EMPTY:]]}
6+
// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]]}
67
// CHECK: ![[#EMPTY]] = !{}
78

89
[shader("compute"), RootSignature("")]
910
[numthreads(1,1,1)]
10-
void FirstEntry() {}
11+
void EmptyEntry() {}
1112

12-
// CHECK: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#SECOND_RS:]]}
13-
// CHECK: ![[#SECOND_RS]] = !{![[#TABLE:]]}
13+
// CHECK: ![[#DT_ENTRY]] = !{ptr @DescriptorTableEntry, ![[#DT_RS:]]}
14+
// CHECK: ![[#DT_RS]] = !{![[#TABLE:]]}
1415
// CHECK: ![[#TABLE]] = !{!"DescriptorTable", i32 0, ![[#CBV:]], ![[#SRV:]]}
1516
// CHECK: ![[#CBV]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4}
1617
// CHECK: ![[#SRV]] = !{!"SRV", i32 4, i32 42, i32 3, i32 32, i32 0}
@@ -22,10 +23,51 @@ void FirstEntry() {}
2223
")"
2324
[shader("compute"), RootSignature(SampleDescriptorTable)]
2425
[numthreads(1,1,1)]
25-
void SecondEntry() {}
26+
void DescriptorTableEntry() {}
27+
28+
// CHECK: ![[#RF_ENTRY]] = !{ptr @RootFlagsEntry, ![[#RF_RS:]]}
29+
// CHECK: ![[#RF_RS]] = !{![[#ROOT_FLAGS:]]}
30+
// CHECK: ![[#ROOT_FLAGS]] = !{!"RootFlags", i32 2114}
31+
32+
#define SampleRootFlags \
33+
"RootFlags( " \
34+
" Deny_Vertex_Shader_Root_Access | Allow_Stream_Output | " \
35+
" sampler_heap_directly_indexed " \
36+
")"
37+
[shader("compute"), RootSignature(SampleRootFlags)]
38+
[numthreads(1,1,1)]
39+
void RootFlagsEntry() {}
40+
41+
// CHECK: ![[#RC_ENTRY]] = !{ptr @RootConstantsEntry, ![[#RC_RS:]]}
42+
// CHECK: ![[#RC_RS]] = !{![[#ROOT_CONSTANTS:]]}
43+
// CHECK: ![[#ROOT_CONSTANTS]] = !{!"RootConstants", i32 5, i32 1, i32 2, i32 1}
44+
45+
#define SampleRootConstants \
46+
"RootConstants(" \
47+
" space = 2, " \
48+
" visibility = Shader_Visibility_Pixel, " \
49+
" b1, num32BitConstants = 1 " \
50+
")"
51+
[shader("compute"), RootSignature(SampleRootConstants)]
52+
[numthreads(1,1,1)]
53+
void RootConstantsEntry() {}
54+
55+
// CHECK: ![[#RD_ENTRY]] = !{ptr @RootDescriptorsEntry, ![[#RD_RS:]]}
56+
// CHECK: ![[#RD_RS]] = !{![[#ROOT_CBV:]], ![[#ROOT_UAV:]], ![[#ROOT_SRV:]]}
57+
// CHECK: ![[#ROOT_CBV]] = !{!"RootCBV", i32 0, i32 0, i32 0, i32 4}
58+
// CHECK: ![[#ROOT_UAV]] = !{!"RootUAV", i32 0, i32 42, i32 3, i32 2}
59+
// CHECK: ![[#ROOT_SRV]] = !{!"RootSRV", i32 4, i32 0, i32 0, i32 2}
60+
61+
#define SampleRootDescriptors \
62+
"CBV(b0), " \
63+
"UAV(space = 3, u42), " \
64+
"SRV(t0, visibility = Shader_Visibility_Geometry, flags = Data_Volatile)"
65+
[shader("compute"), RootSignature(SampleRootDescriptors)]
66+
[numthreads(1,1,1)]
67+
void RootDescriptorsEntry() {}
2668

2769
// Sanity test to ensure no root is added for this function as there is only
2870
// two entries in !dx.roosignatures
2971
[shader("compute")]
3072
[numthreads(1,1,1)]
31-
void ThirdEntry() {}
73+
void NoRSEntry() {}

llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@ class MetadataBuilder {
230230

231231
private:
232232
/// Define the various builders for the different metadata types
233+
MDNode *BuildRootFlags(const RootFlags &Flags);
234+
MDNode *BuildRootConstants(const RootConstants &Constants);
235+
MDNode *BuildRootDescriptor(const RootDescriptor &Descriptor);
233236
MDNode *BuildDescriptorTable(const DescriptorTable &Table);
234237
MDNode *BuildDescriptorTableClause(const DescriptorTableClause &Clause);
235238

llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
14+
#include "llvm/ADT/SmallString.h"
1415
#include "llvm/ADT/bit.h"
1516
#include "llvm/IR/IRBuilder.h"
1617
#include "llvm/IR/Metadata.h"
@@ -171,9 +172,15 @@ void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
171172
MDNode *MetadataBuilder::BuildRootSignature() {
172173
for (const RootElement &Element : Elements) {
173174
MDNode *ElementMD = nullptr;
174-
if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
175+
if (const auto &Flags = std::get_if<RootFlags>(&Element))
176+
ElementMD = BuildRootFlags(*Flags);
177+
else if (const auto &Constants = std::get_if<RootConstants>(&Element))
178+
ElementMD = BuildRootConstants(*Constants);
179+
else if (const auto &Descriptor = std::get_if<RootDescriptor>(&Element))
180+
ElementMD = BuildRootDescriptor(*Descriptor);
181+
else if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
175182
ElementMD = BuildDescriptorTableClause(*Clause);
176-
if (const auto &Table = std::get_if<DescriptorTable>(&Element))
183+
else if (const auto &Table = std::get_if<DescriptorTable>(&Element))
177184
ElementMD = BuildDescriptorTable(*Table);
178185

179186
// FIXME(#126586): remove once all RootElemnt variants are handled in a
@@ -187,6 +194,46 @@ MDNode *MetadataBuilder::BuildRootSignature() {
187194
return MDNode::get(Ctx, GeneratedMetadata);
188195
}
189196

197+
MDNode *MetadataBuilder::BuildRootFlags(const RootFlags &Flags) {
198+
IRBuilder<> Builder(Ctx);
199+
Metadata *Operands[] = {
200+
MDString::get(Ctx, "RootFlags"),
201+
ConstantAsMetadata::get(Builder.getInt32(llvm::to_underlying(Flags))),
202+
};
203+
return MDNode::get(Ctx, Operands);
204+
}
205+
206+
MDNode *MetadataBuilder::BuildRootConstants(const RootConstants &Constants) {
207+
IRBuilder<> Builder(Ctx);
208+
Metadata *Operands[] = {
209+
MDString::get(Ctx, "RootConstants"),
210+
ConstantAsMetadata::get(
211+
Builder.getInt32(llvm::to_underlying(Constants.Visibility))),
212+
ConstantAsMetadata::get(Builder.getInt32(Constants.Reg.Number)),
213+
ConstantAsMetadata::get(Builder.getInt32(Constants.Space)),
214+
ConstantAsMetadata::get(Builder.getInt32(Constants.Num32BitConstants)),
215+
};
216+
return MDNode::get(Ctx, Operands);
217+
}
218+
219+
MDNode *MetadataBuilder::BuildRootDescriptor(const RootDescriptor &Descriptor) {
220+
IRBuilder<> Builder(Ctx);
221+
llvm::SmallString<7> Name;
222+
llvm::raw_svector_ostream OS(Name);
223+
OS << "Root" << ClauseType(llvm::to_underlying(Descriptor.Type));
224+
225+
Metadata *Operands[] = {
226+
MDString::get(Ctx, OS.str()),
227+
ConstantAsMetadata::get(
228+
Builder.getInt32(llvm::to_underlying(Descriptor.Visibility))),
229+
ConstantAsMetadata::get(Builder.getInt32(Descriptor.Reg.Number)),
230+
ConstantAsMetadata::get(Builder.getInt32(Descriptor.Space)),
231+
ConstantAsMetadata::get(
232+
Builder.getInt32(llvm::to_underlying(Descriptor.Flags))),
233+
};
234+
return MDNode::get(Ctx, Operands);
235+
}
236+
190237
MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
191238
IRBuilder<> Builder(Ctx);
192239
SmallVector<Metadata *> TableOperands;

0 commit comments

Comments
 (0)