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 using namespace llvm::hlsl; 25bdd1243dSDimitry Andric 26bdd1243dSDimitry Andric template <typename T> void ResourceTable<T>::collect(Module &M) { 27bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata(MDName); 28bdd1243dSDimitry Andric if (!Entry || Entry->getNumOperands() == 0) 29bdd1243dSDimitry Andric return; 30bdd1243dSDimitry Andric 31bdd1243dSDimitry Andric uint32_t Counter = 0; 32bdd1243dSDimitry Andric for (auto *Res : Entry->operands()) { 33bdd1243dSDimitry Andric Data.push_back(T(Counter++, FrontendResource(cast<MDNode>(Res)))); 34bdd1243dSDimitry Andric } 35bdd1243dSDimitry Andric } 36bdd1243dSDimitry Andric 37bdd1243dSDimitry Andric template <> void ResourceTable<ConstantBuffer>::collect(Module &M) { 38bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata(MDName); 39bdd1243dSDimitry Andric if (!Entry || Entry->getNumOperands() == 0) 40bdd1243dSDimitry Andric return; 41bdd1243dSDimitry Andric 42bdd1243dSDimitry Andric uint32_t Counter = 0; 43bdd1243dSDimitry Andric for (auto *Res : Entry->operands()) { 44bdd1243dSDimitry Andric Data.push_back( 45bdd1243dSDimitry Andric ConstantBuffer(Counter++, FrontendResource(cast<MDNode>(Res)))); 46bdd1243dSDimitry Andric } 47bdd1243dSDimitry Andric // FIXME: share CBufferDataLayout with CBuffer load lowering. 48bdd1243dSDimitry Andric // See https://github.com/llvm/llvm-project/issues/58381 49bdd1243dSDimitry Andric CBufferDataLayout CBDL(M.getDataLayout(), /*IsLegacy*/ true); 50bdd1243dSDimitry Andric for (auto &CB : Data) 51bdd1243dSDimitry Andric CB.setSize(CBDL); 52bdd1243dSDimitry Andric } 53bdd1243dSDimitry Andric 54bdd1243dSDimitry Andric void Resources::collect(Module &M) { 55bdd1243dSDimitry Andric UAVs.collect(M); 56bdd1243dSDimitry Andric CBuffers.collect(M); 57bdd1243dSDimitry Andric } 58bdd1243dSDimitry Andric 59bdd1243dSDimitry Andric ResourceBase::ResourceBase(uint32_t I, FrontendResource R) 60bdd1243dSDimitry Andric : ID(I), GV(R.getGlobalVariable()), Name(""), Space(R.getSpace()), 61bdd1243dSDimitry Andric LowerBound(R.getResourceIndex()), RangeSize(1) { 62bdd1243dSDimitry Andric if (auto *ArrTy = dyn_cast<ArrayType>(GV->getValueType())) 63bdd1243dSDimitry Andric RangeSize = ArrTy->getNumElements(); 64bdd1243dSDimitry Andric } 65bdd1243dSDimitry Andric 66bdd1243dSDimitry Andric StringRef ResourceBase::getComponentTypeName(ComponentType CompType) { 67bdd1243dSDimitry Andric switch (CompType) { 68bdd1243dSDimitry Andric case ComponentType::LastEntry: 69bdd1243dSDimitry Andric case ComponentType::Invalid: 70bdd1243dSDimitry Andric return "invalid"; 71bdd1243dSDimitry Andric case ComponentType::I1: 72bdd1243dSDimitry Andric return "i1"; 73bdd1243dSDimitry Andric case ComponentType::I16: 74bdd1243dSDimitry Andric return "i16"; 75bdd1243dSDimitry Andric case ComponentType::U16: 76bdd1243dSDimitry Andric return "u16"; 77bdd1243dSDimitry Andric case ComponentType::I32: 78bdd1243dSDimitry Andric return "i32"; 79bdd1243dSDimitry Andric case ComponentType::U32: 80bdd1243dSDimitry Andric return "u32"; 81bdd1243dSDimitry Andric case ComponentType::I64: 82bdd1243dSDimitry Andric return "i64"; 83bdd1243dSDimitry Andric case ComponentType::U64: 84bdd1243dSDimitry Andric return "u64"; 85bdd1243dSDimitry Andric case ComponentType::F16: 86bdd1243dSDimitry Andric return "f16"; 87bdd1243dSDimitry Andric case ComponentType::F32: 88bdd1243dSDimitry Andric return "f32"; 89bdd1243dSDimitry Andric case ComponentType::F64: 90bdd1243dSDimitry Andric return "f64"; 91bdd1243dSDimitry Andric case ComponentType::SNormF16: 92bdd1243dSDimitry Andric return "snorm_f16"; 93bdd1243dSDimitry Andric case ComponentType::UNormF16: 94bdd1243dSDimitry Andric return "unorm_f16"; 95bdd1243dSDimitry Andric case ComponentType::SNormF32: 96bdd1243dSDimitry Andric return "snorm_f32"; 97bdd1243dSDimitry Andric case ComponentType::UNormF32: 98bdd1243dSDimitry Andric return "unorm_f32"; 99bdd1243dSDimitry Andric case ComponentType::SNormF64: 100bdd1243dSDimitry Andric return "snorm_f64"; 101bdd1243dSDimitry Andric case ComponentType::UNormF64: 102bdd1243dSDimitry Andric return "unorm_f64"; 103bdd1243dSDimitry Andric case ComponentType::PackedS8x32: 104bdd1243dSDimitry Andric return "p32i8"; 105bdd1243dSDimitry Andric case ComponentType::PackedU8x32: 106bdd1243dSDimitry Andric return "p32u8"; 107bdd1243dSDimitry Andric } 108*06c3fb27SDimitry Andric llvm_unreachable("All ComponentType enums are handled in switch"); 109bdd1243dSDimitry Andric } 110bdd1243dSDimitry Andric 111bdd1243dSDimitry Andric void ResourceBase::printComponentType(Kinds Kind, ComponentType CompType, 112bdd1243dSDimitry Andric unsigned Alignment, raw_ostream &OS) { 113bdd1243dSDimitry Andric switch (Kind) { 114bdd1243dSDimitry Andric default: 115bdd1243dSDimitry Andric // TODO: add vector size. 116bdd1243dSDimitry Andric OS << right_justify(getComponentTypeName(CompType), Alignment); 117bdd1243dSDimitry Andric break; 118bdd1243dSDimitry Andric case Kinds::RawBuffer: 119bdd1243dSDimitry Andric OS << right_justify("byte", Alignment); 120bdd1243dSDimitry Andric break; 121bdd1243dSDimitry Andric case Kinds::StructuredBuffer: 122bdd1243dSDimitry Andric OS << right_justify("struct", Alignment); 123bdd1243dSDimitry Andric break; 124bdd1243dSDimitry Andric case Kinds::CBuffer: 125bdd1243dSDimitry Andric case Kinds::Sampler: 126bdd1243dSDimitry Andric OS << right_justify("NA", Alignment); 127bdd1243dSDimitry Andric break; 128bdd1243dSDimitry Andric case Kinds::Invalid: 129bdd1243dSDimitry Andric case Kinds::NumEntries: 130bdd1243dSDimitry Andric break; 131bdd1243dSDimitry Andric } 132bdd1243dSDimitry Andric } 133bdd1243dSDimitry Andric 134bdd1243dSDimitry Andric StringRef ResourceBase::getKindName(Kinds Kind) { 135bdd1243dSDimitry Andric switch (Kind) { 136bdd1243dSDimitry Andric case Kinds::NumEntries: 137bdd1243dSDimitry Andric case Kinds::Invalid: 138bdd1243dSDimitry Andric return "invalid"; 139bdd1243dSDimitry Andric case Kinds::Texture1D: 140bdd1243dSDimitry Andric return "1d"; 141bdd1243dSDimitry Andric case Kinds::Texture2D: 142bdd1243dSDimitry Andric return "2d"; 143bdd1243dSDimitry Andric case Kinds::Texture2DMS: 144bdd1243dSDimitry Andric return "2dMS"; 145bdd1243dSDimitry Andric case Kinds::Texture3D: 146bdd1243dSDimitry Andric return "3d"; 147bdd1243dSDimitry Andric case Kinds::TextureCube: 148bdd1243dSDimitry Andric return "cube"; 149bdd1243dSDimitry Andric case Kinds::Texture1DArray: 150bdd1243dSDimitry Andric return "1darray"; 151bdd1243dSDimitry Andric case Kinds::Texture2DArray: 152bdd1243dSDimitry Andric return "2darray"; 153bdd1243dSDimitry Andric case Kinds::Texture2DMSArray: 154bdd1243dSDimitry Andric return "2darrayMS"; 155bdd1243dSDimitry Andric case Kinds::TextureCubeArray: 156bdd1243dSDimitry Andric return "cubearray"; 157bdd1243dSDimitry Andric case Kinds::TypedBuffer: 158bdd1243dSDimitry Andric return "buf"; 159bdd1243dSDimitry Andric case Kinds::RawBuffer: 160bdd1243dSDimitry Andric return "rawbuf"; 161bdd1243dSDimitry Andric case Kinds::StructuredBuffer: 162bdd1243dSDimitry Andric return "structbuf"; 163bdd1243dSDimitry Andric case Kinds::CBuffer: 164bdd1243dSDimitry Andric return "cbuffer"; 165bdd1243dSDimitry Andric case Kinds::Sampler: 166bdd1243dSDimitry Andric return "sampler"; 167bdd1243dSDimitry Andric case Kinds::TBuffer: 168bdd1243dSDimitry Andric return "tbuffer"; 169bdd1243dSDimitry Andric case Kinds::RTAccelerationStructure: 170bdd1243dSDimitry Andric return "ras"; 171bdd1243dSDimitry Andric case Kinds::FeedbackTexture2D: 172bdd1243dSDimitry Andric return "fbtex2d"; 173bdd1243dSDimitry Andric case Kinds::FeedbackTexture2DArray: 174bdd1243dSDimitry Andric return "fbtex2darray"; 175bdd1243dSDimitry Andric } 176*06c3fb27SDimitry Andric llvm_unreachable("All Kinds enums are handled in switch"); 177bdd1243dSDimitry Andric } 178bdd1243dSDimitry Andric 179bdd1243dSDimitry Andric void ResourceBase::printKind(Kinds Kind, unsigned Alignment, raw_ostream &OS, 180bdd1243dSDimitry Andric bool SRV, bool HasCounter, uint32_t SampleCount) { 181bdd1243dSDimitry Andric switch (Kind) { 182bdd1243dSDimitry Andric default: 183bdd1243dSDimitry Andric OS << right_justify(getKindName(Kind), Alignment); 184bdd1243dSDimitry Andric break; 185bdd1243dSDimitry Andric 186bdd1243dSDimitry Andric case Kinds::RawBuffer: 187bdd1243dSDimitry Andric case Kinds::StructuredBuffer: 188bdd1243dSDimitry Andric if (SRV) 189bdd1243dSDimitry Andric OS << right_justify("r/o", Alignment); 190bdd1243dSDimitry Andric else { 191bdd1243dSDimitry Andric if (!HasCounter) 192bdd1243dSDimitry Andric OS << right_justify("r/w", Alignment); 193bdd1243dSDimitry Andric else 194bdd1243dSDimitry Andric OS << right_justify("r/w+cnt", Alignment); 195bdd1243dSDimitry Andric } 196bdd1243dSDimitry Andric break; 197bdd1243dSDimitry Andric case Kinds::TypedBuffer: 198bdd1243dSDimitry Andric OS << right_justify("buf", Alignment); 199bdd1243dSDimitry Andric break; 200bdd1243dSDimitry Andric case Kinds::Texture2DMS: 201bdd1243dSDimitry Andric case Kinds::Texture2DMSArray: { 202bdd1243dSDimitry Andric std::string DimName = getKindName(Kind).str(); 203bdd1243dSDimitry Andric if (SampleCount) 204bdd1243dSDimitry Andric DimName += std::to_string(SampleCount); 205bdd1243dSDimitry Andric OS << right_justify(DimName, Alignment); 206bdd1243dSDimitry Andric } break; 207bdd1243dSDimitry Andric case Kinds::CBuffer: 208bdd1243dSDimitry Andric case Kinds::Sampler: 209bdd1243dSDimitry Andric OS << right_justify("NA", Alignment); 210bdd1243dSDimitry Andric break; 211bdd1243dSDimitry Andric case Kinds::Invalid: 212bdd1243dSDimitry Andric case Kinds::NumEntries: 213bdd1243dSDimitry Andric break; 214bdd1243dSDimitry Andric } 215bdd1243dSDimitry Andric } 216bdd1243dSDimitry Andric 217bdd1243dSDimitry Andric void ResourceBase::print(raw_ostream &OS, StringRef IDPrefix, 218bdd1243dSDimitry Andric StringRef BindingPrefix) const { 219bdd1243dSDimitry Andric std::string ResID = IDPrefix.str(); 220bdd1243dSDimitry Andric ResID += std::to_string(ID); 221bdd1243dSDimitry Andric OS << right_justify(ResID, 8); 222bdd1243dSDimitry Andric 223bdd1243dSDimitry Andric std::string Bind = BindingPrefix.str(); 224bdd1243dSDimitry Andric Bind += std::to_string(LowerBound); 225bdd1243dSDimitry Andric if (Space) 226bdd1243dSDimitry Andric Bind += ",space" + std::to_string(Space); 227bdd1243dSDimitry Andric 228bdd1243dSDimitry Andric OS << right_justify(Bind, 15); 229bdd1243dSDimitry Andric if (RangeSize != UINT_MAX) 230bdd1243dSDimitry Andric OS << right_justify(std::to_string(RangeSize), 6) << "\n"; 231bdd1243dSDimitry Andric else 232bdd1243dSDimitry Andric OS << right_justify("unbounded", 6) << "\n"; 233bdd1243dSDimitry Andric } 234bdd1243dSDimitry Andric 235bdd1243dSDimitry Andric UAVResource::UAVResource(uint32_t I, FrontendResource R) 236bdd1243dSDimitry Andric : ResourceBase(I, R), 237bdd1243dSDimitry Andric Shape(static_cast<ResourceBase::Kinds>(R.getResourceKind())), 238bdd1243dSDimitry Andric GloballyCoherent(false), HasCounter(false), IsROV(false), ExtProps() { 239bdd1243dSDimitry Andric parseSourceType(R.getSourceType()); 240bdd1243dSDimitry Andric } 241bdd1243dSDimitry Andric 242bdd1243dSDimitry Andric void UAVResource::print(raw_ostream &OS) const { 243bdd1243dSDimitry Andric OS << "; " << left_justify(Name, 31); 244bdd1243dSDimitry Andric 245bdd1243dSDimitry Andric OS << right_justify("UAV", 10); 246bdd1243dSDimitry Andric 247bdd1243dSDimitry Andric printComponentType( 248bdd1243dSDimitry Andric Shape, ExtProps.ElementType.value_or(ComponentType::Invalid), 8, OS); 249bdd1243dSDimitry Andric 250bdd1243dSDimitry Andric // FIXME: support SampleCount. 251bdd1243dSDimitry Andric // See https://github.com/llvm/llvm-project/issues/58175 252bdd1243dSDimitry Andric printKind(Shape, 12, OS, /*SRV*/ false, HasCounter); 253bdd1243dSDimitry Andric // Print the binding part. 254bdd1243dSDimitry Andric ResourceBase::print(OS, "U", "u"); 255bdd1243dSDimitry Andric } 256bdd1243dSDimitry Andric 257bdd1243dSDimitry Andric // FIXME: Capture this in HLSL source. I would go do this right now, but I want 258bdd1243dSDimitry Andric // to get this in first so that I can make sure to capture all the extra 259bdd1243dSDimitry Andric // information we need to remove the source type string from here (See issue: 260bdd1243dSDimitry Andric // https://github.com/llvm/llvm-project/issues/57991). 261bdd1243dSDimitry Andric void UAVResource::parseSourceType(StringRef S) { 262bdd1243dSDimitry Andric IsROV = S.startswith("RasterizerOrdered"); 263bdd1243dSDimitry Andric if (IsROV) 264bdd1243dSDimitry Andric S = S.substr(strlen("RasterizerOrdered")); 265bdd1243dSDimitry Andric if (S.startswith("RW")) 266bdd1243dSDimitry Andric S = S.substr(strlen("RW")); 267bdd1243dSDimitry Andric 268bdd1243dSDimitry Andric // Note: I'm deliberately not handling any of the Texture buffer types at the 269bdd1243dSDimitry Andric // moment. I want to resolve the issue above before adding Texture or Sampler 270bdd1243dSDimitry Andric // support. 271bdd1243dSDimitry Andric Shape = StringSwitch<ResourceBase::Kinds>(S) 272bdd1243dSDimitry Andric .StartsWith("Buffer<", Kinds::TypedBuffer) 273bdd1243dSDimitry Andric .StartsWith("ByteAddressBuffer<", Kinds::RawBuffer) 274bdd1243dSDimitry Andric .StartsWith("StructuredBuffer<", Kinds::StructuredBuffer) 275bdd1243dSDimitry Andric .Default(Kinds::Invalid); 276bdd1243dSDimitry Andric assert(Shape != Kinds::Invalid && "Unsupported buffer type"); 277bdd1243dSDimitry Andric 278bdd1243dSDimitry Andric S = S.substr(S.find("<") + 1); 279bdd1243dSDimitry Andric 280bdd1243dSDimitry Andric constexpr size_t PrefixLen = StringRef("vector<").size(); 281bdd1243dSDimitry Andric if (S.startswith("vector<")) 282bdd1243dSDimitry Andric S = S.substr(PrefixLen, S.find(",") - PrefixLen); 283bdd1243dSDimitry Andric else 284bdd1243dSDimitry Andric S = S.substr(0, S.find(">")); 285bdd1243dSDimitry Andric 286bdd1243dSDimitry Andric ComponentType ElTy = StringSwitch<ResourceBase::ComponentType>(S) 287bdd1243dSDimitry Andric .Case("bool", ComponentType::I1) 288bdd1243dSDimitry Andric .Case("int16_t", ComponentType::I16) 289bdd1243dSDimitry Andric .Case("uint16_t", ComponentType::U16) 290bdd1243dSDimitry Andric .Case("int32_t", ComponentType::I32) 291bdd1243dSDimitry Andric .Case("uint32_t", ComponentType::U32) 292bdd1243dSDimitry Andric .Case("int64_t", ComponentType::I64) 293bdd1243dSDimitry Andric .Case("uint64_t", ComponentType::U64) 294bdd1243dSDimitry Andric .Case("half", ComponentType::F16) 295bdd1243dSDimitry Andric .Case("float", ComponentType::F32) 296bdd1243dSDimitry Andric .Case("double", ComponentType::F64) 297bdd1243dSDimitry Andric .Default(ComponentType::Invalid); 298bdd1243dSDimitry Andric if (ElTy != ComponentType::Invalid) 299bdd1243dSDimitry Andric ExtProps.ElementType = ElTy; 300bdd1243dSDimitry Andric } 301bdd1243dSDimitry Andric 302bdd1243dSDimitry Andric ConstantBuffer::ConstantBuffer(uint32_t I, hlsl::FrontendResource R) 303bdd1243dSDimitry Andric : ResourceBase(I, R) {} 304bdd1243dSDimitry Andric 305bdd1243dSDimitry Andric void ConstantBuffer::setSize(CBufferDataLayout &DL) { 306bdd1243dSDimitry Andric CBufferSizeInBytes = DL.getTypeAllocSizeInBytes(GV->getValueType()); 307bdd1243dSDimitry Andric } 308bdd1243dSDimitry Andric 309bdd1243dSDimitry Andric void ConstantBuffer::print(raw_ostream &OS) const { 310bdd1243dSDimitry Andric OS << "; " << left_justify(Name, 31); 311bdd1243dSDimitry Andric 312bdd1243dSDimitry Andric OS << right_justify("cbuffer", 10); 313bdd1243dSDimitry Andric 314bdd1243dSDimitry Andric printComponentType(Kinds::CBuffer, ComponentType::Invalid, 8, OS); 315bdd1243dSDimitry Andric 316bdd1243dSDimitry Andric printKind(Kinds::CBuffer, 12, OS, /*SRV*/ false, /*HasCounter*/ false); 317bdd1243dSDimitry Andric // Print the binding part. 318bdd1243dSDimitry Andric ResourceBase::print(OS, "CB", "cb"); 319bdd1243dSDimitry Andric } 320bdd1243dSDimitry Andric 321bdd1243dSDimitry Andric template <typename T> void ResourceTable<T>::print(raw_ostream &OS) const { 322bdd1243dSDimitry Andric for (auto &Res : Data) 323bdd1243dSDimitry Andric Res.print(OS); 324bdd1243dSDimitry Andric } 325bdd1243dSDimitry Andric 326bdd1243dSDimitry Andric MDNode *ResourceBase::ExtendedProperties::write(LLVMContext &Ctx) const { 327bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 328bdd1243dSDimitry Andric SmallVector<Metadata *> Entries; 329bdd1243dSDimitry Andric if (ElementType) { 330bdd1243dSDimitry Andric Entries.emplace_back( 331bdd1243dSDimitry Andric ConstantAsMetadata::get(B.getInt32(TypedBufferElementType))); 332bdd1243dSDimitry Andric Entries.emplace_back(ConstantAsMetadata::get( 333bdd1243dSDimitry Andric B.getInt32(static_cast<uint32_t>(*ElementType)))); 334bdd1243dSDimitry Andric } 335bdd1243dSDimitry Andric if (Entries.empty()) 336bdd1243dSDimitry Andric return nullptr; 337bdd1243dSDimitry Andric return MDNode::get(Ctx, Entries); 338bdd1243dSDimitry Andric } 339bdd1243dSDimitry Andric 340bdd1243dSDimitry Andric void ResourceBase::write(LLVMContext &Ctx, 341bdd1243dSDimitry Andric MutableArrayRef<Metadata *> Entries) const { 342bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 343bdd1243dSDimitry Andric Entries[0] = ConstantAsMetadata::get(B.getInt32(ID)); 344bdd1243dSDimitry Andric Entries[1] = ConstantAsMetadata::get(GV); 345bdd1243dSDimitry Andric Entries[2] = MDString::get(Ctx, Name); 346bdd1243dSDimitry Andric Entries[3] = ConstantAsMetadata::get(B.getInt32(Space)); 347bdd1243dSDimitry Andric Entries[4] = ConstantAsMetadata::get(B.getInt32(LowerBound)); 348bdd1243dSDimitry Andric Entries[5] = ConstantAsMetadata::get(B.getInt32(RangeSize)); 349bdd1243dSDimitry Andric } 350bdd1243dSDimitry Andric 351bdd1243dSDimitry Andric MDNode *UAVResource::write() const { 352bdd1243dSDimitry Andric auto &Ctx = GV->getContext(); 353bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 354bdd1243dSDimitry Andric Metadata *Entries[11]; 355bdd1243dSDimitry Andric ResourceBase::write(Ctx, Entries); 356bdd1243dSDimitry Andric Entries[6] = 357bdd1243dSDimitry Andric ConstantAsMetadata::get(B.getInt32(static_cast<uint32_t>(Shape))); 358bdd1243dSDimitry Andric Entries[7] = ConstantAsMetadata::get(B.getInt1(GloballyCoherent)); 359bdd1243dSDimitry Andric Entries[8] = ConstantAsMetadata::get(B.getInt1(HasCounter)); 360bdd1243dSDimitry Andric Entries[9] = ConstantAsMetadata::get(B.getInt1(IsROV)); 361bdd1243dSDimitry Andric Entries[10] = ExtProps.write(Ctx); 362bdd1243dSDimitry Andric return MDNode::get(Ctx, Entries); 363bdd1243dSDimitry Andric } 364bdd1243dSDimitry Andric 365bdd1243dSDimitry Andric MDNode *ConstantBuffer::write() const { 366bdd1243dSDimitry Andric auto &Ctx = GV->getContext(); 367bdd1243dSDimitry Andric IRBuilder<> B(Ctx); 368bdd1243dSDimitry Andric Metadata *Entries[7]; 369bdd1243dSDimitry Andric ResourceBase::write(Ctx, Entries); 370bdd1243dSDimitry Andric 371bdd1243dSDimitry Andric Entries[6] = ConstantAsMetadata::get(B.getInt32(CBufferSizeInBytes)); 372bdd1243dSDimitry Andric return MDNode::get(Ctx, Entries); 373bdd1243dSDimitry Andric } 374bdd1243dSDimitry Andric 375bdd1243dSDimitry Andric template <typename T> MDNode *ResourceTable<T>::write(Module &M) const { 376bdd1243dSDimitry Andric if (Data.empty()) 377bdd1243dSDimitry Andric return nullptr; 378bdd1243dSDimitry Andric SmallVector<Metadata *> MDs; 379bdd1243dSDimitry Andric for (auto &Res : Data) 380bdd1243dSDimitry Andric MDs.emplace_back(Res.write()); 381bdd1243dSDimitry Andric 382bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata(MDName); 383bdd1243dSDimitry Andric if (Entry) 384bdd1243dSDimitry Andric Entry->eraseFromParent(); 385bdd1243dSDimitry Andric 386bdd1243dSDimitry Andric return MDNode::get(M.getContext(), MDs); 387bdd1243dSDimitry Andric } 388bdd1243dSDimitry Andric 389bdd1243dSDimitry Andric void Resources::write(Module &M) const { 390bdd1243dSDimitry Andric Metadata *ResourceMDs[4] = {nullptr, nullptr, nullptr, nullptr}; 391bdd1243dSDimitry Andric 392bdd1243dSDimitry Andric ResourceMDs[1] = UAVs.write(M); 393bdd1243dSDimitry Andric 394bdd1243dSDimitry Andric ResourceMDs[2] = CBuffers.write(M); 395bdd1243dSDimitry Andric 396bdd1243dSDimitry Andric bool HasResource = ResourceMDs[0] != nullptr || ResourceMDs[1] != nullptr || 397bdd1243dSDimitry Andric ResourceMDs[2] != nullptr || ResourceMDs[3] != nullptr; 398bdd1243dSDimitry Andric 399bdd1243dSDimitry Andric if (HasResource) { 400bdd1243dSDimitry Andric NamedMDNode *DXResMD = M.getOrInsertNamedMetadata("dx.resources"); 401bdd1243dSDimitry Andric DXResMD->addOperand(MDNode::get(M.getContext(), ResourceMDs)); 402bdd1243dSDimitry Andric } 403bdd1243dSDimitry Andric 404bdd1243dSDimitry Andric NamedMDNode *Entry = M.getNamedMetadata("hlsl.uavs"); 405bdd1243dSDimitry Andric if (Entry) 406bdd1243dSDimitry Andric Entry->eraseFromParent(); 407bdd1243dSDimitry Andric } 408bdd1243dSDimitry Andric 409bdd1243dSDimitry Andric void Resources::print(raw_ostream &O) const { 410bdd1243dSDimitry Andric O << ";\n" 411bdd1243dSDimitry Andric << "; Resource Bindings:\n" 412bdd1243dSDimitry Andric << ";\n" 413bdd1243dSDimitry Andric << "; Name Type Format Dim " 414bdd1243dSDimitry Andric "ID HLSL Bind Count\n" 415bdd1243dSDimitry Andric << "; ------------------------------ ---------- ------- ----------- " 416bdd1243dSDimitry Andric "------- -------------- ------\n"; 417bdd1243dSDimitry Andric 418bdd1243dSDimitry Andric CBuffers.print(O); 419bdd1243dSDimitry Andric UAVs.print(O); 420bdd1243dSDimitry Andric } 421bdd1243dSDimitry Andric 422bdd1243dSDimitry Andric void Resources::dump() const { print(dbgs()); } 423