1bdd1243dSDimitry Andric //===- DXILResource.cpp - DXIL Resource helper objects --------------------===// 2bdd1243dSDimitry Andric // 3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bdd1243dSDimitry Andric // 7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8bdd1243dSDimitry Andric /// 9bdd1243dSDimitry Andric /// \file This file contains helper objects for working with DXIL Resources. 10bdd1243dSDimitry Andric /// 11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12bdd1243dSDimitry Andric 13bdd1243dSDimitry Andric #include "DXILResource.h" 14bdd1243dSDimitry Andric #include "CBufferDataLayout.h" 15bdd1243dSDimitry Andric #include "llvm/ADT/StringSwitch.h" 16bdd1243dSDimitry Andric #include "llvm/IR/IRBuilder.h" 17bdd1243dSDimitry Andric #include "llvm/IR/Metadata.h" 18bdd1243dSDimitry Andric #include "llvm/IR/Module.h" 19bdd1243dSDimitry Andric #include "llvm/Support/Debug.h" 20bdd1243dSDimitry Andric #include "llvm/Support/Format.h" 21bdd1243dSDimitry Andric 22bdd1243dSDimitry Andric using namespace llvm; 23bdd1243dSDimitry Andric using namespace llvm::dxil; 24bdd1243dSDimitry Andric 25bdd1243dSDimitry Andric template <typename T> void ResourceTable<T>::collect(Module &M) { 26bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata(MDName); 27bdd1243dSDimitry Andric if (!Entry || Entry->getNumOperands() == 0) 28bdd1243dSDimitry Andric return; 29bdd1243dSDimitry Andric 30bdd1243dSDimitry Andric uint32_t Counter = 0; 31bdd1243dSDimitry Andric for (auto *Res : Entry->operands()) { 32*0fca6ea1SDimitry Andric Data.push_back(T(Counter++, hlsl::FrontendResource(cast<MDNode>(Res)))); 33bdd1243dSDimitry Andric } 34bdd1243dSDimitry Andric } 35bdd1243dSDimitry Andric 36bdd1243dSDimitry Andric template <> void ResourceTable<ConstantBuffer>::collect(Module &M) { 37bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata(MDName); 38bdd1243dSDimitry Andric if (!Entry || Entry->getNumOperands() == 0) 39bdd1243dSDimitry Andric return; 40bdd1243dSDimitry Andric 41bdd1243dSDimitry Andric uint32_t Counter = 0; 42bdd1243dSDimitry Andric for (auto *Res : Entry->operands()) { 43bdd1243dSDimitry Andric Data.push_back( 44*0fca6ea1SDimitry Andric ConstantBuffer(Counter++, hlsl::FrontendResource(cast<MDNode>(Res)))); 45bdd1243dSDimitry Andric } 46bdd1243dSDimitry Andric // FIXME: share CBufferDataLayout with CBuffer load lowering. 47bdd1243dSDimitry Andric // See https://github.com/llvm/llvm-project/issues/58381 48bdd1243dSDimitry Andric CBufferDataLayout CBDL(M.getDataLayout(), /*IsLegacy*/ true); 49bdd1243dSDimitry Andric for (auto &CB : Data) 50bdd1243dSDimitry Andric CB.setSize(CBDL); 51bdd1243dSDimitry Andric } 52bdd1243dSDimitry Andric 53bdd1243dSDimitry Andric void Resources::collect(Module &M) { 54bdd1243dSDimitry Andric UAVs.collect(M); 55bdd1243dSDimitry Andric CBuffers.collect(M); 56bdd1243dSDimitry Andric } 57bdd1243dSDimitry Andric 58*0fca6ea1SDimitry Andric ResourceBase::ResourceBase(uint32_t I, hlsl::FrontendResource R) 59bdd1243dSDimitry Andric : ID(I), GV(R.getGlobalVariable()), Name(""), Space(R.getSpace()), 60bdd1243dSDimitry Andric LowerBound(R.getResourceIndex()), RangeSize(1) { 61bdd1243dSDimitry Andric if (auto *ArrTy = dyn_cast<ArrayType>(GV->getValueType())) 62bdd1243dSDimitry Andric RangeSize = ArrTy->getNumElements(); 63bdd1243dSDimitry Andric } 64bdd1243dSDimitry Andric 65cb14a3feSDimitry Andric StringRef ResourceBase::getElementTypeName(ElementType ElTy) { 66cb14a3feSDimitry Andric switch (ElTy) { 67cb14a3feSDimitry Andric case ElementType::Invalid: 68bdd1243dSDimitry Andric return "invalid"; 69cb14a3feSDimitry Andric case ElementType::I1: 70bdd1243dSDimitry Andric return "i1"; 71cb14a3feSDimitry Andric case ElementType::I16: 72bdd1243dSDimitry Andric return "i16"; 73cb14a3feSDimitry Andric case ElementType::U16: 74bdd1243dSDimitry Andric return "u16"; 75cb14a3feSDimitry Andric case ElementType::I32: 76bdd1243dSDimitry Andric return "i32"; 77cb14a3feSDimitry Andric case ElementType::U32: 78bdd1243dSDimitry Andric return "u32"; 79cb14a3feSDimitry Andric case ElementType::I64: 80bdd1243dSDimitry Andric return "i64"; 81cb14a3feSDimitry Andric case ElementType::U64: 82bdd1243dSDimitry Andric return "u64"; 83cb14a3feSDimitry Andric case ElementType::F16: 84bdd1243dSDimitry Andric return "f16"; 85cb14a3feSDimitry Andric case ElementType::F32: 86bdd1243dSDimitry Andric return "f32"; 87cb14a3feSDimitry Andric case ElementType::F64: 88bdd1243dSDimitry Andric return "f64"; 89cb14a3feSDimitry Andric case ElementType::SNormF16: 90bdd1243dSDimitry Andric return "snorm_f16"; 91cb14a3feSDimitry Andric case ElementType::UNormF16: 92bdd1243dSDimitry Andric return "unorm_f16"; 93cb14a3feSDimitry Andric case ElementType::SNormF32: 94bdd1243dSDimitry Andric return "snorm_f32"; 95cb14a3feSDimitry Andric case ElementType::UNormF32: 96bdd1243dSDimitry Andric return "unorm_f32"; 97cb14a3feSDimitry Andric case ElementType::SNormF64: 98bdd1243dSDimitry Andric return "snorm_f64"; 99cb14a3feSDimitry Andric case ElementType::UNormF64: 100bdd1243dSDimitry Andric return "unorm_f64"; 101cb14a3feSDimitry Andric case ElementType::PackedS8x32: 102bdd1243dSDimitry Andric return "p32i8"; 103cb14a3feSDimitry Andric case ElementType::PackedU8x32: 104bdd1243dSDimitry Andric return "p32u8"; 105bdd1243dSDimitry Andric } 106cb14a3feSDimitry Andric llvm_unreachable("All ElementType enums are handled in switch"); 107bdd1243dSDimitry Andric } 108bdd1243dSDimitry Andric 109*0fca6ea1SDimitry Andric void ResourceBase::printElementType(ResourceKind Kind, ElementType ElTy, 110bdd1243dSDimitry Andric unsigned Alignment, raw_ostream &OS) { 111bdd1243dSDimitry Andric switch (Kind) { 112bdd1243dSDimitry Andric default: 113bdd1243dSDimitry Andric // TODO: add vector size. 114cb14a3feSDimitry Andric OS << right_justify(getElementTypeName(ElTy), Alignment); 115bdd1243dSDimitry Andric break; 116*0fca6ea1SDimitry Andric case ResourceKind::RawBuffer: 117bdd1243dSDimitry Andric OS << right_justify("byte", Alignment); 118bdd1243dSDimitry Andric break; 119*0fca6ea1SDimitry Andric case ResourceKind::StructuredBuffer: 120bdd1243dSDimitry Andric OS << right_justify("struct", Alignment); 121bdd1243dSDimitry Andric break; 122*0fca6ea1SDimitry Andric case ResourceKind::CBuffer: 123*0fca6ea1SDimitry Andric case ResourceKind::Sampler: 124bdd1243dSDimitry Andric OS << right_justify("NA", Alignment); 125bdd1243dSDimitry Andric break; 126*0fca6ea1SDimitry Andric case ResourceKind::Invalid: 127*0fca6ea1SDimitry Andric case ResourceKind::NumEntries: 128bdd1243dSDimitry Andric break; 129bdd1243dSDimitry Andric } 130bdd1243dSDimitry Andric } 131bdd1243dSDimitry Andric 132*0fca6ea1SDimitry Andric StringRef ResourceBase::getKindName(ResourceKind Kind) { 133bdd1243dSDimitry Andric switch (Kind) { 134*0fca6ea1SDimitry Andric case ResourceKind::NumEntries: 135*0fca6ea1SDimitry Andric case ResourceKind::Invalid: 136bdd1243dSDimitry Andric return "invalid"; 137*0fca6ea1SDimitry Andric case ResourceKind::Texture1D: 138bdd1243dSDimitry Andric return "1d"; 139*0fca6ea1SDimitry Andric case ResourceKind::Texture2D: 140bdd1243dSDimitry Andric return "2d"; 141*0fca6ea1SDimitry Andric case ResourceKind::Texture2DMS: 142bdd1243dSDimitry Andric return "2dMS"; 143*0fca6ea1SDimitry Andric case ResourceKind::Texture3D: 144bdd1243dSDimitry Andric return "3d"; 145*0fca6ea1SDimitry Andric case ResourceKind::TextureCube: 146bdd1243dSDimitry Andric return "cube"; 147*0fca6ea1SDimitry Andric case ResourceKind::Texture1DArray: 148bdd1243dSDimitry Andric return "1darray"; 149*0fca6ea1SDimitry Andric case ResourceKind::Texture2DArray: 150bdd1243dSDimitry Andric return "2darray"; 151*0fca6ea1SDimitry Andric case ResourceKind::Texture2DMSArray: 152bdd1243dSDimitry Andric return "2darrayMS"; 153*0fca6ea1SDimitry Andric case ResourceKind::TextureCubeArray: 154bdd1243dSDimitry Andric return "cubearray"; 155*0fca6ea1SDimitry Andric case ResourceKind::TypedBuffer: 156bdd1243dSDimitry Andric return "buf"; 157*0fca6ea1SDimitry Andric case ResourceKind::RawBuffer: 158bdd1243dSDimitry Andric return "rawbuf"; 159*0fca6ea1SDimitry Andric case ResourceKind::StructuredBuffer: 160bdd1243dSDimitry Andric return "structbuf"; 161*0fca6ea1SDimitry Andric case ResourceKind::CBuffer: 162bdd1243dSDimitry Andric return "cbuffer"; 163*0fca6ea1SDimitry Andric case ResourceKind::Sampler: 164bdd1243dSDimitry Andric return "sampler"; 165*0fca6ea1SDimitry Andric case ResourceKind::TBuffer: 166bdd1243dSDimitry Andric return "tbuffer"; 167*0fca6ea1SDimitry Andric case ResourceKind::RTAccelerationStructure: 168bdd1243dSDimitry Andric return "ras"; 169*0fca6ea1SDimitry Andric case ResourceKind::FeedbackTexture2D: 170bdd1243dSDimitry Andric return "fbtex2d"; 171*0fca6ea1SDimitry Andric case ResourceKind::FeedbackTexture2DArray: 172bdd1243dSDimitry Andric return "fbtex2darray"; 173bdd1243dSDimitry Andric } 174*0fca6ea1SDimitry Andric llvm_unreachable("All ResourceKind enums are handled in switch"); 175bdd1243dSDimitry Andric } 176bdd1243dSDimitry Andric 177*0fca6ea1SDimitry Andric void ResourceBase::printKind(ResourceKind Kind, unsigned Alignment, 178*0fca6ea1SDimitry Andric raw_ostream &OS, bool SRV, bool HasCounter, 179*0fca6ea1SDimitry Andric uint32_t SampleCount) { 180bdd1243dSDimitry Andric switch (Kind) { 181bdd1243dSDimitry Andric default: 182bdd1243dSDimitry Andric OS << right_justify(getKindName(Kind), Alignment); 183bdd1243dSDimitry Andric break; 184bdd1243dSDimitry Andric 185*0fca6ea1SDimitry Andric case ResourceKind::RawBuffer: 186*0fca6ea1SDimitry Andric case ResourceKind::StructuredBuffer: 187bdd1243dSDimitry Andric if (SRV) 188bdd1243dSDimitry Andric OS << right_justify("r/o", Alignment); 189bdd1243dSDimitry Andric else { 190bdd1243dSDimitry Andric if (!HasCounter) 191bdd1243dSDimitry Andric OS << right_justify("r/w", Alignment); 192bdd1243dSDimitry Andric else 193bdd1243dSDimitry Andric OS << right_justify("r/w+cnt", Alignment); 194bdd1243dSDimitry Andric } 195bdd1243dSDimitry Andric break; 196*0fca6ea1SDimitry Andric case ResourceKind::TypedBuffer: 197bdd1243dSDimitry Andric OS << right_justify("buf", Alignment); 198bdd1243dSDimitry Andric break; 199*0fca6ea1SDimitry Andric case ResourceKind::Texture2DMS: 200*0fca6ea1SDimitry Andric case ResourceKind::Texture2DMSArray: { 201bdd1243dSDimitry Andric std::string DimName = getKindName(Kind).str(); 202bdd1243dSDimitry Andric if (SampleCount) 203bdd1243dSDimitry Andric DimName += std::to_string(SampleCount); 204bdd1243dSDimitry Andric OS << right_justify(DimName, Alignment); 205bdd1243dSDimitry Andric } break; 206*0fca6ea1SDimitry Andric case ResourceKind::CBuffer: 207*0fca6ea1SDimitry Andric case ResourceKind::Sampler: 208bdd1243dSDimitry Andric OS << right_justify("NA", Alignment); 209bdd1243dSDimitry Andric break; 210*0fca6ea1SDimitry Andric case ResourceKind::Invalid: 211*0fca6ea1SDimitry Andric case ResourceKind::NumEntries: 212bdd1243dSDimitry Andric break; 213bdd1243dSDimitry Andric } 214bdd1243dSDimitry Andric } 215bdd1243dSDimitry Andric 216bdd1243dSDimitry Andric void ResourceBase::print(raw_ostream &OS, StringRef IDPrefix, 217bdd1243dSDimitry Andric StringRef BindingPrefix) const { 218bdd1243dSDimitry Andric std::string ResID = IDPrefix.str(); 219bdd1243dSDimitry Andric ResID += std::to_string(ID); 220bdd1243dSDimitry Andric OS << right_justify(ResID, 8); 221bdd1243dSDimitry Andric 222bdd1243dSDimitry Andric std::string Bind = BindingPrefix.str(); 223bdd1243dSDimitry Andric Bind += std::to_string(LowerBound); 224bdd1243dSDimitry Andric if (Space) 225bdd1243dSDimitry Andric Bind += ",space" + std::to_string(Space); 226bdd1243dSDimitry Andric 227bdd1243dSDimitry Andric OS << right_justify(Bind, 15); 228bdd1243dSDimitry Andric if (RangeSize != UINT_MAX) 229bdd1243dSDimitry Andric OS << right_justify(std::to_string(RangeSize), 6) << "\n"; 230bdd1243dSDimitry Andric else 231bdd1243dSDimitry Andric OS << right_justify("unbounded", 6) << "\n"; 232bdd1243dSDimitry Andric } 233bdd1243dSDimitry Andric 234bdd1243dSDimitry Andric void UAVResource::print(raw_ostream &OS) const { 235bdd1243dSDimitry Andric OS << "; " << left_justify(Name, 31); 236bdd1243dSDimitry Andric 237bdd1243dSDimitry Andric OS << right_justify("UAV", 10); 238bdd1243dSDimitry Andric 239cb14a3feSDimitry Andric printElementType(Shape, ExtProps.ElementType.value_or(ElementType::Invalid), 240cb14a3feSDimitry Andric 8, OS); 241bdd1243dSDimitry Andric 242bdd1243dSDimitry Andric // FIXME: support SampleCount. 243bdd1243dSDimitry Andric // See https://github.com/llvm/llvm-project/issues/58175 244bdd1243dSDimitry Andric printKind(Shape, 12, OS, /*SRV*/ false, HasCounter); 245bdd1243dSDimitry Andric // Print the binding part. 246bdd1243dSDimitry Andric ResourceBase::print(OS, "U", "u"); 247bdd1243dSDimitry Andric } 248bdd1243dSDimitry Andric 249bdd1243dSDimitry Andric ConstantBuffer::ConstantBuffer(uint32_t I, hlsl::FrontendResource R) 250bdd1243dSDimitry Andric : ResourceBase(I, R) {} 251bdd1243dSDimitry Andric 252bdd1243dSDimitry Andric void ConstantBuffer::setSize(CBufferDataLayout &DL) { 253bdd1243dSDimitry Andric CBufferSizeInBytes = DL.getTypeAllocSizeInBytes(GV->getValueType()); 254bdd1243dSDimitry Andric } 255bdd1243dSDimitry Andric 256bdd1243dSDimitry Andric void ConstantBuffer::print(raw_ostream &OS) const { 257bdd1243dSDimitry Andric OS << "; " << left_justify(Name, 31); 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric OS << right_justify("cbuffer", 10); 260bdd1243dSDimitry Andric 261*0fca6ea1SDimitry Andric printElementType(ResourceKind::CBuffer, ElementType::Invalid, 8, OS); 262bdd1243dSDimitry Andric 263*0fca6ea1SDimitry Andric printKind(ResourceKind::CBuffer, 12, OS, /*SRV*/ false, /*HasCounter*/ false); 264bdd1243dSDimitry Andric // Print the binding part. 265bdd1243dSDimitry Andric ResourceBase::print(OS, "CB", "cb"); 266bdd1243dSDimitry Andric } 267bdd1243dSDimitry Andric 268bdd1243dSDimitry Andric template <typename T> void ResourceTable<T>::print(raw_ostream &OS) const { 269bdd1243dSDimitry Andric for (auto &Res : Data) 270bdd1243dSDimitry Andric Res.print(OS); 271bdd1243dSDimitry Andric } 272bdd1243dSDimitry Andric 273bdd1243dSDimitry Andric MDNode *ResourceBase::ExtendedProperties::write(LLVMContext &Ctx) const { 274bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 275bdd1243dSDimitry Andric SmallVector<Metadata *> Entries; 276bdd1243dSDimitry Andric if (ElementType) { 277bdd1243dSDimitry Andric Entries.emplace_back( 278bdd1243dSDimitry Andric ConstantAsMetadata::get(B.getInt32(TypedBufferElementType))); 279bdd1243dSDimitry Andric Entries.emplace_back(ConstantAsMetadata::get( 280bdd1243dSDimitry Andric B.getInt32(static_cast<uint32_t>(*ElementType)))); 281bdd1243dSDimitry Andric } 282bdd1243dSDimitry Andric if (Entries.empty()) 283bdd1243dSDimitry Andric return nullptr; 284bdd1243dSDimitry Andric return MDNode::get(Ctx, Entries); 285bdd1243dSDimitry Andric } 286bdd1243dSDimitry Andric 287bdd1243dSDimitry Andric void ResourceBase::write(LLVMContext &Ctx, 288bdd1243dSDimitry Andric MutableArrayRef<Metadata *> Entries) const { 289bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 290bdd1243dSDimitry Andric Entries[0] = ConstantAsMetadata::get(B.getInt32(ID)); 291bdd1243dSDimitry Andric Entries[1] = ConstantAsMetadata::get(GV); 292bdd1243dSDimitry Andric Entries[2] = MDString::get(Ctx, Name); 293bdd1243dSDimitry Andric Entries[3] = ConstantAsMetadata::get(B.getInt32(Space)); 294bdd1243dSDimitry Andric Entries[4] = ConstantAsMetadata::get(B.getInt32(LowerBound)); 295bdd1243dSDimitry Andric Entries[5] = ConstantAsMetadata::get(B.getInt32(RangeSize)); 296bdd1243dSDimitry Andric } 297bdd1243dSDimitry Andric 298bdd1243dSDimitry Andric MDNode *UAVResource::write() const { 299bdd1243dSDimitry Andric auto &Ctx = GV->getContext(); 300bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 301bdd1243dSDimitry Andric Metadata *Entries[11]; 302bdd1243dSDimitry Andric ResourceBase::write(Ctx, Entries); 303bdd1243dSDimitry Andric Entries[6] = 304bdd1243dSDimitry Andric ConstantAsMetadata::get(B.getInt32(static_cast<uint32_t>(Shape))); 305bdd1243dSDimitry Andric Entries[7] = ConstantAsMetadata::get(B.getInt1(GloballyCoherent)); 306bdd1243dSDimitry Andric Entries[8] = ConstantAsMetadata::get(B.getInt1(HasCounter)); 307bdd1243dSDimitry Andric Entries[9] = ConstantAsMetadata::get(B.getInt1(IsROV)); 308bdd1243dSDimitry Andric Entries[10] = ExtProps.write(Ctx); 309bdd1243dSDimitry Andric return MDNode::get(Ctx, Entries); 310bdd1243dSDimitry Andric } 311bdd1243dSDimitry Andric 312bdd1243dSDimitry Andric MDNode *ConstantBuffer::write() const { 313bdd1243dSDimitry Andric auto &Ctx = GV->getContext(); 314bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 315bdd1243dSDimitry Andric Metadata *Entries[7]; 316bdd1243dSDimitry Andric ResourceBase::write(Ctx, Entries); 317bdd1243dSDimitry Andric 318bdd1243dSDimitry Andric Entries[6] = ConstantAsMetadata::get(B.getInt32(CBufferSizeInBytes)); 319bdd1243dSDimitry Andric return MDNode::get(Ctx, Entries); 320bdd1243dSDimitry Andric } 321bdd1243dSDimitry Andric 322bdd1243dSDimitry Andric template <typename T> MDNode *ResourceTable<T>::write(Module &M) const { 323bdd1243dSDimitry Andric if (Data.empty()) 324bdd1243dSDimitry Andric return nullptr; 325bdd1243dSDimitry Andric SmallVector<Metadata *> MDs; 326bdd1243dSDimitry Andric for (auto &Res : Data) 327bdd1243dSDimitry Andric MDs.emplace_back(Res.write()); 328bdd1243dSDimitry Andric 329bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata(MDName); 330bdd1243dSDimitry Andric if (Entry) 331bdd1243dSDimitry Andric Entry->eraseFromParent(); 332bdd1243dSDimitry Andric 333bdd1243dSDimitry Andric return MDNode::get(M.getContext(), MDs); 334bdd1243dSDimitry Andric } 335bdd1243dSDimitry Andric 336bdd1243dSDimitry Andric void Resources::write(Module &M) const { 337bdd1243dSDimitry Andric Metadata *ResourceMDs[4] = {nullptr, nullptr, nullptr, nullptr}; 338bdd1243dSDimitry Andric 339bdd1243dSDimitry Andric ResourceMDs[1] = UAVs.write(M); 340bdd1243dSDimitry Andric 341bdd1243dSDimitry Andric ResourceMDs[2] = CBuffers.write(M); 342bdd1243dSDimitry Andric 343bdd1243dSDimitry Andric bool HasResource = ResourceMDs[0] != nullptr || ResourceMDs[1] != nullptr || 344bdd1243dSDimitry Andric ResourceMDs[2] != nullptr || ResourceMDs[3] != nullptr; 345bdd1243dSDimitry Andric 346bdd1243dSDimitry Andric if (HasResource) { 347bdd1243dSDimitry Andric NamedMDNode *DXResMD = M.getOrInsertNamedMetadata("dx.resources"); 348bdd1243dSDimitry Andric DXResMD->addOperand(MDNode::get(M.getContext(), ResourceMDs)); 349bdd1243dSDimitry Andric } 350bdd1243dSDimitry Andric 351bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata("hlsl.uavs"); 352bdd1243dSDimitry Andric if (Entry) 353bdd1243dSDimitry Andric Entry->eraseFromParent(); 354bdd1243dSDimitry Andric } 355bdd1243dSDimitry Andric 356bdd1243dSDimitry Andric void Resources::print(raw_ostream &O) const { 357bdd1243dSDimitry Andric O << ";\n" 358bdd1243dSDimitry Andric << "; Resource Bindings:\n" 359bdd1243dSDimitry Andric << ";\n" 360bdd1243dSDimitry Andric << "; Name Type Format Dim " 361bdd1243dSDimitry Andric "ID HLSL Bind Count\n" 362bdd1243dSDimitry Andric << "; ------------------------------ ---------- ------- ----------- " 363bdd1243dSDimitry Andric "------- -------------- ------\n"; 364bdd1243dSDimitry Andric 365bdd1243dSDimitry Andric CBuffers.print(O); 366bdd1243dSDimitry Andric UAVs.print(O); 367bdd1243dSDimitry Andric } 368bdd1243dSDimitry Andric 369bdd1243dSDimitry Andric void Resources::dump() const { print(dbgs()); } 370