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