1 //===- DXILResourceTest.cpp - Unit tests for DXILResource -----------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Analysis/DXILResource.h"
10 #include "llvm/IR/Constants.h"
11 #include "gtest/gtest.h"
17 // Helper to succinctly build resource shaped metadata for tests.
23 MDBuilder(LLVMContext
&Context
, Type
*Int32Ty
, Type
*Int1Ty
)
24 : Context(Context
), Int32Ty(Int32Ty
), Int1Ty(Int1Ty
) {}
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
...);
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
...);
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
...);
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
...);
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
...);
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
...);
59 template <typename
... Ts
>
60 void appendMDs(SmallVectorImpl
<Metadata
*> &MDs
, std::nullptr_t V
,
62 MDs
.push_back(nullptr);
63 appendMDs(MDs
, More
...);
65 template <typename
... Ts
>
66 void appendMDs(SmallVectorImpl
<Metadata
*> &MDs
, MDTuple
*V
, Ts
... More
) {
68 appendMDs(MDs
, More
...);
70 void appendMDs(SmallVectorImpl
<Metadata
*> &MDs
) {
71 // Base case, nothing to do.
74 template <typename
... Ts
> MDTuple
*get(Ts
... Data
) {
75 SmallVector
<Metadata
*> MDs
;
76 appendMDs(MDs
, Data
...);
77 return MDNode::get(Context
, MDs
);
81 testing::AssertionResult
MDTupleEq(const char *LHSExpr
, const char *RHSExpr
,
82 MDTuple
*LHS
, MDTuple
*RHS
) {
84 return testing::AssertionSuccess();
85 std::string LHSRepr
, RHSRepr
;
86 raw_string_ostream
LHSS(LHSRepr
), RHSS(RHSRepr
);
90 return testing::AssertionFailure() << "Expected equality:\n"
91 << " " << LHSExpr
<< "\n"
93 << " " << LHSRepr
<< "\n\n"
94 << " " << RHSExpr
<< "\n"
98 #define EXPECT_MDEQ(X, Y) EXPECT_PRED_FORMAT2(MDTupleEq, X, Y)
101 TEST(DXILResource
, AnnotationsAndMetadata
) {
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);
111 MDBuilder
TestMD(Context
, Int32Ty
, Int1Ty
);
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));
124 // RWByteAddressBuffer BufferOut : register(u3, space2);
125 Symbol
= UndefValue::get(
126 StructType::create(Context
, {Int32Ty
}, "struct.RWByteAddressBuffer"));
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,
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
);
152 MD
, TestMD
.get(0, Symbol
, "Buffer0", 0, 0, 1, 12, 0, TestMD
.get(1, 16)));
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",
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
);
165 MD
, TestMD
.get(1, Symbol
, "Buffer1", 0, 1, 1, 12, 0, TestMD
.get(1, 12)));
167 // Texture2D<float4> ColorMapTexture : register(t2);
168 Symbol
= UndefValue::get(StructType::create(
169 Context
, {Floatx4Ty
}, "class.Texture2D<vector<float, 4> >"));
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,
181 // Texture2DMS<float, 8> DepthBuffer : register(t0);
182 Symbol
= UndefValue::get(
183 StructType::create(Context
, {FloatTy
}, "class.Texture2DMS<float, 8>"));
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,
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)));
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)));
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)));
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,
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>"));
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)));
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)));
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));
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
);
303 TestMD
.get(0, Symbol
, "ColorMapSampler", 0, 0, 1, 0, nullptr));
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));