xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/DirectX/DXILResource.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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