xref: /llvm-project/llvm/unittests/Analysis/DXILResourceTest.cpp (revision 6992ebcb4b69fc7f116cd475e4731d3877118c1d)
1 //===- DXILResourceTest.cpp - Unit tests for DXILResource -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Analysis/DXILResource.h"
10 #include "llvm/IR/Constants.h"
11 #include "gtest/gtest.h"
12 
13 using namespace llvm;
14 using namespace dxil;
15 
16 namespace {
17 // Helper to succinctly build resource shaped metadata for tests.
18 struct MDBuilder {
19   LLVMContext &Context;
20   Type *Int32Ty;
21   Type *Int1Ty;
22 
23   MDBuilder(LLVMContext &Context, Type *Int32Ty, Type *Int1Ty)
24       : Context(Context), Int32Ty(Int32Ty), Int1Ty(Int1Ty) {}
25 
26   template <typename... Ts>
27   void appendMDs(SmallVectorImpl<Metadata *> &MDs, int V, Ts... More) {
28     MDs.push_back(ConstantAsMetadata::get(
29         Constant::getIntegerValue(Int32Ty, APInt(32, V))));
30     appendMDs(MDs, More...);
31   }
32   template <typename... Ts>
33   void appendMDs(SmallVectorImpl<Metadata *> &MDs, unsigned int V, Ts... More) {
34     MDs.push_back(ConstantAsMetadata::get(
35         Constant::getIntegerValue(Int32Ty, APInt(32, V))));
36     appendMDs(MDs, More...);
37   }
38   template <typename... Ts>
39   void appendMDs(SmallVectorImpl<Metadata *> &MDs, bool V, Ts... More) {
40     MDs.push_back(ConstantAsMetadata::get(
41         Constant::getIntegerValue(Int1Ty, APInt(1, V))));
42     appendMDs(MDs, More...);
43   }
44   template <typename... Ts>
45   void appendMDs(SmallVectorImpl<Metadata *> &MDs, Value *V, Ts... More) {
46     MDs.push_back(ValueAsMetadata::get(V));
47     appendMDs(MDs, More...);
48   }
49   template <typename... Ts>
50   void appendMDs(SmallVectorImpl<Metadata *> &MDs, const char *V, Ts... More) {
51     MDs.push_back(MDString::get(Context, V));
52     appendMDs(MDs, More...);
53   }
54   template <typename... Ts>
55   void appendMDs(SmallVectorImpl<Metadata *> &MDs, StringRef V, Ts... More) {
56     MDs.push_back(MDString::get(Context, V));
57     appendMDs(MDs, More...);
58   }
59   template <typename... Ts>
60   void appendMDs(SmallVectorImpl<Metadata *> &MDs, std::nullptr_t V,
61                  Ts... More) {
62     MDs.push_back(nullptr);
63     appendMDs(MDs, More...);
64   }
65   template <typename... Ts>
66   void appendMDs(SmallVectorImpl<Metadata *> &MDs, MDTuple *V, Ts... More) {
67     MDs.push_back(V);
68     appendMDs(MDs, More...);
69   }
70   void appendMDs(SmallVectorImpl<Metadata *> &MDs) {
71     // Base case, nothing to do.
72   }
73 
74   template <typename... Ts> MDTuple *get(Ts... Data) {
75     SmallVector<Metadata *> MDs;
76     appendMDs(MDs, Data...);
77     return MDNode::get(Context, MDs);
78   }
79 };
80 
81 testing::AssertionResult MDTupleEq(const char *LHSExpr, const char *RHSExpr,
82                                    MDTuple *LHS, MDTuple *RHS) {
83   if (LHS == RHS)
84     return testing::AssertionSuccess();
85   std::string LHSRepr, RHSRepr;
86   raw_string_ostream LHSS(LHSRepr), RHSS(RHSRepr);
87   LHS->printTree(LHSS);
88   RHS->printTree(RHSS);
89 
90   return testing::AssertionFailure() << "Expected equality:\n"
91                                      << "  " << LHSExpr << "\n"
92                                      << "Which is:\n"
93                                      << "  " << LHSS.str() << "\n\n"
94                                      << "  " << RHSExpr << "\n"
95                                      << "Which is:\n"
96                                      << "  " << RHSS.str();
97 }
98 #define EXPECT_MDEQ(X, Y) EXPECT_PRED_FORMAT2(MDTupleEq, X, Y)
99 } // namespace
100 
101 TEST(DXILResource, AnnotationsAndMetadata) {
102   LLVMContext Context;
103   Type *Int1Ty = Type::getInt1Ty(Context);
104   Type *Int32Ty = Type::getInt32Ty(Context);
105   Type *FloatTy = Type::getFloatTy(Context);
106   Type *DoubleTy = Type::getDoubleTy(Context);
107   Type *Floatx4Ty = FixedVectorType::get(FloatTy, 4);
108   Type *Floatx3Ty = FixedVectorType::get(FloatTy, 3);
109   Type *Int32x2Ty = FixedVectorType::get(Int32Ty, 2);
110 
111   MDBuilder TestMD(Context, Int32Ty, Int1Ty);
112 
113   // ByteAddressBuffer Buffer0;
114   Value *Symbol = UndefValue::get(
115       StructType::create(Context, {Int32Ty}, "struct.ByteAddressBuffer"));
116   ResourceInfo Resource = ResourceInfo::RawBuffer(Symbol, "Buffer0");
117   Resource.bind(0, 0, 0, 1);
118   std::pair<uint32_t, uint32_t> Props = Resource.getAnnotateProps();
119   EXPECT_EQ(Props.first, 0x0000000bU);
120   EXPECT_EQ(Props.second, 0U);
121   MDTuple *MD = Resource.getAsMetadata(Context);
122   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "Buffer0", 0, 0, 1, 11, 0, nullptr));
123 
124   // RWByteAddressBuffer BufferOut : register(u3, space2);
125   Symbol = UndefValue::get(
126       StructType::create(Context, {Int32Ty}, "struct.RWByteAddressBuffer"));
127   Resource =
128       ResourceInfo::RWRawBuffer(Symbol, "BufferOut",
129                                 /*GloballyCoherent=*/false, /*IsROV=*/false);
130   Resource.bind(1, 2, 3, 1);
131   Props = Resource.getAnnotateProps();
132   EXPECT_EQ(Props.first, 0x0000100bU);
133   EXPECT_EQ(Props.second, 0U);
134   MD = Resource.getAsMetadata(Context);
135   EXPECT_MDEQ(MD, TestMD.get(1, Symbol, "BufferOut", 2, 3, 1, 11, false, false,
136                              false, nullptr));
137 
138   // struct BufType0 { int i; float f; double d; };
139   // StructuredBuffer<BufType0> Buffer0 : register(t0);
140   StructType *BufType0 =
141       StructType::create(Context, {Int32Ty, FloatTy, DoubleTy}, "BufType0");
142   Symbol = UndefValue::get(StructType::create(
143       Context, {BufType0}, "class.StructuredBuffer<BufType>"));
144   Resource = ResourceInfo::StructuredBuffer(Symbol, "Buffer0",
145                                             /*Stride=*/16, Align(8));
146   Resource.bind(0, 0, 0, 1);
147   Props = Resource.getAnnotateProps();
148   EXPECT_EQ(Props.first, 0x0000030cU);
149   EXPECT_EQ(Props.second, 0x00000010U);
150   MD = Resource.getAsMetadata(Context);
151   EXPECT_MDEQ(
152       MD, TestMD.get(0, Symbol, "Buffer0", 0, 0, 1, 12, 0, TestMD.get(1, 16)));
153 
154   // StructuredBuffer<float3> Buffer1 : register(t1);
155   Symbol = UndefValue::get(StructType::create(
156       Context, {Floatx3Ty}, "class.StructuredBuffer<vector<float, 3> >"));
157   Resource = ResourceInfo::StructuredBuffer(Symbol, "Buffer1",
158                                             /*Stride=*/12, {});
159   Resource.bind(1, 0, 1, 1);
160   Props = Resource.getAnnotateProps();
161   EXPECT_EQ(Props.first, 0x0000000cU);
162   EXPECT_EQ(Props.second, 0x0000000cU);
163   MD = Resource.getAsMetadata(Context);
164   EXPECT_MDEQ(
165       MD, TestMD.get(1, Symbol, "Buffer1", 0, 1, 1, 12, 0, TestMD.get(1, 12)));
166 
167   // Texture2D<float4> ColorMapTexture : register(t2);
168   Symbol = UndefValue::get(StructType::create(
169       Context, {Floatx4Ty}, "class.Texture2D<vector<float, 4> >"));
170   Resource =
171       ResourceInfo::SRV(Symbol, "ColorMapTexture", dxil::ElementType::F32,
172                         /*ElementCount=*/4, dxil::ResourceKind::Texture2D);
173   Resource.bind(2, 0, 2, 1);
174   Props = Resource.getAnnotateProps();
175   EXPECT_EQ(Props.first, 0x00000002U);
176   EXPECT_EQ(Props.second, 0x00000409U);
177   MD = Resource.getAsMetadata(Context);
178   EXPECT_MDEQ(MD, TestMD.get(2, Symbol, "ColorMapTexture", 0, 2, 1, 2, 0,
179                              TestMD.get(0, 9)));
180 
181   // Texture2DMS<float, 8> DepthBuffer : register(t0);
182   Symbol = UndefValue::get(
183       StructType::create(Context, {FloatTy}, "class.Texture2DMS<float, 8>"));
184   Resource =
185       ResourceInfo::Texture2DMS(Symbol, "DepthBuffer", dxil::ElementType::F32,
186                                 /*ElementCount=*/1, /*SampleCount=*/8);
187   Resource.bind(0, 0, 0, 1);
188   Props = Resource.getAnnotateProps();
189   EXPECT_EQ(Props.first, 0x00000003U);
190   EXPECT_EQ(Props.second, 0x00080109U);
191   MD = Resource.getAsMetadata(Context);
192   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "DepthBuffer", 0, 0, 1, 3, 8,
193                              TestMD.get(0, 9)));
194 
195   // FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMip;
196   Symbol = UndefValue::get(
197       StructType::create(Context, {Int32Ty}, "class.FeedbackTexture2D<0>"));
198   Resource = ResourceInfo::FeedbackTexture2D(Symbol, "feedbackMinMip",
199                                              SamplerFeedbackType::MinMip);
200   Resource.bind(0, 0, 0, 1);
201   Props = Resource.getAnnotateProps();
202   EXPECT_EQ(Props.first, 0x00001011U);
203   EXPECT_EQ(Props.second, 0U);
204   MD = Resource.getAsMetadata(Context);
205   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "feedbackMinMip", 0, 0, 1, 17, false,
206                              false, false, TestMD.get(2, 0)));
207 
208   // FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIP_REGION_USED> feedbackMipRegion;
209   Symbol = UndefValue::get(StructType::create(
210       Context, {Int32Ty}, "class.FeedbackTexture2DArray<1>"));
211   Resource = ResourceInfo::FeedbackTexture2DArray(
212       Symbol, "feedbackMipRegion", SamplerFeedbackType::MipRegionUsed);
213   Resource.bind(0, 0, 0, 1);
214   Props = Resource.getAnnotateProps();
215   EXPECT_EQ(Props.first, 0x00001012U);
216   EXPECT_EQ(Props.second, 0x00000001U);
217   MD = Resource.getAsMetadata(Context);
218   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "feedbackMipRegion", 0, 0, 1, 18, false,
219                              false, false, TestMD.get(2, 1)));
220 
221   // globallycoherent RWTexture2D<int2> OutputTexture : register(u0, space2);
222   Symbol = UndefValue::get(StructType::create(
223       Context, {Int32x2Ty}, "class.RWTexture2D<vector<int, 2> >"));
224   Resource = ResourceInfo::UAV(Symbol, "OutputTexture", dxil::ElementType::I32,
225                                /*ElementCount=*/2, /*GloballyCoherent=*/1,
226                                /*IsROV=*/0, dxil::ResourceKind::Texture2D);
227   Resource.bind(0, 2, 0, 1);
228   Props = Resource.getAnnotateProps();
229   EXPECT_EQ(Props.first, 0x00005002U);
230   EXPECT_EQ(Props.second, 0x00000204U);
231   MD = Resource.getAsMetadata(Context);
232   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "OutputTexture", 2, 0, 1, 2, true,
233                              false, false, TestMD.get(0, 4)));
234 
235   // RasterizerOrderedBuffer<float4> ROB;
236   Symbol = UndefValue::get(
237       StructType::create(Context, {Floatx4Ty},
238                          "class.RasterizerOrderedBuffer<vector<float, 4> >"));
239   Resource = ResourceInfo::UAV(Symbol, "ROB", dxil::ElementType::F32,
240                                /*ElementCount=*/4, /*GloballyCoherent=*/0,
241                                /*IsROV=*/1, dxil::ResourceKind::TypedBuffer);
242   Resource.bind(0, 0, 0, 1);
243   Props = Resource.getAnnotateProps();
244   EXPECT_EQ(Props.first, 0x0000300aU);
245   EXPECT_EQ(Props.second, 0x00000409U);
246   MD = Resource.getAsMetadata(Context);
247   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "ROB", 0, 0, 1, 10, false, false, true,
248                              TestMD.get(0, 9)));
249 
250   // RWStructuredBuffer<ParticleMotion> g_OutputBuffer : register(u2);
251   StructType *BufType1 = StructType::create(
252       Context, {Floatx3Ty, FloatTy, Int32Ty}, "ParticleMotion");
253   Symbol = UndefValue::get(StructType::create(
254       Context, {BufType1}, "class.StructuredBuffer<ParticleMotion>"));
255   Resource =
256       ResourceInfo::RWStructuredBuffer(Symbol, "g_OutputBuffer", /*Stride=*/20,
257                                        Align(4), /*GloballyCoherent=*/false,
258                                        /*IsROV=*/false, /*HasCounter=*/true);
259   Resource.bind(0, 0, 2, 1);
260   Props = Resource.getAnnotateProps();
261   EXPECT_EQ(Props.first, 0x0000920cU);
262   EXPECT_EQ(Props.second, 0x00000014U);
263   MD = Resource.getAsMetadata(Context);
264   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "g_OutputBuffer", 0, 2, 1, 12, false,
265                              true, false, TestMD.get(1, 20)));
266 
267   // RWTexture2DMSArray<uint,8> g_rw_t2dmsa;
268   Symbol = UndefValue::get(StructType::create(
269       Context, {Int32Ty}, "class.RWTexture2DMSArray<unsigned int, 8>"));
270   Resource = ResourceInfo::RWTexture2DMSArray(
271       Symbol, "g_rw_t2dmsa", dxil::ElementType::U32, /*ElementCount=*/1,
272       /*SampleCount=*/8, /*GloballyCoherent=*/false);
273   Resource.bind(0, 0, 0, 1);
274   Props = Resource.getAnnotateProps();
275   EXPECT_EQ(Props.first, 0x00001008U);
276   EXPECT_EQ(Props.second, 0x00080105U);
277   MD = Resource.getAsMetadata(Context);
278   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "g_rw_t2dmsa", 0, 0, 1, 8, false, false,
279                              false, TestMD.get(0, 5)));
280 
281   // cbuffer cb0 { float4 g_X; float4 g_Y; }
282   Symbol = UndefValue::get(
283       StructType::create(Context, {Floatx4Ty, Floatx4Ty}, "cb0"));
284   Resource = ResourceInfo::CBuffer(Symbol, "cb0", /*Size=*/32);
285   Resource.bind(0, 0, 0, 1);
286   Props = Resource.getAnnotateProps();
287   EXPECT_EQ(Props.first, 0x0000000dU);
288   EXPECT_EQ(Props.second, 0x00000020U);
289   MD = Resource.getAsMetadata(Context);
290   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "cb0", 0, 0, 1, 32, nullptr));
291 
292   // SamplerState ColorMapSampler : register(s0);
293   Symbol = UndefValue::get(
294       StructType::create(Context, {Int32Ty}, "struct.SamplerState"));
295   Resource = ResourceInfo::Sampler(Symbol, "ColorMapSampler",
296                                    dxil::SamplerType::Default);
297   Resource.bind(0, 0, 0, 1);
298   Props = Resource.getAnnotateProps();
299   EXPECT_EQ(Props.first, 0x0000000eU);
300   EXPECT_EQ(Props.second, 0U);
301   MD = Resource.getAsMetadata(Context);
302   EXPECT_MDEQ(MD,
303               TestMD.get(0, Symbol, "ColorMapSampler", 0, 0, 1, 0, nullptr));
304 
305   // SamplerComparisonState ShadowSampler {...};
306   Resource = ResourceInfo::Sampler(Symbol, "CmpSampler",
307                                    dxil::SamplerType::Comparison);
308   Resource.bind(0, 0, 0, 1);
309   Props = Resource.getAnnotateProps();
310   EXPECT_EQ(Props.first, 0x0000800eU);
311   EXPECT_EQ(Props.second, 0U);
312   MD = Resource.getAsMetadata(Context);
313   EXPECT_MDEQ(MD, TestMD.get(0, Symbol, "CmpSampler", 0, 0, 1, 1, nullptr));
314 }
315