Skip to content

Commit b3ed428

Browse files
authored
[HLSL][RootSignature] Metadata generation of StaticSampler (#142642)
Implements metadata generation of a Root Signature from its in-memory representation. It follows the same style as: #139633. This pr handles `StaticSamplers`. It also handles converting the else-if chain into a `std::visit` to allow for future compiler warnings when adding additional `RootElement` variants. 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 `BuildStaticSampler` 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. Resolves #126586
1 parent 7ce315d commit b3ed428

File tree

3 files changed

+102
-17
lines changed

3 files changed

+102
-17
lines changed

clang/test/CodeGenHLSL/RootSignature.hlsl

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s
22

33
// CHECK: !dx.rootsignatures = !{![[#EMPTY_ENTRY:]], ![[#DT_ENTRY:]],
4-
// CHECK-SAME: ![[#RF_ENTRY:]], ![[#RC_ENTRY:]], ![[#RD_ENTRY:]]}
4+
// CHECK-SAME: ![[#RF_ENTRY:]], ![[#RC_ENTRY:]], ![[#RD_ENTRY:]], ![[#SS_ENTRY:]]}
55

66
// CHECK: ![[#EMPTY_ENTRY]] = !{ptr @EmptyEntry, ![[#EMPTY:]]}
77
// CHECK: ![[#EMPTY]] = !{}
@@ -66,6 +66,40 @@ void RootConstantsEntry() {}
6666
[numthreads(1,1,1)]
6767
void RootDescriptorsEntry() {}
6868

69+
// CHECK: ![[#SS_ENTRY]] = !{ptr @StaticSamplerEntry, ![[#SS_RS:]]}
70+
// CHECK: ![[#SS_RS]] = !{![[#STATIC_SAMPLER:]]}
71+
72+
// checking filter = 0x4
73+
// CHECK: ![[#STATIC_SAMPLER]] = !{!"StaticSampler", i32 4,
74+
75+
// checking texture address[U|V|W]
76+
// CHECK-SAME: i32 2, i32 3, i32 5,
77+
78+
// checking mipLODBias, maxAnisotropy, comparisonFunc, borderColor
79+
// CHECK-SAME: float 0x40403999A0000000, i32 9, i32 3, i32 2,
80+
81+
// checking minLOD, maxLOD
82+
// CHECK-SAME: float -1.280000e+02, float 1.280000e+02,
83+
84+
// checking register, space and visibility
85+
// CHECK-SAME: i32 42, i32 0, i32 0}
86+
87+
#define SampleStaticSampler \
88+
"StaticSampler(s42, " \
89+
" filter = FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT, " \
90+
" addressU = TEXTURE_ADDRESS_MIRROR, " \
91+
" addressV = TEXTURE_ADDRESS_CLAMP, " \
92+
" addressW = TEXTURE_ADDRESS_MIRRORONCE, " \
93+
" mipLODBias = 32.45f, maxAnisotropy = 9, " \
94+
" comparisonFunc = COMPARISON_EQUAL, " \
95+
" borderColor = STATIC_BORDER_COLOR_OPAQUE_WHITE, " \
96+
" minLOD = -128.f, maxLOD = 128.f, " \
97+
" space = 0, visibility = SHADER_VISIBILITY_ALL, " \
98+
")"
99+
[shader("compute"), RootSignature(SampleStaticSampler)]
100+
[numthreads(1,1,1)]
101+
void StaticSamplerEntry() {}
102+
69103
// Sanity test to ensure no root is added for this function as there is only
70104
// two entries in !dx.roosignatures
71105
[shader("compute")]

llvm/include/llvm/Frontend/HLSL/HLSLRootSignatureUtils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class MetadataBuilder {
5252
MDNode *BuildRootDescriptor(const RootDescriptor &Descriptor);
5353
MDNode *BuildDescriptorTable(const DescriptorTable &Table);
5454
MDNode *BuildDescriptorTableClause(const DescriptorTableClause &Clause);
55+
MDNode *BuildStaticSampler(const StaticSampler &Sampler);
5556

5657
llvm::LLVMContext &Ctx;
5758
ArrayRef<RootElement> Elements;

llvm/lib/Frontend/HLSL/HLSLRootSignatureUtils.cpp

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -168,25 +168,44 @@ void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
168168
OS << "}";
169169
}
170170

171+
namespace {
172+
173+
// We use the OverloadBuild with std::visit to ensure the compiler catches if a
174+
// new RootElement variant type is added but it's metadata generation isn't
175+
// handled.
176+
template <class... Ts> struct OverloadedBuild : Ts... {
177+
using Ts::operator()...;
178+
};
179+
template <class... Ts> OverloadedBuild(Ts...) -> OverloadedBuild<Ts...>;
180+
181+
} // namespace
182+
171183
MDNode *MetadataBuilder::BuildRootSignature() {
184+
const auto Visitor = OverloadedBuild{
185+
[this](const RootFlags &Flags) -> MDNode * {
186+
return BuildRootFlags(Flags);
187+
},
188+
[this](const RootConstants &Constants) -> MDNode * {
189+
return BuildRootConstants(Constants);
190+
},
191+
[this](const RootDescriptor &Descriptor) -> MDNode * {
192+
return BuildRootDescriptor(Descriptor);
193+
},
194+
[this](const DescriptorTableClause &Clause) -> MDNode * {
195+
return BuildDescriptorTableClause(Clause);
196+
},
197+
[this](const DescriptorTable &Table) -> MDNode * {
198+
return BuildDescriptorTable(Table);
199+
},
200+
[this](const StaticSampler &Sampler) -> MDNode * {
201+
return BuildStaticSampler(Sampler);
202+
},
203+
};
204+
172205
for (const RootElement &Element : Elements) {
173-
MDNode *ElementMD = nullptr;
174-
if (const auto &Flags = std::get_if<RootFlags>(&Element))
175-
ElementMD = BuildRootFlags(*Flags);
176-
else if (const auto &Constants = std::get_if<RootConstants>(&Element))
177-
ElementMD = BuildRootConstants(*Constants);
178-
else if (const auto &Descriptor = std::get_if<RootDescriptor>(&Element))
179-
ElementMD = BuildRootDescriptor(*Descriptor);
180-
else if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element))
181-
ElementMD = BuildDescriptorTableClause(*Clause);
182-
else if (const auto &Table = std::get_if<DescriptorTable>(&Element))
183-
ElementMD = BuildDescriptorTable(*Table);
184-
185-
// FIXME(#126586): remove once all RootElemnt variants are handled in a
186-
// visit or otherwise
206+
MDNode *ElementMD = std::visit(Visitor, Element);
187207
assert(ElementMD != nullptr &&
188-
"Constructed an unhandled root element type.");
189-
208+
"Root Element must be initialized and validated");
190209
GeneratedMetadata.push_back(ElementMD);
191210
}
192211

@@ -273,6 +292,37 @@ MDNode *MetadataBuilder::BuildDescriptorTableClause(
273292
});
274293
}
275294

295+
MDNode *MetadataBuilder::BuildStaticSampler(const StaticSampler &Sampler) {
296+
IRBuilder<> Builder(Ctx);
297+
Metadata *Operands[] = {
298+
MDString::get(Ctx, "StaticSampler"),
299+
ConstantAsMetadata::get(
300+
Builder.getInt32(llvm::to_underlying(Sampler.Filter))),
301+
ConstantAsMetadata::get(
302+
Builder.getInt32(llvm::to_underlying(Sampler.AddressU))),
303+
ConstantAsMetadata::get(
304+
Builder.getInt32(llvm::to_underlying(Sampler.AddressV))),
305+
ConstantAsMetadata::get(
306+
Builder.getInt32(llvm::to_underlying(Sampler.AddressW))),
307+
ConstantAsMetadata::get(llvm::ConstantFP::get(llvm::Type::getFloatTy(Ctx),
308+
Sampler.MipLODBias)),
309+
ConstantAsMetadata::get(Builder.getInt32(Sampler.MaxAnisotropy)),
310+
ConstantAsMetadata::get(
311+
Builder.getInt32(llvm::to_underlying(Sampler.CompFunc))),
312+
ConstantAsMetadata::get(
313+
Builder.getInt32(llvm::to_underlying(Sampler.BorderColor))),
314+
ConstantAsMetadata::get(
315+
llvm::ConstantFP::get(llvm::Type::getFloatTy(Ctx), Sampler.MinLOD)),
316+
ConstantAsMetadata::get(
317+
llvm::ConstantFP::get(llvm::Type::getFloatTy(Ctx), Sampler.MaxLOD)),
318+
ConstantAsMetadata::get(Builder.getInt32(Sampler.Reg.Number)),
319+
ConstantAsMetadata::get(Builder.getInt32(Sampler.Space)),
320+
ConstantAsMetadata::get(
321+
Builder.getInt32(llvm::to_underlying(Sampler.Visibility))),
322+
};
323+
return MDNode::get(Ctx, Operands);
324+
}
325+
276326
} // namespace rootsig
277327
} // namespace hlsl
278328
} // namespace llvm

0 commit comments

Comments
 (0)