xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/DXILResource.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1*0fca6ea1SDimitry Andric //===- DXILResource.cpp - Tools to translate DXIL resources ---------------===//
2*0fca6ea1SDimitry Andric //
3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0fca6ea1SDimitry Andric //
7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===//
8*0fca6ea1SDimitry Andric 
9*0fca6ea1SDimitry Andric #include "llvm/Transforms/Utils/DXILResource.h"
10*0fca6ea1SDimitry Andric #include "llvm/ADT/APInt.h"
11*0fca6ea1SDimitry Andric #include "llvm/IR/DerivedTypes.h"
12*0fca6ea1SDimitry Andric 
13*0fca6ea1SDimitry Andric using namespace llvm;
14*0fca6ea1SDimitry Andric using namespace dxil;
15*0fca6ea1SDimitry Andric 
16*0fca6ea1SDimitry Andric bool ResourceInfo::isUAV() const { return RC == ResourceClass::UAV; }
17*0fca6ea1SDimitry Andric 
18*0fca6ea1SDimitry Andric bool ResourceInfo::isCBuffer() const { return RC == ResourceClass::CBuffer; }
19*0fca6ea1SDimitry Andric 
20*0fca6ea1SDimitry Andric bool ResourceInfo::isSampler() const { return RC == ResourceClass::Sampler; }
21*0fca6ea1SDimitry Andric 
22*0fca6ea1SDimitry Andric bool ResourceInfo::isStruct() const {
23*0fca6ea1SDimitry Andric   return Kind == ResourceKind::StructuredBuffer;
24*0fca6ea1SDimitry Andric }
25*0fca6ea1SDimitry Andric 
26*0fca6ea1SDimitry Andric bool ResourceInfo::isTyped() const {
27*0fca6ea1SDimitry Andric   switch (Kind) {
28*0fca6ea1SDimitry Andric   case ResourceKind::Texture1D:
29*0fca6ea1SDimitry Andric   case ResourceKind::Texture2D:
30*0fca6ea1SDimitry Andric   case ResourceKind::Texture2DMS:
31*0fca6ea1SDimitry Andric   case ResourceKind::Texture3D:
32*0fca6ea1SDimitry Andric   case ResourceKind::TextureCube:
33*0fca6ea1SDimitry Andric   case ResourceKind::Texture1DArray:
34*0fca6ea1SDimitry Andric   case ResourceKind::Texture2DArray:
35*0fca6ea1SDimitry Andric   case ResourceKind::Texture2DMSArray:
36*0fca6ea1SDimitry Andric   case ResourceKind::TextureCubeArray:
37*0fca6ea1SDimitry Andric   case ResourceKind::TypedBuffer:
38*0fca6ea1SDimitry Andric     return true;
39*0fca6ea1SDimitry Andric   case ResourceKind::RawBuffer:
40*0fca6ea1SDimitry Andric   case ResourceKind::StructuredBuffer:
41*0fca6ea1SDimitry Andric   case ResourceKind::FeedbackTexture2D:
42*0fca6ea1SDimitry Andric   case ResourceKind::FeedbackTexture2DArray:
43*0fca6ea1SDimitry Andric   case ResourceKind::CBuffer:
44*0fca6ea1SDimitry Andric   case ResourceKind::Sampler:
45*0fca6ea1SDimitry Andric   case ResourceKind::TBuffer:
46*0fca6ea1SDimitry Andric   case ResourceKind::RTAccelerationStructure:
47*0fca6ea1SDimitry Andric     return false;
48*0fca6ea1SDimitry Andric   case ResourceKind::Invalid:
49*0fca6ea1SDimitry Andric   case ResourceKind::NumEntries:
50*0fca6ea1SDimitry Andric     llvm_unreachable("Invalid resource kind");
51*0fca6ea1SDimitry Andric   }
52*0fca6ea1SDimitry Andric   llvm_unreachable("Unhandled ResourceKind enum");
53*0fca6ea1SDimitry Andric }
54*0fca6ea1SDimitry Andric 
55*0fca6ea1SDimitry Andric bool ResourceInfo::isFeedback() const {
56*0fca6ea1SDimitry Andric   return Kind == ResourceKind::FeedbackTexture2D ||
57*0fca6ea1SDimitry Andric          Kind == ResourceKind::FeedbackTexture2DArray;
58*0fca6ea1SDimitry Andric }
59*0fca6ea1SDimitry Andric 
60*0fca6ea1SDimitry Andric bool ResourceInfo::isMultiSample() const {
61*0fca6ea1SDimitry Andric   return Kind == ResourceKind::Texture2DMS ||
62*0fca6ea1SDimitry Andric          Kind == ResourceKind::Texture2DMSArray;
63*0fca6ea1SDimitry Andric }
64*0fca6ea1SDimitry Andric 
65*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::SRV(Value *Symbol, StringRef Name,
66*0fca6ea1SDimitry Andric                                ResourceBinding Binding, uint32_t UniqueID,
67*0fca6ea1SDimitry Andric                                ElementType ElementTy, uint32_t ElementCount,
68*0fca6ea1SDimitry Andric                                ResourceKind Kind) {
69*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::SRV, Kind, Symbol, Name, Binding, UniqueID);
70*0fca6ea1SDimitry Andric   assert(RI.isTyped() && !(RI.isStruct() || RI.isMultiSample()) &&
71*0fca6ea1SDimitry Andric          "Invalid ResourceKind for SRV constructor.");
72*0fca6ea1SDimitry Andric   RI.Typed.ElementTy = ElementTy;
73*0fca6ea1SDimitry Andric   RI.Typed.ElementCount = ElementCount;
74*0fca6ea1SDimitry Andric   return RI;
75*0fca6ea1SDimitry Andric }
76*0fca6ea1SDimitry Andric 
77*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::RawBuffer(Value *Symbol, StringRef Name,
78*0fca6ea1SDimitry Andric                                      ResourceBinding Binding,
79*0fca6ea1SDimitry Andric                                      uint32_t UniqueID) {
80*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::SRV, ResourceKind::RawBuffer, Symbol, Name,
81*0fca6ea1SDimitry Andric                   Binding, UniqueID);
82*0fca6ea1SDimitry Andric   return RI;
83*0fca6ea1SDimitry Andric }
84*0fca6ea1SDimitry Andric 
85*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::StructuredBuffer(Value *Symbol, StringRef Name,
86*0fca6ea1SDimitry Andric                                             ResourceBinding Binding,
87*0fca6ea1SDimitry Andric                                             uint32_t UniqueID, uint32_t Stride,
88*0fca6ea1SDimitry Andric                                             Align Alignment) {
89*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::SRV, ResourceKind::StructuredBuffer, Symbol,
90*0fca6ea1SDimitry Andric                   Name, Binding, UniqueID);
91*0fca6ea1SDimitry Andric   RI.Struct.Stride = Stride;
92*0fca6ea1SDimitry Andric   RI.Struct.Alignment = Alignment;
93*0fca6ea1SDimitry Andric   return RI;
94*0fca6ea1SDimitry Andric }
95*0fca6ea1SDimitry Andric 
96*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::Texture2DMS(Value *Symbol, StringRef Name,
97*0fca6ea1SDimitry Andric                                        ResourceBinding Binding,
98*0fca6ea1SDimitry Andric                                        uint32_t UniqueID, ElementType ElementTy,
99*0fca6ea1SDimitry Andric                                        uint32_t ElementCount,
100*0fca6ea1SDimitry Andric                                        uint32_t SampleCount) {
101*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::SRV, ResourceKind::Texture2DMS, Symbol, Name,
102*0fca6ea1SDimitry Andric                   Binding, UniqueID);
103*0fca6ea1SDimitry Andric   RI.Typed.ElementTy = ElementTy;
104*0fca6ea1SDimitry Andric   RI.Typed.ElementCount = ElementCount;
105*0fca6ea1SDimitry Andric   RI.MultiSample.Count = SampleCount;
106*0fca6ea1SDimitry Andric   return RI;
107*0fca6ea1SDimitry Andric }
108*0fca6ea1SDimitry Andric 
109*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::Texture2DMSArray(
110*0fca6ea1SDimitry Andric     Value *Symbol, StringRef Name, ResourceBinding Binding, uint32_t UniqueID,
111*0fca6ea1SDimitry Andric     ElementType ElementTy, uint32_t ElementCount, uint32_t SampleCount) {
112*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::SRV, ResourceKind::Texture2DMSArray, Symbol,
113*0fca6ea1SDimitry Andric                   Name, Binding, UniqueID);
114*0fca6ea1SDimitry Andric   RI.Typed.ElementTy = ElementTy;
115*0fca6ea1SDimitry Andric   RI.Typed.ElementCount = ElementCount;
116*0fca6ea1SDimitry Andric   RI.MultiSample.Count = SampleCount;
117*0fca6ea1SDimitry Andric   return RI;
118*0fca6ea1SDimitry Andric }
119*0fca6ea1SDimitry Andric 
120*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::UAV(Value *Symbol, StringRef Name,
121*0fca6ea1SDimitry Andric                                ResourceBinding Binding, uint32_t UniqueID,
122*0fca6ea1SDimitry Andric                                ElementType ElementTy, uint32_t ElementCount,
123*0fca6ea1SDimitry Andric                                bool GloballyCoherent, bool IsROV,
124*0fca6ea1SDimitry Andric                                ResourceKind Kind) {
125*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::UAV, Kind, Symbol, Name, Binding, UniqueID);
126*0fca6ea1SDimitry Andric   assert(RI.isTyped() && !(RI.isStruct() || RI.isMultiSample()) &&
127*0fca6ea1SDimitry Andric          "Invalid ResourceKind for UAV constructor.");
128*0fca6ea1SDimitry Andric   RI.Typed.ElementTy = ElementTy;
129*0fca6ea1SDimitry Andric   RI.Typed.ElementCount = ElementCount;
130*0fca6ea1SDimitry Andric   RI.UAVFlags.GloballyCoherent = GloballyCoherent;
131*0fca6ea1SDimitry Andric   RI.UAVFlags.IsROV = IsROV;
132*0fca6ea1SDimitry Andric   RI.UAVFlags.HasCounter = false;
133*0fca6ea1SDimitry Andric   return RI;
134*0fca6ea1SDimitry Andric }
135*0fca6ea1SDimitry Andric 
136*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::RWRawBuffer(Value *Symbol, StringRef Name,
137*0fca6ea1SDimitry Andric                                        ResourceBinding Binding,
138*0fca6ea1SDimitry Andric                                        uint32_t UniqueID, bool GloballyCoherent,
139*0fca6ea1SDimitry Andric                                        bool IsROV) {
140*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::UAV, ResourceKind::RawBuffer, Symbol, Name,
141*0fca6ea1SDimitry Andric                   Binding, UniqueID);
142*0fca6ea1SDimitry Andric   RI.UAVFlags.GloballyCoherent = GloballyCoherent;
143*0fca6ea1SDimitry Andric   RI.UAVFlags.IsROV = IsROV;
144*0fca6ea1SDimitry Andric   RI.UAVFlags.HasCounter = false;
145*0fca6ea1SDimitry Andric   return RI;
146*0fca6ea1SDimitry Andric }
147*0fca6ea1SDimitry Andric 
148*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::RWStructuredBuffer(Value *Symbol, StringRef Name,
149*0fca6ea1SDimitry Andric                                               ResourceBinding Binding,
150*0fca6ea1SDimitry Andric                                               uint32_t UniqueID,
151*0fca6ea1SDimitry Andric                                               uint32_t Stride, Align Alignment,
152*0fca6ea1SDimitry Andric                                               bool GloballyCoherent, bool IsROV,
153*0fca6ea1SDimitry Andric                                               bool HasCounter) {
154*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::UAV, ResourceKind::StructuredBuffer, Symbol,
155*0fca6ea1SDimitry Andric                   Name, Binding, UniqueID);
156*0fca6ea1SDimitry Andric   RI.Struct.Stride = Stride;
157*0fca6ea1SDimitry Andric   RI.Struct.Alignment = Alignment;
158*0fca6ea1SDimitry Andric   RI.UAVFlags.GloballyCoherent = GloballyCoherent;
159*0fca6ea1SDimitry Andric   RI.UAVFlags.IsROV = IsROV;
160*0fca6ea1SDimitry Andric   RI.UAVFlags.HasCounter = HasCounter;
161*0fca6ea1SDimitry Andric   return RI;
162*0fca6ea1SDimitry Andric }
163*0fca6ea1SDimitry Andric 
164*0fca6ea1SDimitry Andric ResourceInfo
165*0fca6ea1SDimitry Andric ResourceInfo::RWTexture2DMS(Value *Symbol, StringRef Name,
166*0fca6ea1SDimitry Andric                             ResourceBinding Binding, uint32_t UniqueID,
167*0fca6ea1SDimitry Andric                             ElementType ElementTy, uint32_t ElementCount,
168*0fca6ea1SDimitry Andric                             uint32_t SampleCount, bool GloballyCoherent) {
169*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::UAV, ResourceKind::Texture2DMS, Symbol, Name,
170*0fca6ea1SDimitry Andric                   Binding, UniqueID);
171*0fca6ea1SDimitry Andric   RI.Typed.ElementTy = ElementTy;
172*0fca6ea1SDimitry Andric   RI.Typed.ElementCount = ElementCount;
173*0fca6ea1SDimitry Andric   RI.UAVFlags.GloballyCoherent = GloballyCoherent;
174*0fca6ea1SDimitry Andric   RI.UAVFlags.IsROV = false;
175*0fca6ea1SDimitry Andric   RI.UAVFlags.HasCounter = false;
176*0fca6ea1SDimitry Andric   RI.MultiSample.Count = SampleCount;
177*0fca6ea1SDimitry Andric   return RI;
178*0fca6ea1SDimitry Andric }
179*0fca6ea1SDimitry Andric 
180*0fca6ea1SDimitry Andric ResourceInfo
181*0fca6ea1SDimitry Andric ResourceInfo::RWTexture2DMSArray(Value *Symbol, StringRef Name,
182*0fca6ea1SDimitry Andric                                  ResourceBinding Binding, uint32_t UniqueID,
183*0fca6ea1SDimitry Andric                                  ElementType ElementTy, uint32_t ElementCount,
184*0fca6ea1SDimitry Andric                                  uint32_t SampleCount, bool GloballyCoherent) {
185*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::UAV, ResourceKind::Texture2DMSArray, Symbol,
186*0fca6ea1SDimitry Andric                   Name, Binding, UniqueID);
187*0fca6ea1SDimitry Andric   RI.Typed.ElementTy = ElementTy;
188*0fca6ea1SDimitry Andric   RI.Typed.ElementCount = ElementCount;
189*0fca6ea1SDimitry Andric   RI.UAVFlags.GloballyCoherent = GloballyCoherent;
190*0fca6ea1SDimitry Andric   RI.UAVFlags.IsROV = false;
191*0fca6ea1SDimitry Andric   RI.UAVFlags.HasCounter = false;
192*0fca6ea1SDimitry Andric   RI.MultiSample.Count = SampleCount;
193*0fca6ea1SDimitry Andric   return RI;
194*0fca6ea1SDimitry Andric }
195*0fca6ea1SDimitry Andric 
196*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::FeedbackTexture2D(Value *Symbol, StringRef Name,
197*0fca6ea1SDimitry Andric                                              ResourceBinding Binding,
198*0fca6ea1SDimitry Andric                                              uint32_t UniqueID,
199*0fca6ea1SDimitry Andric                                              SamplerFeedbackType FeedbackTy) {
200*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::UAV, ResourceKind::FeedbackTexture2D, Symbol,
201*0fca6ea1SDimitry Andric                   Name, Binding, UniqueID);
202*0fca6ea1SDimitry Andric   RI.UAVFlags.GloballyCoherent = false;
203*0fca6ea1SDimitry Andric   RI.UAVFlags.IsROV = false;
204*0fca6ea1SDimitry Andric   RI.UAVFlags.HasCounter = false;
205*0fca6ea1SDimitry Andric   RI.Feedback.Type = FeedbackTy;
206*0fca6ea1SDimitry Andric   return RI;
207*0fca6ea1SDimitry Andric }
208*0fca6ea1SDimitry Andric 
209*0fca6ea1SDimitry Andric ResourceInfo
210*0fca6ea1SDimitry Andric ResourceInfo::FeedbackTexture2DArray(Value *Symbol, StringRef Name,
211*0fca6ea1SDimitry Andric                                      ResourceBinding Binding, uint32_t UniqueID,
212*0fca6ea1SDimitry Andric                                      SamplerFeedbackType FeedbackTy) {
213*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::UAV, ResourceKind::FeedbackTexture2DArray,
214*0fca6ea1SDimitry Andric                   Symbol, Name, Binding, UniqueID);
215*0fca6ea1SDimitry Andric   RI.UAVFlags.GloballyCoherent = false;
216*0fca6ea1SDimitry Andric   RI.UAVFlags.IsROV = false;
217*0fca6ea1SDimitry Andric   RI.UAVFlags.HasCounter = false;
218*0fca6ea1SDimitry Andric   RI.Feedback.Type = FeedbackTy;
219*0fca6ea1SDimitry Andric   return RI;
220*0fca6ea1SDimitry Andric }
221*0fca6ea1SDimitry Andric 
222*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::CBuffer(Value *Symbol, StringRef Name,
223*0fca6ea1SDimitry Andric                                    ResourceBinding Binding, uint32_t UniqueID,
224*0fca6ea1SDimitry Andric                                    uint32_t Size) {
225*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::CBuffer, ResourceKind::CBuffer, Symbol, Name,
226*0fca6ea1SDimitry Andric                   Binding, UniqueID);
227*0fca6ea1SDimitry Andric   RI.CBufferSize = Size;
228*0fca6ea1SDimitry Andric   return RI;
229*0fca6ea1SDimitry Andric }
230*0fca6ea1SDimitry Andric 
231*0fca6ea1SDimitry Andric ResourceInfo ResourceInfo::Sampler(Value *Symbol, StringRef Name,
232*0fca6ea1SDimitry Andric                                    ResourceBinding Binding, uint32_t UniqueID,
233*0fca6ea1SDimitry Andric                                    SamplerType SamplerTy) {
234*0fca6ea1SDimitry Andric   ResourceInfo RI(ResourceClass::Sampler, ResourceKind::Sampler, Symbol, Name,
235*0fca6ea1SDimitry Andric                   Binding, UniqueID);
236*0fca6ea1SDimitry Andric   RI.SamplerTy = SamplerTy;
237*0fca6ea1SDimitry Andric   return RI;
238*0fca6ea1SDimitry Andric }
239*0fca6ea1SDimitry Andric 
240*0fca6ea1SDimitry Andric bool ResourceInfo::operator==(const ResourceInfo &RHS) const {
241*0fca6ea1SDimitry Andric   if (std::tie(Symbol, Name, Binding, UniqueID, RC, Kind) !=
242*0fca6ea1SDimitry Andric       std::tie(RHS.Symbol, RHS.Name, RHS.Binding, RHS.UniqueID, RHS.RC,
243*0fca6ea1SDimitry Andric                RHS.Kind))
244*0fca6ea1SDimitry Andric     return false;
245*0fca6ea1SDimitry Andric   if (isCBuffer())
246*0fca6ea1SDimitry Andric     return CBufferSize == RHS.CBufferSize;
247*0fca6ea1SDimitry Andric   if (isSampler())
248*0fca6ea1SDimitry Andric     return SamplerTy == RHS.SamplerTy;
249*0fca6ea1SDimitry Andric   if (isUAV() && UAVFlags != RHS.UAVFlags)
250*0fca6ea1SDimitry Andric     return false;
251*0fca6ea1SDimitry Andric 
252*0fca6ea1SDimitry Andric   if (isStruct())
253*0fca6ea1SDimitry Andric     return Struct == RHS.Struct;
254*0fca6ea1SDimitry Andric   if (isFeedback())
255*0fca6ea1SDimitry Andric     return Feedback == RHS.Feedback;
256*0fca6ea1SDimitry Andric   if (isTyped() && Typed != RHS.Typed)
257*0fca6ea1SDimitry Andric     return false;
258*0fca6ea1SDimitry Andric 
259*0fca6ea1SDimitry Andric   if (isMultiSample())
260*0fca6ea1SDimitry Andric     return MultiSample == RHS.MultiSample;
261*0fca6ea1SDimitry Andric 
262*0fca6ea1SDimitry Andric   assert((Kind == ResourceKind::RawBuffer) && "Unhandled resource kind");
263*0fca6ea1SDimitry Andric   return true;
264*0fca6ea1SDimitry Andric }
265*0fca6ea1SDimitry Andric 
266*0fca6ea1SDimitry Andric MDTuple *ResourceInfo::getAsMetadata(LLVMContext &Ctx) const {
267*0fca6ea1SDimitry Andric   SmallVector<Metadata *, 11> MDVals;
268*0fca6ea1SDimitry Andric 
269*0fca6ea1SDimitry Andric   Type *I32Ty = Type::getInt32Ty(Ctx);
270*0fca6ea1SDimitry Andric   Type *I1Ty = Type::getInt1Ty(Ctx);
271*0fca6ea1SDimitry Andric   auto getIntMD = [&I32Ty](uint32_t V) {
272*0fca6ea1SDimitry Andric     return ConstantAsMetadata::get(
273*0fca6ea1SDimitry Andric         Constant::getIntegerValue(I32Ty, APInt(32, V)));
274*0fca6ea1SDimitry Andric   };
275*0fca6ea1SDimitry Andric   auto getBoolMD = [&I1Ty](uint32_t V) {
276*0fca6ea1SDimitry Andric     return ConstantAsMetadata::get(
277*0fca6ea1SDimitry Andric         Constant::getIntegerValue(I1Ty, APInt(1, V)));
278*0fca6ea1SDimitry Andric   };
279*0fca6ea1SDimitry Andric 
280*0fca6ea1SDimitry Andric   MDVals.push_back(getIntMD(UniqueID));
281*0fca6ea1SDimitry Andric   MDVals.push_back(ValueAsMetadata::get(Symbol));
282*0fca6ea1SDimitry Andric   MDVals.push_back(MDString::get(Ctx, Name));
283*0fca6ea1SDimitry Andric   MDVals.push_back(getIntMD(Binding.Space));
284*0fca6ea1SDimitry Andric   MDVals.push_back(getIntMD(Binding.LowerBound));
285*0fca6ea1SDimitry Andric   MDVals.push_back(getIntMD(Binding.Size));
286*0fca6ea1SDimitry Andric 
287*0fca6ea1SDimitry Andric   if (isCBuffer()) {
288*0fca6ea1SDimitry Andric     MDVals.push_back(getIntMD(CBufferSize));
289*0fca6ea1SDimitry Andric     MDVals.push_back(nullptr);
290*0fca6ea1SDimitry Andric   } else if (isSampler()) {
291*0fca6ea1SDimitry Andric     MDVals.push_back(getIntMD(llvm::to_underlying(SamplerTy)));
292*0fca6ea1SDimitry Andric     MDVals.push_back(nullptr);
293*0fca6ea1SDimitry Andric   } else {
294*0fca6ea1SDimitry Andric     MDVals.push_back(getIntMD(llvm::to_underlying(Kind)));
295*0fca6ea1SDimitry Andric 
296*0fca6ea1SDimitry Andric     if (isUAV()) {
297*0fca6ea1SDimitry Andric       MDVals.push_back(getBoolMD(UAVFlags.GloballyCoherent));
298*0fca6ea1SDimitry Andric       MDVals.push_back(getBoolMD(UAVFlags.HasCounter));
299*0fca6ea1SDimitry Andric       MDVals.push_back(getBoolMD(UAVFlags.IsROV));
300*0fca6ea1SDimitry Andric     } else {
301*0fca6ea1SDimitry Andric       // All SRVs include sample count in the metadata, but it's only meaningful
302*0fca6ea1SDimitry Andric       // for multi-sampled textured. Also, UAVs can be multisampled in SM6.7+,
303*0fca6ea1SDimitry Andric       // but this just isn't reflected in the metadata at all.
304*0fca6ea1SDimitry Andric       uint32_t SampleCount = isMultiSample() ? MultiSample.Count : 0;
305*0fca6ea1SDimitry Andric       MDVals.push_back(getIntMD(SampleCount));
306*0fca6ea1SDimitry Andric     }
307*0fca6ea1SDimitry Andric 
308*0fca6ea1SDimitry Andric     // Further properties are attached to a metadata list of tag-value pairs.
309*0fca6ea1SDimitry Andric     SmallVector<Metadata *> Tags;
310*0fca6ea1SDimitry Andric     if (isStruct()) {
311*0fca6ea1SDimitry Andric       Tags.push_back(
312*0fca6ea1SDimitry Andric           getIntMD(llvm::to_underlying(ExtPropTags::StructuredBufferStride)));
313*0fca6ea1SDimitry Andric       Tags.push_back(getIntMD(Struct.Stride));
314*0fca6ea1SDimitry Andric     } else if (isTyped()) {
315*0fca6ea1SDimitry Andric       Tags.push_back(getIntMD(llvm::to_underlying(ExtPropTags::ElementType)));
316*0fca6ea1SDimitry Andric       Tags.push_back(getIntMD(llvm::to_underlying(Typed.ElementTy)));
317*0fca6ea1SDimitry Andric     } else if (isFeedback()) {
318*0fca6ea1SDimitry Andric       Tags.push_back(
319*0fca6ea1SDimitry Andric           getIntMD(llvm::to_underlying(ExtPropTags::SamplerFeedbackKind)));
320*0fca6ea1SDimitry Andric       Tags.push_back(getIntMD(llvm::to_underlying(Feedback.Type)));
321*0fca6ea1SDimitry Andric     }
322*0fca6ea1SDimitry Andric     MDVals.push_back(Tags.empty() ? nullptr : MDNode::get(Ctx, Tags));
323*0fca6ea1SDimitry Andric   }
324*0fca6ea1SDimitry Andric 
325*0fca6ea1SDimitry Andric   return MDNode::get(Ctx, MDVals);
326*0fca6ea1SDimitry Andric }
327*0fca6ea1SDimitry Andric 
328*0fca6ea1SDimitry Andric std::pair<uint32_t, uint32_t> ResourceInfo::getAnnotateProps() const {
329*0fca6ea1SDimitry Andric   uint32_t ResourceKind = llvm::to_underlying(Kind);
330*0fca6ea1SDimitry Andric   uint32_t AlignLog2 = isStruct() ? Log2(Struct.Alignment) : 0;
331*0fca6ea1SDimitry Andric   bool IsUAV = isUAV();
332*0fca6ea1SDimitry Andric   bool IsROV = IsUAV && UAVFlags.IsROV;
333*0fca6ea1SDimitry Andric   bool IsGloballyCoherent = IsUAV && UAVFlags.GloballyCoherent;
334*0fca6ea1SDimitry Andric   uint8_t SamplerCmpOrHasCounter = 0;
335*0fca6ea1SDimitry Andric   if (IsUAV)
336*0fca6ea1SDimitry Andric     SamplerCmpOrHasCounter = UAVFlags.HasCounter;
337*0fca6ea1SDimitry Andric   else if (isSampler())
338*0fca6ea1SDimitry Andric     SamplerCmpOrHasCounter = SamplerTy == SamplerType::Comparison;
339*0fca6ea1SDimitry Andric 
340*0fca6ea1SDimitry Andric   // TODO: Document this format. Currently the only reference is the
341*0fca6ea1SDimitry Andric   // implementation of dxc's DxilResourceProperties struct.
342*0fca6ea1SDimitry Andric   uint32_t Word0 = 0;
343*0fca6ea1SDimitry Andric   Word0 |= ResourceKind & 0xFF;
344*0fca6ea1SDimitry Andric   Word0 |= (AlignLog2 & 0xF) << 8;
345*0fca6ea1SDimitry Andric   Word0 |= (IsUAV & 1) << 12;
346*0fca6ea1SDimitry Andric   Word0 |= (IsROV & 1) << 13;
347*0fca6ea1SDimitry Andric   Word0 |= (IsGloballyCoherent & 1) << 14;
348*0fca6ea1SDimitry Andric   Word0 |= (SamplerCmpOrHasCounter & 1) << 15;
349*0fca6ea1SDimitry Andric 
350*0fca6ea1SDimitry Andric   uint32_t Word1 = 0;
351*0fca6ea1SDimitry Andric   if (isStruct())
352*0fca6ea1SDimitry Andric     Word1 = Struct.Stride;
353*0fca6ea1SDimitry Andric   else if (isCBuffer())
354*0fca6ea1SDimitry Andric     Word1 = CBufferSize;
355*0fca6ea1SDimitry Andric   else if (isFeedback())
356*0fca6ea1SDimitry Andric     Word1 = llvm::to_underlying(Feedback.Type);
357*0fca6ea1SDimitry Andric   else if (isTyped()) {
358*0fca6ea1SDimitry Andric     uint32_t CompType = llvm::to_underlying(Typed.ElementTy);
359*0fca6ea1SDimitry Andric     uint32_t CompCount = Typed.ElementCount;
360*0fca6ea1SDimitry Andric     uint32_t SampleCount = isMultiSample() ? MultiSample.Count : 0;
361*0fca6ea1SDimitry Andric 
362*0fca6ea1SDimitry Andric     Word1 |= (CompType & 0xFF) << 0;
363*0fca6ea1SDimitry Andric     Word1 |= (CompCount & 0xFF) << 8;
364*0fca6ea1SDimitry Andric     Word1 |= (SampleCount & 0xFF) << 16;
365*0fca6ea1SDimitry Andric   }
366*0fca6ea1SDimitry Andric 
367*0fca6ea1SDimitry Andric   return {Word0, Word1};
368*0fca6ea1SDimitry Andric }
369*0fca6ea1SDimitry Andric 
370*0fca6ea1SDimitry Andric #define DEBUG_TYPE "dxil-resource"
371