225 lines · cpp
1//===- HLSLRootSignature.cpp - HLSL Root Signature helpers ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file This file contains helpers for working with HLSL Root Signatures.10///11//===----------------------------------------------------------------------===//12 13#include "llvm/Frontend/HLSL/HLSLRootSignature.h"14#include "llvm/Support/DXILABI.h"15#include "llvm/Support/ScopedPrinter.h"16 17namespace llvm {18namespace hlsl {19namespace rootsig {20 21template <typename T>22static raw_ostream &printFlags(raw_ostream &OS, const T Value,23 ArrayRef<EnumEntry<T>> Flags) {24 bool FlagSet = false;25 unsigned Remaining = llvm::to_underlying(Value);26 while (Remaining) {27 unsigned Bit = 1u << llvm::countr_zero(Remaining);28 if (Remaining & Bit) {29 if (FlagSet)30 OS << " | ";31 32 StringRef MaybeFlag = enumToStringRef(T(Bit), Flags);33 if (!MaybeFlag.empty())34 OS << MaybeFlag;35 else36 OS << "invalid: " << Bit;37 38 FlagSet = true;39 }40 Remaining &= ~Bit;41 }42 43 if (!FlagSet)44 OS << "None";45 return OS;46}47 48static const EnumEntry<RegisterType> RegisterNames[] = {49 {"b", RegisterType::BReg},50 {"t", RegisterType::TReg},51 {"u", RegisterType::UReg},52 {"s", RegisterType::SReg},53};54 55static raw_ostream &operator<<(raw_ostream &OS, const Register &Reg) {56 OS << enumToStringRef(Reg.ViewType, ArrayRef(RegisterNames)) << Reg.Number;57 58 return OS;59}60 61static raw_ostream &operator<<(raw_ostream &OS,62 const llvm::dxbc::ShaderVisibility &Visibility) {63 OS << enumToStringRef(Visibility, dxbc::getShaderVisibility());64 65 return OS;66}67 68static raw_ostream &operator<<(raw_ostream &OS,69 const llvm::dxbc::SamplerFilter &Filter) {70 OS << enumToStringRef(Filter, dxbc::getSamplerFilters());71 72 return OS;73}74 75static raw_ostream &operator<<(raw_ostream &OS,76 const dxbc::TextureAddressMode &Address) {77 OS << enumToStringRef(Address, dxbc::getTextureAddressModes());78 79 return OS;80}81 82static raw_ostream &operator<<(raw_ostream &OS,83 const dxbc::ComparisonFunc &CompFunc) {84 OS << enumToStringRef(CompFunc, dxbc::getComparisonFuncs());85 86 return OS;87}88 89static raw_ostream &operator<<(raw_ostream &OS,90 const dxbc::StaticBorderColor &BorderColor) {91 OS << enumToStringRef(BorderColor, dxbc::getStaticBorderColors());92 93 return OS;94}95 96static raw_ostream &operator<<(raw_ostream &OS,97 const dxil::ResourceClass &Type) {98 OS << dxil::getResourceClassName(Type);99 return OS;100}101 102static raw_ostream &operator<<(raw_ostream &OS,103 const dxbc::RootDescriptorFlags &Flags) {104 printFlags(OS, Flags, dxbc::getRootDescriptorFlags());105 106 return OS;107}108 109static raw_ostream &operator<<(raw_ostream &OS,110 const llvm::dxbc::DescriptorRangeFlags &Flags) {111 printFlags(OS, Flags, dxbc::getDescriptorRangeFlags());112 113 return OS;114}115 116static raw_ostream &operator<<(raw_ostream &OS,117 const llvm::dxbc::StaticSamplerFlags &Flags) {118 printFlags(OS, Flags, dxbc::getStaticSamplerFlags());119 120 return OS;121}122 123raw_ostream &operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags) {124 OS << "RootFlags(";125 printFlags(OS, Flags, dxbc::getRootFlags());126 OS << ")";127 128 return OS;129}130 131raw_ostream &operator<<(raw_ostream &OS, const RootConstants &Constants) {132 OS << "RootConstants(num32BitConstants = " << Constants.Num32BitConstants133 << ", " << Constants.Reg << ", space = " << Constants.Space134 << ", visibility = " << Constants.Visibility << ")";135 136 return OS;137}138 139raw_ostream &operator<<(raw_ostream &OS, const DescriptorTable &Table) {140 OS << "DescriptorTable(numClauses = " << Table.NumClauses141 << ", visibility = " << Table.Visibility << ")";142 143 return OS;144}145 146raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause) {147 OS << Clause.Type << "(" << Clause.Reg << ", numDescriptors = ";148 if (Clause.NumDescriptors == NumDescriptorsUnbounded)149 OS << "unbounded";150 else151 OS << Clause.NumDescriptors;152 OS << ", space = " << Clause.Space << ", offset = ";153 if (Clause.Offset == DescriptorTableOffsetAppend)154 OS << "DescriptorTableOffsetAppend";155 else156 OS << Clause.Offset;157 OS << ", flags = " << Clause.Flags << ")";158 159 return OS;160}161 162raw_ostream &operator<<(raw_ostream &OS, const RootDescriptor &Descriptor) {163 OS << "Root" << Descriptor.Type << "(" << Descriptor.Reg164 << ", space = " << Descriptor.Space165 << ", visibility = " << Descriptor.Visibility166 << ", flags = " << Descriptor.Flags << ")";167 168 return OS;169}170 171raw_ostream &operator<<(raw_ostream &OS, const StaticSampler &Sampler) {172 OS << "StaticSampler(" << Sampler.Reg << ", filter = " << Sampler.Filter173 << ", addressU = " << Sampler.AddressU174 << ", addressV = " << Sampler.AddressV175 << ", addressW = " << Sampler.AddressW176 << ", mipLODBias = " << Sampler.MipLODBias177 << ", maxAnisotropy = " << Sampler.MaxAnisotropy178 << ", comparisonFunc = " << Sampler.CompFunc179 << ", borderColor = " << Sampler.BorderColor180 << ", minLOD = " << Sampler.MinLOD << ", maxLOD = " << Sampler.MaxLOD181 << ", space = " << Sampler.Space << ", visibility = " << Sampler.Visibility182 << ", flags = " << Sampler.Flags << ")";183 return OS;184}185 186namespace {187 188// We use the OverloadVisit with std::visit to ensure the compiler catches if a189// new RootElement variant type is added but it's operator<< isn't handled.190template <class... Ts> struct OverloadedVisit : Ts... {191 using Ts::operator()...;192};193template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;194 195} // namespace196 197raw_ostream &operator<<(raw_ostream &OS, const RootElement &Element) {198 const auto Visitor = OverloadedVisit{199 [&OS](const dxbc::RootFlags &Flags) { OS << Flags; },200 [&OS](const RootConstants &Constants) { OS << Constants; },201 [&OS](const RootDescriptor &Descriptor) { OS << Descriptor; },202 [&OS](const DescriptorTableClause &Clause) { OS << Clause; },203 [&OS](const DescriptorTable &Table) { OS << Table; },204 [&OS](const StaticSampler &Sampler) { OS << Sampler; },205 };206 std::visit(Visitor, Element);207 return OS;208}209 210void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {211 OS << " RootElements{";212 bool First = true;213 for (const RootElement &Element : Elements) {214 if (!First)215 OS << ",";216 OS << " " << Element;217 First = false;218 }219 OS << "}";220}221 222} // namespace rootsig223} // namespace hlsl224} // namespace llvm225