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