xref: /freebsd/contrib/llvm-project/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===- HLSLRootSignature.cpp - HLSL Root Signature helpers ----------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric ///
9*700637cbSDimitry Andric /// \file This file contains helpers for working with HLSL Root Signatures.
10*700637cbSDimitry Andric ///
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "llvm/Frontend/HLSL/HLSLRootSignature.h"
14*700637cbSDimitry Andric #include "llvm/Support/ScopedPrinter.h"
15*700637cbSDimitry Andric 
16*700637cbSDimitry Andric namespace llvm {
17*700637cbSDimitry Andric namespace hlsl {
18*700637cbSDimitry Andric namespace rootsig {
19*700637cbSDimitry Andric 
20*700637cbSDimitry Andric template <typename T>
getEnumName(const T Value,ArrayRef<EnumEntry<T>> Enums)21*700637cbSDimitry Andric static std::optional<StringRef> getEnumName(const T Value,
22*700637cbSDimitry Andric                                             ArrayRef<EnumEntry<T>> Enums) {
23*700637cbSDimitry Andric   for (const auto &EnumItem : Enums)
24*700637cbSDimitry Andric     if (EnumItem.Value == Value)
25*700637cbSDimitry Andric       return EnumItem.Name;
26*700637cbSDimitry Andric   return std::nullopt;
27*700637cbSDimitry Andric }
28*700637cbSDimitry Andric 
29*700637cbSDimitry Andric template <typename T>
printEnum(raw_ostream & OS,const T Value,ArrayRef<EnumEntry<T>> Enums)30*700637cbSDimitry Andric static raw_ostream &printEnum(raw_ostream &OS, const T Value,
31*700637cbSDimitry Andric                               ArrayRef<EnumEntry<T>> Enums) {
32*700637cbSDimitry Andric   auto MaybeName = getEnumName(Value, Enums);
33*700637cbSDimitry Andric   if (MaybeName)
34*700637cbSDimitry Andric     OS << *MaybeName;
35*700637cbSDimitry Andric   return OS;
36*700637cbSDimitry Andric }
37*700637cbSDimitry Andric 
38*700637cbSDimitry Andric template <typename T>
printFlags(raw_ostream & OS,const T Value,ArrayRef<EnumEntry<T>> Flags)39*700637cbSDimitry Andric static raw_ostream &printFlags(raw_ostream &OS, const T Value,
40*700637cbSDimitry Andric                                ArrayRef<EnumEntry<T>> Flags) {
41*700637cbSDimitry Andric   bool FlagSet = false;
42*700637cbSDimitry Andric   unsigned Remaining = llvm::to_underlying(Value);
43*700637cbSDimitry Andric   while (Remaining) {
44*700637cbSDimitry Andric     unsigned Bit = 1u << llvm::countr_zero(Remaining);
45*700637cbSDimitry Andric     if (Remaining & Bit) {
46*700637cbSDimitry Andric       if (FlagSet)
47*700637cbSDimitry Andric         OS << " | ";
48*700637cbSDimitry Andric 
49*700637cbSDimitry Andric       auto MaybeFlag = getEnumName(T(Bit), Flags);
50*700637cbSDimitry Andric       if (MaybeFlag)
51*700637cbSDimitry Andric         OS << *MaybeFlag;
52*700637cbSDimitry Andric       else
53*700637cbSDimitry Andric         OS << "invalid: " << Bit;
54*700637cbSDimitry Andric 
55*700637cbSDimitry Andric       FlagSet = true;
56*700637cbSDimitry Andric     }
57*700637cbSDimitry Andric     Remaining &= ~Bit;
58*700637cbSDimitry Andric   }
59*700637cbSDimitry Andric 
60*700637cbSDimitry Andric   if (!FlagSet)
61*700637cbSDimitry Andric     OS << "None";
62*700637cbSDimitry Andric   return OS;
63*700637cbSDimitry Andric }
64*700637cbSDimitry Andric 
65*700637cbSDimitry Andric static const EnumEntry<RegisterType> RegisterNames[] = {
66*700637cbSDimitry Andric     {"b", RegisterType::BReg},
67*700637cbSDimitry Andric     {"t", RegisterType::TReg},
68*700637cbSDimitry Andric     {"u", RegisterType::UReg},
69*700637cbSDimitry Andric     {"s", RegisterType::SReg},
70*700637cbSDimitry Andric };
71*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const Register & Reg)72*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS, const Register &Reg) {
73*700637cbSDimitry Andric   printEnum(OS, Reg.ViewType, ArrayRef(RegisterNames));
74*700637cbSDimitry Andric   OS << Reg.Number;
75*700637cbSDimitry Andric 
76*700637cbSDimitry Andric   return OS;
77*700637cbSDimitry Andric }
78*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const llvm::dxbc::ShaderVisibility & Visibility)79*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS,
80*700637cbSDimitry Andric                                const llvm::dxbc::ShaderVisibility &Visibility) {
81*700637cbSDimitry Andric   printEnum(OS, Visibility, dxbc::getShaderVisibility());
82*700637cbSDimitry Andric 
83*700637cbSDimitry Andric   return OS;
84*700637cbSDimitry Andric }
85*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const llvm::dxbc::SamplerFilter & Filter)86*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS,
87*700637cbSDimitry Andric                                const llvm::dxbc::SamplerFilter &Filter) {
88*700637cbSDimitry Andric   printEnum(OS, Filter, dxbc::getSamplerFilters());
89*700637cbSDimitry Andric 
90*700637cbSDimitry Andric   return OS;
91*700637cbSDimitry Andric }
92*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const dxbc::TextureAddressMode & Address)93*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS,
94*700637cbSDimitry Andric                                const dxbc::TextureAddressMode &Address) {
95*700637cbSDimitry Andric   printEnum(OS, Address, dxbc::getTextureAddressModes());
96*700637cbSDimitry Andric 
97*700637cbSDimitry Andric   return OS;
98*700637cbSDimitry Andric }
99*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const dxbc::ComparisonFunc & CompFunc)100*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS,
101*700637cbSDimitry Andric                                const dxbc::ComparisonFunc &CompFunc) {
102*700637cbSDimitry Andric   printEnum(OS, CompFunc, dxbc::getComparisonFuncs());
103*700637cbSDimitry Andric 
104*700637cbSDimitry Andric   return OS;
105*700637cbSDimitry Andric }
106*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const dxbc::StaticBorderColor & BorderColor)107*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS,
108*700637cbSDimitry Andric                                const dxbc::StaticBorderColor &BorderColor) {
109*700637cbSDimitry Andric   printEnum(OS, BorderColor, dxbc::getStaticBorderColors());
110*700637cbSDimitry Andric 
111*700637cbSDimitry Andric   return OS;
112*700637cbSDimitry Andric }
113*700637cbSDimitry Andric 
114*700637cbSDimitry Andric static const EnumEntry<dxil::ResourceClass> ResourceClassNames[] = {
115*700637cbSDimitry Andric     {"CBV", dxil::ResourceClass::CBuffer},
116*700637cbSDimitry Andric     {"SRV", dxil::ResourceClass::SRV},
117*700637cbSDimitry Andric     {"UAV", dxil::ResourceClass::UAV},
118*700637cbSDimitry Andric     {"Sampler", dxil::ResourceClass::Sampler},
119*700637cbSDimitry Andric };
120*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const ClauseType & Type)121*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS, const ClauseType &Type) {
122*700637cbSDimitry Andric   printEnum(OS, dxil::ResourceClass(llvm::to_underlying(Type)),
123*700637cbSDimitry Andric             ArrayRef(ResourceClassNames));
124*700637cbSDimitry Andric 
125*700637cbSDimitry Andric   return OS;
126*700637cbSDimitry Andric }
127*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const dxbc::RootDescriptorFlags & Flags)128*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS,
129*700637cbSDimitry Andric                                const dxbc::RootDescriptorFlags &Flags) {
130*700637cbSDimitry Andric   printFlags(OS, Flags, dxbc::getRootDescriptorFlags());
131*700637cbSDimitry Andric 
132*700637cbSDimitry Andric   return OS;
133*700637cbSDimitry Andric }
134*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const llvm::dxbc::DescriptorRangeFlags & Flags)135*700637cbSDimitry Andric static raw_ostream &operator<<(raw_ostream &OS,
136*700637cbSDimitry Andric                                const llvm::dxbc::DescriptorRangeFlags &Flags) {
137*700637cbSDimitry Andric   printFlags(OS, Flags, dxbc::getDescriptorRangeFlags());
138*700637cbSDimitry Andric 
139*700637cbSDimitry Andric   return OS;
140*700637cbSDimitry Andric }
141*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const dxbc::RootFlags & Flags)142*700637cbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags) {
143*700637cbSDimitry Andric   OS << "RootFlags(";
144*700637cbSDimitry Andric   printFlags(OS, Flags, dxbc::getRootFlags());
145*700637cbSDimitry Andric   OS << ")";
146*700637cbSDimitry Andric 
147*700637cbSDimitry Andric   return OS;
148*700637cbSDimitry Andric }
149*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const RootConstants & Constants)150*700637cbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RootConstants &Constants) {
151*700637cbSDimitry Andric   OS << "RootConstants(num32BitConstants = " << Constants.Num32BitConstants
152*700637cbSDimitry Andric      << ", " << Constants.Reg << ", space = " << Constants.Space
153*700637cbSDimitry Andric      << ", visibility = " << Constants.Visibility << ")";
154*700637cbSDimitry Andric 
155*700637cbSDimitry Andric   return OS;
156*700637cbSDimitry Andric }
157*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const DescriptorTable & Table)158*700637cbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const DescriptorTable &Table) {
159*700637cbSDimitry Andric   OS << "DescriptorTable(numClauses = " << Table.NumClauses
160*700637cbSDimitry Andric      << ", visibility = " << Table.Visibility << ")";
161*700637cbSDimitry Andric 
162*700637cbSDimitry Andric   return OS;
163*700637cbSDimitry Andric }
164*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const DescriptorTableClause & Clause)165*700637cbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause) {
166*700637cbSDimitry Andric   OS << Clause.Type << "(" << Clause.Reg << ", numDescriptors = ";
167*700637cbSDimitry Andric   if (Clause.NumDescriptors == NumDescriptorsUnbounded)
168*700637cbSDimitry Andric     OS << "unbounded";
169*700637cbSDimitry Andric   else
170*700637cbSDimitry Andric     OS << Clause.NumDescriptors;
171*700637cbSDimitry Andric   OS << ", space = " << Clause.Space << ", offset = ";
172*700637cbSDimitry Andric   if (Clause.Offset == DescriptorTableOffsetAppend)
173*700637cbSDimitry Andric     OS << "DescriptorTableOffsetAppend";
174*700637cbSDimitry Andric   else
175*700637cbSDimitry Andric     OS << Clause.Offset;
176*700637cbSDimitry Andric   OS << ", flags = " << Clause.Flags << ")";
177*700637cbSDimitry Andric 
178*700637cbSDimitry Andric   return OS;
179*700637cbSDimitry Andric }
180*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const RootDescriptor & Descriptor)181*700637cbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RootDescriptor &Descriptor) {
182*700637cbSDimitry Andric   ClauseType Type = ClauseType(llvm::to_underlying(Descriptor.Type));
183*700637cbSDimitry Andric   OS << "Root" << Type << "(" << Descriptor.Reg
184*700637cbSDimitry Andric      << ", space = " << Descriptor.Space
185*700637cbSDimitry Andric      << ", visibility = " << Descriptor.Visibility
186*700637cbSDimitry Andric      << ", flags = " << Descriptor.Flags << ")";
187*700637cbSDimitry Andric 
188*700637cbSDimitry Andric   return OS;
189*700637cbSDimitry Andric }
190*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const StaticSampler & Sampler)191*700637cbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const StaticSampler &Sampler) {
192*700637cbSDimitry Andric   OS << "StaticSampler(" << Sampler.Reg << ", filter = " << Sampler.Filter
193*700637cbSDimitry Andric      << ", addressU = " << Sampler.AddressU
194*700637cbSDimitry Andric      << ", addressV = " << Sampler.AddressV
195*700637cbSDimitry Andric      << ", addressW = " << Sampler.AddressW
196*700637cbSDimitry Andric      << ", mipLODBias = " << Sampler.MipLODBias
197*700637cbSDimitry Andric      << ", maxAnisotropy = " << Sampler.MaxAnisotropy
198*700637cbSDimitry Andric      << ", comparisonFunc = " << Sampler.CompFunc
199*700637cbSDimitry Andric      << ", borderColor = " << Sampler.BorderColor
200*700637cbSDimitry Andric      << ", minLOD = " << Sampler.MinLOD << ", maxLOD = " << Sampler.MaxLOD
201*700637cbSDimitry Andric      << ", space = " << Sampler.Space << ", visibility = " << Sampler.Visibility
202*700637cbSDimitry Andric      << ")";
203*700637cbSDimitry Andric   return OS;
204*700637cbSDimitry Andric }
205*700637cbSDimitry Andric 
206*700637cbSDimitry Andric namespace {
207*700637cbSDimitry Andric 
208*700637cbSDimitry Andric // We use the OverloadVisit with std::visit to ensure the compiler catches if a
209*700637cbSDimitry Andric // new RootElement variant type is added but it's operator<< isn't handled.
210*700637cbSDimitry Andric template <class... Ts> struct OverloadedVisit : Ts... {
211*700637cbSDimitry Andric   using Ts::operator()...;
212*700637cbSDimitry Andric };
213*700637cbSDimitry Andric template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;
214*700637cbSDimitry Andric 
215*700637cbSDimitry Andric } // namespace
216*700637cbSDimitry Andric 
operator <<(raw_ostream & OS,const RootElement & Element)217*700637cbSDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const RootElement &Element) {
218*700637cbSDimitry Andric   const auto Visitor = OverloadedVisit{
219*700637cbSDimitry Andric       [&OS](const dxbc::RootFlags &Flags) { OS << Flags; },
220*700637cbSDimitry Andric       [&OS](const RootConstants &Constants) { OS << Constants; },
221*700637cbSDimitry Andric       [&OS](const RootDescriptor &Descriptor) { OS << Descriptor; },
222*700637cbSDimitry Andric       [&OS](const DescriptorTableClause &Clause) { OS << Clause; },
223*700637cbSDimitry Andric       [&OS](const DescriptorTable &Table) { OS << Table; },
224*700637cbSDimitry Andric       [&OS](const StaticSampler &Sampler) { OS << Sampler; },
225*700637cbSDimitry Andric   };
226*700637cbSDimitry Andric   std::visit(Visitor, Element);
227*700637cbSDimitry Andric   return OS;
228*700637cbSDimitry Andric }
229*700637cbSDimitry Andric 
dumpRootElements(raw_ostream & OS,ArrayRef<RootElement> Elements)230*700637cbSDimitry Andric void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {
231*700637cbSDimitry Andric   OS << " RootElements{";
232*700637cbSDimitry Andric   bool First = true;
233*700637cbSDimitry Andric   for (const RootElement &Element : Elements) {
234*700637cbSDimitry Andric     if (!First)
235*700637cbSDimitry Andric       OS << ",";
236*700637cbSDimitry Andric     OS << " " << Element;
237*700637cbSDimitry Andric     First = false;
238*700637cbSDimitry Andric   }
239*700637cbSDimitry Andric   OS << "}";
240*700637cbSDimitry Andric }
241*700637cbSDimitry Andric 
242*700637cbSDimitry Andric } // namespace rootsig
243*700637cbSDimitry Andric } // namespace hlsl
244*700637cbSDimitry Andric } // namespace llvm
245