Path: blob/main/contrib/llvm-project/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
213799 views
//===- HLSLRootSignature.cpp - HLSL Root Signature helpers ----------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file This file contains helpers for working with HLSL Root Signatures.9///10//===----------------------------------------------------------------------===//1112#include "llvm/Frontend/HLSL/HLSLRootSignature.h"13#include "llvm/Support/ScopedPrinter.h"1415namespace llvm {16namespace hlsl {17namespace rootsig {1819template <typename T>20static std::optional<StringRef> getEnumName(const T Value,21ArrayRef<EnumEntry<T>> Enums) {22for (const auto &EnumItem : Enums)23if (EnumItem.Value == Value)24return EnumItem.Name;25return std::nullopt;26}2728template <typename T>29static raw_ostream &printEnum(raw_ostream &OS, const T Value,30ArrayRef<EnumEntry<T>> Enums) {31auto MaybeName = getEnumName(Value, Enums);32if (MaybeName)33OS << *MaybeName;34return OS;35}3637template <typename T>38static raw_ostream &printFlags(raw_ostream &OS, const T Value,39ArrayRef<EnumEntry<T>> Flags) {40bool FlagSet = false;41unsigned Remaining = llvm::to_underlying(Value);42while (Remaining) {43unsigned Bit = 1u << llvm::countr_zero(Remaining);44if (Remaining & Bit) {45if (FlagSet)46OS << " | ";4748auto MaybeFlag = getEnumName(T(Bit), Flags);49if (MaybeFlag)50OS << *MaybeFlag;51else52OS << "invalid: " << Bit;5354FlagSet = true;55}56Remaining &= ~Bit;57}5859if (!FlagSet)60OS << "None";61return OS;62}6364static const EnumEntry<RegisterType> RegisterNames[] = {65{"b", RegisterType::BReg},66{"t", RegisterType::TReg},67{"u", RegisterType::UReg},68{"s", RegisterType::SReg},69};7071static raw_ostream &operator<<(raw_ostream &OS, const Register &Reg) {72printEnum(OS, Reg.ViewType, ArrayRef(RegisterNames));73OS << Reg.Number;7475return OS;76}7778static raw_ostream &operator<<(raw_ostream &OS,79const llvm::dxbc::ShaderVisibility &Visibility) {80printEnum(OS, Visibility, dxbc::getShaderVisibility());8182return OS;83}8485static raw_ostream &operator<<(raw_ostream &OS,86const llvm::dxbc::SamplerFilter &Filter) {87printEnum(OS, Filter, dxbc::getSamplerFilters());8889return OS;90}9192static raw_ostream &operator<<(raw_ostream &OS,93const dxbc::TextureAddressMode &Address) {94printEnum(OS, Address, dxbc::getTextureAddressModes());9596return OS;97}9899static raw_ostream &operator<<(raw_ostream &OS,100const dxbc::ComparisonFunc &CompFunc) {101printEnum(OS, CompFunc, dxbc::getComparisonFuncs());102103return OS;104}105106static raw_ostream &operator<<(raw_ostream &OS,107const dxbc::StaticBorderColor &BorderColor) {108printEnum(OS, BorderColor, dxbc::getStaticBorderColors());109110return OS;111}112113static const EnumEntry<dxil::ResourceClass> ResourceClassNames[] = {114{"CBV", dxil::ResourceClass::CBuffer},115{"SRV", dxil::ResourceClass::SRV},116{"UAV", dxil::ResourceClass::UAV},117{"Sampler", dxil::ResourceClass::Sampler},118};119120static raw_ostream &operator<<(raw_ostream &OS, const ClauseType &Type) {121printEnum(OS, dxil::ResourceClass(llvm::to_underlying(Type)),122ArrayRef(ResourceClassNames));123124return OS;125}126127static raw_ostream &operator<<(raw_ostream &OS,128const dxbc::RootDescriptorFlags &Flags) {129printFlags(OS, Flags, dxbc::getRootDescriptorFlags());130131return OS;132}133134static raw_ostream &operator<<(raw_ostream &OS,135const llvm::dxbc::DescriptorRangeFlags &Flags) {136printFlags(OS, Flags, dxbc::getDescriptorRangeFlags());137138return OS;139}140141raw_ostream &operator<<(raw_ostream &OS, const dxbc::RootFlags &Flags) {142OS << "RootFlags(";143printFlags(OS, Flags, dxbc::getRootFlags());144OS << ")";145146return OS;147}148149raw_ostream &operator<<(raw_ostream &OS, const RootConstants &Constants) {150OS << "RootConstants(num32BitConstants = " << Constants.Num32BitConstants151<< ", " << Constants.Reg << ", space = " << Constants.Space152<< ", visibility = " << Constants.Visibility << ")";153154return OS;155}156157raw_ostream &operator<<(raw_ostream &OS, const DescriptorTable &Table) {158OS << "DescriptorTable(numClauses = " << Table.NumClauses159<< ", visibility = " << Table.Visibility << ")";160161return OS;162}163164raw_ostream &operator<<(raw_ostream &OS, const DescriptorTableClause &Clause) {165OS << Clause.Type << "(" << Clause.Reg << ", numDescriptors = ";166if (Clause.NumDescriptors == NumDescriptorsUnbounded)167OS << "unbounded";168else169OS << Clause.NumDescriptors;170OS << ", space = " << Clause.Space << ", offset = ";171if (Clause.Offset == DescriptorTableOffsetAppend)172OS << "DescriptorTableOffsetAppend";173else174OS << Clause.Offset;175OS << ", flags = " << Clause.Flags << ")";176177return OS;178}179180raw_ostream &operator<<(raw_ostream &OS, const RootDescriptor &Descriptor) {181ClauseType Type = ClauseType(llvm::to_underlying(Descriptor.Type));182OS << "Root" << Type << "(" << Descriptor.Reg183<< ", space = " << Descriptor.Space184<< ", visibility = " << Descriptor.Visibility185<< ", flags = " << Descriptor.Flags << ")";186187return OS;188}189190raw_ostream &operator<<(raw_ostream &OS, const StaticSampler &Sampler) {191OS << "StaticSampler(" << Sampler.Reg << ", filter = " << Sampler.Filter192<< ", addressU = " << Sampler.AddressU193<< ", addressV = " << Sampler.AddressV194<< ", addressW = " << Sampler.AddressW195<< ", mipLODBias = " << Sampler.MipLODBias196<< ", maxAnisotropy = " << Sampler.MaxAnisotropy197<< ", comparisonFunc = " << Sampler.CompFunc198<< ", borderColor = " << Sampler.BorderColor199<< ", minLOD = " << Sampler.MinLOD << ", maxLOD = " << Sampler.MaxLOD200<< ", space = " << Sampler.Space << ", visibility = " << Sampler.Visibility201<< ")";202return OS;203}204205namespace {206207// We use the OverloadVisit with std::visit to ensure the compiler catches if a208// new RootElement variant type is added but it's operator<< isn't handled.209template <class... Ts> struct OverloadedVisit : Ts... {210using Ts::operator()...;211};212template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;213214} // namespace215216raw_ostream &operator<<(raw_ostream &OS, const RootElement &Element) {217const auto Visitor = OverloadedVisit{218[&OS](const dxbc::RootFlags &Flags) { OS << Flags; },219[&OS](const RootConstants &Constants) { OS << Constants; },220[&OS](const RootDescriptor &Descriptor) { OS << Descriptor; },221[&OS](const DescriptorTableClause &Clause) { OS << Clause; },222[&OS](const DescriptorTable &Table) { OS << Table; },223[&OS](const StaticSampler &Sampler) { OS << Sampler; },224};225std::visit(Visitor, Element);226return OS;227}228229void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) {230OS << " RootElements{";231bool First = true;232for (const RootElement &Element : Elements) {233if (!First)234OS << ",";235OS << " " << Element;236First = false;237}238OS << "}";239}240241} // namespace rootsig242} // namespace hlsl243} // namespace llvm244245246