Path: blob/main/contrib/llvm-project/llvm/lib/Target/DirectX/DXILResource.cpp
35266 views
//===- DXILResource.cpp - DXIL Resource helper objects --------------------===//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 helper objects for working with DXIL Resources.9///10//===----------------------------------------------------------------------===//1112#include "DXILResource.h"13#include "CBufferDataLayout.h"14#include "llvm/ADT/StringSwitch.h"15#include "llvm/IR/IRBuilder.h"16#include "llvm/IR/Metadata.h"17#include "llvm/IR/Module.h"18#include "llvm/Support/Debug.h"19#include "llvm/Support/Format.h"2021using namespace llvm;22using namespace llvm::dxil;2324template <typename T> void ResourceTable<T>::collect(Module &M) {25NamedMDNode *Entry = M.getNamedMetadata(MDName);26if (!Entry || Entry->getNumOperands() == 0)27return;2829uint32_t Counter = 0;30for (auto *Res : Entry->operands()) {31Data.push_back(T(Counter++, hlsl::FrontendResource(cast<MDNode>(Res))));32}33}3435template <> void ResourceTable<ConstantBuffer>::collect(Module &M) {36NamedMDNode *Entry = M.getNamedMetadata(MDName);37if (!Entry || Entry->getNumOperands() == 0)38return;3940uint32_t Counter = 0;41for (auto *Res : Entry->operands()) {42Data.push_back(43ConstantBuffer(Counter++, hlsl::FrontendResource(cast<MDNode>(Res))));44}45// FIXME: share CBufferDataLayout with CBuffer load lowering.46// See https://github.com/llvm/llvm-project/issues/5838147CBufferDataLayout CBDL(M.getDataLayout(), /*IsLegacy*/ true);48for (auto &CB : Data)49CB.setSize(CBDL);50}5152void Resources::collect(Module &M) {53UAVs.collect(M);54CBuffers.collect(M);55}5657ResourceBase::ResourceBase(uint32_t I, hlsl::FrontendResource R)58: ID(I), GV(R.getGlobalVariable()), Name(""), Space(R.getSpace()),59LowerBound(R.getResourceIndex()), RangeSize(1) {60if (auto *ArrTy = dyn_cast<ArrayType>(GV->getValueType()))61RangeSize = ArrTy->getNumElements();62}6364StringRef ResourceBase::getElementTypeName(ElementType ElTy) {65switch (ElTy) {66case ElementType::Invalid:67return "invalid";68case ElementType::I1:69return "i1";70case ElementType::I16:71return "i16";72case ElementType::U16:73return "u16";74case ElementType::I32:75return "i32";76case ElementType::U32:77return "u32";78case ElementType::I64:79return "i64";80case ElementType::U64:81return "u64";82case ElementType::F16:83return "f16";84case ElementType::F32:85return "f32";86case ElementType::F64:87return "f64";88case ElementType::SNormF16:89return "snorm_f16";90case ElementType::UNormF16:91return "unorm_f16";92case ElementType::SNormF32:93return "snorm_f32";94case ElementType::UNormF32:95return "unorm_f32";96case ElementType::SNormF64:97return "snorm_f64";98case ElementType::UNormF64:99return "unorm_f64";100case ElementType::PackedS8x32:101return "p32i8";102case ElementType::PackedU8x32:103return "p32u8";104}105llvm_unreachable("All ElementType enums are handled in switch");106}107108void ResourceBase::printElementType(ResourceKind Kind, ElementType ElTy,109unsigned Alignment, raw_ostream &OS) {110switch (Kind) {111default:112// TODO: add vector size.113OS << right_justify(getElementTypeName(ElTy), Alignment);114break;115case ResourceKind::RawBuffer:116OS << right_justify("byte", Alignment);117break;118case ResourceKind::StructuredBuffer:119OS << right_justify("struct", Alignment);120break;121case ResourceKind::CBuffer:122case ResourceKind::Sampler:123OS << right_justify("NA", Alignment);124break;125case ResourceKind::Invalid:126case ResourceKind::NumEntries:127break;128}129}130131StringRef ResourceBase::getKindName(ResourceKind Kind) {132switch (Kind) {133case ResourceKind::NumEntries:134case ResourceKind::Invalid:135return "invalid";136case ResourceKind::Texture1D:137return "1d";138case ResourceKind::Texture2D:139return "2d";140case ResourceKind::Texture2DMS:141return "2dMS";142case ResourceKind::Texture3D:143return "3d";144case ResourceKind::TextureCube:145return "cube";146case ResourceKind::Texture1DArray:147return "1darray";148case ResourceKind::Texture2DArray:149return "2darray";150case ResourceKind::Texture2DMSArray:151return "2darrayMS";152case ResourceKind::TextureCubeArray:153return "cubearray";154case ResourceKind::TypedBuffer:155return "buf";156case ResourceKind::RawBuffer:157return "rawbuf";158case ResourceKind::StructuredBuffer:159return "structbuf";160case ResourceKind::CBuffer:161return "cbuffer";162case ResourceKind::Sampler:163return "sampler";164case ResourceKind::TBuffer:165return "tbuffer";166case ResourceKind::RTAccelerationStructure:167return "ras";168case ResourceKind::FeedbackTexture2D:169return "fbtex2d";170case ResourceKind::FeedbackTexture2DArray:171return "fbtex2darray";172}173llvm_unreachable("All ResourceKind enums are handled in switch");174}175176void ResourceBase::printKind(ResourceKind Kind, unsigned Alignment,177raw_ostream &OS, bool SRV, bool HasCounter,178uint32_t SampleCount) {179switch (Kind) {180default:181OS << right_justify(getKindName(Kind), Alignment);182break;183184case ResourceKind::RawBuffer:185case ResourceKind::StructuredBuffer:186if (SRV)187OS << right_justify("r/o", Alignment);188else {189if (!HasCounter)190OS << right_justify("r/w", Alignment);191else192OS << right_justify("r/w+cnt", Alignment);193}194break;195case ResourceKind::TypedBuffer:196OS << right_justify("buf", Alignment);197break;198case ResourceKind::Texture2DMS:199case ResourceKind::Texture2DMSArray: {200std::string DimName = getKindName(Kind).str();201if (SampleCount)202DimName += std::to_string(SampleCount);203OS << right_justify(DimName, Alignment);204} break;205case ResourceKind::CBuffer:206case ResourceKind::Sampler:207OS << right_justify("NA", Alignment);208break;209case ResourceKind::Invalid:210case ResourceKind::NumEntries:211break;212}213}214215void ResourceBase::print(raw_ostream &OS, StringRef IDPrefix,216StringRef BindingPrefix) const {217std::string ResID = IDPrefix.str();218ResID += std::to_string(ID);219OS << right_justify(ResID, 8);220221std::string Bind = BindingPrefix.str();222Bind += std::to_string(LowerBound);223if (Space)224Bind += ",space" + std::to_string(Space);225226OS << right_justify(Bind, 15);227if (RangeSize != UINT_MAX)228OS << right_justify(std::to_string(RangeSize), 6) << "\n";229else230OS << right_justify("unbounded", 6) << "\n";231}232233void UAVResource::print(raw_ostream &OS) const {234OS << "; " << left_justify(Name, 31);235236OS << right_justify("UAV", 10);237238printElementType(Shape, ExtProps.ElementType.value_or(ElementType::Invalid),2398, OS);240241// FIXME: support SampleCount.242// See https://github.com/llvm/llvm-project/issues/58175243printKind(Shape, 12, OS, /*SRV*/ false, HasCounter);244// Print the binding part.245ResourceBase::print(OS, "U", "u");246}247248ConstantBuffer::ConstantBuffer(uint32_t I, hlsl::FrontendResource R)249: ResourceBase(I, R) {}250251void ConstantBuffer::setSize(CBufferDataLayout &DL) {252CBufferSizeInBytes = DL.getTypeAllocSizeInBytes(GV->getValueType());253}254255void ConstantBuffer::print(raw_ostream &OS) const {256OS << "; " << left_justify(Name, 31);257258OS << right_justify("cbuffer", 10);259260printElementType(ResourceKind::CBuffer, ElementType::Invalid, 8, OS);261262printKind(ResourceKind::CBuffer, 12, OS, /*SRV*/ false, /*HasCounter*/ false);263// Print the binding part.264ResourceBase::print(OS, "CB", "cb");265}266267template <typename T> void ResourceTable<T>::print(raw_ostream &OS) const {268for (auto &Res : Data)269Res.print(OS);270}271272MDNode *ResourceBase::ExtendedProperties::write(LLVMContext &Ctx) const {273IRBuilder<> B(Ctx);274SmallVector<Metadata *> Entries;275if (ElementType) {276Entries.emplace_back(277ConstantAsMetadata::get(B.getInt32(TypedBufferElementType)));278Entries.emplace_back(ConstantAsMetadata::get(279B.getInt32(static_cast<uint32_t>(*ElementType))));280}281if (Entries.empty())282return nullptr;283return MDNode::get(Ctx, Entries);284}285286void ResourceBase::write(LLVMContext &Ctx,287MutableArrayRef<Metadata *> Entries) const {288IRBuilder<> B(Ctx);289Entries[0] = ConstantAsMetadata::get(B.getInt32(ID));290Entries[1] = ConstantAsMetadata::get(GV);291Entries[2] = MDString::get(Ctx, Name);292Entries[3] = ConstantAsMetadata::get(B.getInt32(Space));293Entries[4] = ConstantAsMetadata::get(B.getInt32(LowerBound));294Entries[5] = ConstantAsMetadata::get(B.getInt32(RangeSize));295}296297MDNode *UAVResource::write() const {298auto &Ctx = GV->getContext();299IRBuilder<> B(Ctx);300Metadata *Entries[11];301ResourceBase::write(Ctx, Entries);302Entries[6] =303ConstantAsMetadata::get(B.getInt32(static_cast<uint32_t>(Shape)));304Entries[7] = ConstantAsMetadata::get(B.getInt1(GloballyCoherent));305Entries[8] = ConstantAsMetadata::get(B.getInt1(HasCounter));306Entries[9] = ConstantAsMetadata::get(B.getInt1(IsROV));307Entries[10] = ExtProps.write(Ctx);308return MDNode::get(Ctx, Entries);309}310311MDNode *ConstantBuffer::write() const {312auto &Ctx = GV->getContext();313IRBuilder<> B(Ctx);314Metadata *Entries[7];315ResourceBase::write(Ctx, Entries);316317Entries[6] = ConstantAsMetadata::get(B.getInt32(CBufferSizeInBytes));318return MDNode::get(Ctx, Entries);319}320321template <typename T> MDNode *ResourceTable<T>::write(Module &M) const {322if (Data.empty())323return nullptr;324SmallVector<Metadata *> MDs;325for (auto &Res : Data)326MDs.emplace_back(Res.write());327328NamedMDNode *Entry = M.getNamedMetadata(MDName);329if (Entry)330Entry->eraseFromParent();331332return MDNode::get(M.getContext(), MDs);333}334335void Resources::write(Module &M) const {336Metadata *ResourceMDs[4] = {nullptr, nullptr, nullptr, nullptr};337338ResourceMDs[1] = UAVs.write(M);339340ResourceMDs[2] = CBuffers.write(M);341342bool HasResource = ResourceMDs[0] != nullptr || ResourceMDs[1] != nullptr ||343ResourceMDs[2] != nullptr || ResourceMDs[3] != nullptr;344345if (HasResource) {346NamedMDNode *DXResMD = M.getOrInsertNamedMetadata("dx.resources");347DXResMD->addOperand(MDNode::get(M.getContext(), ResourceMDs));348}349350NamedMDNode *Entry = M.getNamedMetadata("hlsl.uavs");351if (Entry)352Entry->eraseFromParent();353}354355void Resources::print(raw_ostream &O) const {356O << ";\n"357<< "; Resource Bindings:\n"358<< ";\n"359<< "; Name Type Format Dim "360"ID HLSL Bind Count\n"361<< "; ------------------------------ ---------- ------- ----------- "362"------- -------------- ------\n";363364CBuffers.print(O);365UAVs.print(O);366}367368void Resources::dump() const { print(dbgs()); }369370371