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