xref: /llvm-project/llvm/unittests/Analysis/DXILResourceTest.cpp (revision 0e2466f62491a2623e61a81f17e4c0f2c15cb8ba)
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 "llvm/IR/DataLayout.h"
12 #include "llvm/IR/GlobalVariable.h"
13 #include "llvm/IR/Module.h"
14 #include "gtest/gtest.h"
15 
16 using namespace llvm;
17 using namespace dxil;
18 
19 namespace {
20 // Helper to succinctly build resource shaped metadata for tests.
21 struct MDBuilder {
22   LLVMContext &Context;
23   Type *Int32Ty;
24   Type *Int1Ty;
25 
26   MDBuilder(LLVMContext &Context, Type *Int32Ty, Type *Int1Ty)
27       : Context(Context), Int32Ty(Int32Ty), Int1Ty(Int1Ty) {}
28 
29   Metadata *toMD(unsigned int V) {
30     return ConstantAsMetadata::get(
31         Constant::getIntegerValue(Int32Ty, APInt(32, V)));
32   }
33   Metadata *toMD(int V) { return toMD(static_cast<unsigned int>(V)); }
34   Metadata *toMD(bool V) {
35     return ConstantAsMetadata::get(
36         Constant::getIntegerValue(Int32Ty, APInt(1, V)));
37   }
38   Metadata *toMD(Value *V) { return ValueAsMetadata::get(V); }
39   Metadata *toMD(const char *V) { return MDString::get(Context, V); }
40   Metadata *toMD(StringRef V) { return MDString::get(Context, V); }
41   Metadata *toMD(std::nullptr_t V) { return nullptr; }
42   Metadata *toMD(MDTuple *V) { return V; }
43 
44   template <typename... Ts> MDTuple *get(Ts... Vs) {
45     std::array<Metadata *, sizeof...(Vs)> MDs{toMD(std::forward<Ts>(Vs))...};
46     return MDNode::get(Context, MDs);
47   }
48 };
49 
50 testing::AssertionResult MDTupleEq(const char *LHSExpr, const char *RHSExpr,
51                                    MDTuple *LHS, MDTuple *RHS) {
52   if (LHS == RHS)
53     return testing::AssertionSuccess();
54   std::string LHSRepr, RHSRepr;
55   raw_string_ostream LHSS(LHSRepr), RHSS(RHSRepr);
56   LHS->printTree(LHSS);
57   RHS->printTree(RHSS);
58 
59   return testing::AssertionFailure() << "Expected equality:\n"
60                                      << "  " << LHSExpr << "\n"
61                                      << "Which is:\n"
62                                      << "  " << LHSRepr << "\n\n"
63                                      << "  " << RHSExpr << "\n"
64                                      << "Which is:\n"
65                                      << "  " << RHSRepr;
66 }
67 #define EXPECT_MDEQ(X, Y) EXPECT_PRED_FORMAT2(MDTupleEq, X, Y)
68 } // namespace
69 
70 TEST(DXILResource, AnnotationsAndMetadata) {
71   // TODO: How am I supposed to get this?
72   DataLayout DL("e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-"
73                 "f64:64-n8:16:32:64-v96:32");
74 
75   LLVMContext Context;
76   Module M("AnnotationsAndMetadata", Context);
77   M.setDataLayout(DL);
78 
79   Type *Int1Ty = Type::getInt1Ty(Context);
80   Type *Int8Ty = Type::getInt8Ty(Context);
81   Type *Int32Ty = Type::getInt32Ty(Context);
82   Type *FloatTy = Type::getFloatTy(Context);
83   Type *DoubleTy = Type::getDoubleTy(Context);
84   Type *Floatx4Ty = FixedVectorType::get(FloatTy, 4);
85   Type *Floatx3Ty = FixedVectorType::get(FloatTy, 3);
86   Type *Int32x2Ty = FixedVectorType::get(Int32Ty, 2);
87 
88   MDBuilder TestMD(Context, Int32Ty, Int1Ty);
89 
90   // ByteAddressBuffer Buffer;
91   ResourceTypeInfo RTI(llvm::TargetExtType::get(
92       Context, "dx.RawBuffer", Int8Ty, {/*IsWriteable=*/0, /*IsROV=*/0}));
93   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV);
94   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::RawBuffer);
95 
96   ResourceBindingInfo RBI(
97       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
98       RTI.getHandleTy());
99   GlobalVariable *GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer");
100   std::pair<uint32_t, uint32_t> Props = RBI.getAnnotateProps(M, RTI);
101   EXPECT_EQ(Props.first, 0x0000000bU);
102   EXPECT_EQ(Props.second, 0U);
103   MDTuple *MD = RBI.getAsMetadata(M, RTI);
104   EXPECT_MDEQ(MD, TestMD.get(0, GV, "Buffer", 0, 0, 1, 11, 0, nullptr));
105 
106   // RWByteAddressBuffer BufferOut : register(u3, space2);
107   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
108       Context, "dx.RawBuffer", Int8Ty, {/*IsWriteable=*/1, /*IsROV=*/0}));
109   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
110   EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
111   EXPECT_EQ(RTI.getUAV().HasCounter, false);
112   EXPECT_EQ(RTI.getUAV().IsROV, false);
113   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::RawBuffer);
114 
115   RBI = ResourceBindingInfo(
116       /*RecordID=*/1, /*Space=*/2, /*LowerBound=*/3, /*Size=*/1,
117       RTI.getHandleTy());
118   GV = RBI.createSymbol(M, RTI.createElementStruct(), "BufferOut");
119   Props = RBI.getAnnotateProps(M, RTI);
120   EXPECT_EQ(Props.first, 0x0000100bU);
121   EXPECT_EQ(Props.second, 0U);
122   MD = RBI.getAsMetadata(M, RTI);
123   EXPECT_MDEQ(MD, TestMD.get(1, GV, "BufferOut", 2, 3, 1, 11, false, false,
124                              false, nullptr));
125 
126   // struct BufType0 { int i; float f; double d; };
127   // StructuredBuffer<BufType0> Buffer0 : register(t0);
128   StructType *BufType0 =
129       StructType::create(Context, {Int32Ty, FloatTy, DoubleTy}, "BufType0");
130   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
131       Context, "dx.RawBuffer", BufType0, {/*IsWriteable=*/0, /*IsROV=*/0}));
132   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV);
133   ASSERT_EQ(RTI.isStruct(), true);
134   EXPECT_EQ(RTI.getStruct(DL).Stride, 16u);
135   EXPECT_EQ(RTI.getStruct(DL).AlignLog2, Log2(Align(8)));
136   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::StructuredBuffer);
137 
138   RBI = ResourceBindingInfo(
139       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
140       RTI.getHandleTy());
141   GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer0");
142   Props = RBI.getAnnotateProps(M, RTI);
143   EXPECT_EQ(Props.first, 0x0000030cU);
144   EXPECT_EQ(Props.second, 0x00000010U);
145   MD = RBI.getAsMetadata(M, RTI);
146   EXPECT_MDEQ(MD,
147               TestMD.get(0, GV, "Buffer0", 0, 0, 1, 12, 0, TestMD.get(1, 16)));
148 
149   // StructuredBuffer<float3> Buffer1 : register(t1);
150   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
151       Context, "dx.RawBuffer", Floatx3Ty, {/*IsWriteable=*/0, /*IsROV=*/0}));
152   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV);
153   ASSERT_EQ(RTI.isStruct(), true);
154   EXPECT_EQ(RTI.getStruct(DL).Stride, 12u);
155   EXPECT_EQ(RTI.getStruct(DL).AlignLog2, 0u);
156   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::StructuredBuffer);
157 
158   RBI = ResourceBindingInfo(
159       /*RecordID=*/1, /*Space=*/0, /*LowerBound=*/1, /*Size=*/1,
160       RTI.getHandleTy());
161   GV = RBI.createSymbol(M, RTI.createElementStruct(), "Buffer1");
162   Props = RBI.getAnnotateProps(M, RTI);
163   EXPECT_EQ(Props.first, 0x0000000cU);
164   EXPECT_EQ(Props.second, 0x0000000cU);
165   MD = RBI.getAsMetadata(M, RTI);
166   EXPECT_MDEQ(MD,
167               TestMD.get(1, GV, "Buffer1", 0, 1, 1, 12, 0, TestMD.get(1, 12)));
168 
169   // Texture2D<float4> ColorMapTexture : register(t2);
170   RTI = ResourceTypeInfo(
171       llvm::TargetExtType::get(Context, "dx.Texture", Floatx4Ty,
172                                {/*IsWriteable=*/0, /*IsROV=*/0, /*IsSigned=*/0,
173                                 llvm::to_underlying(ResourceKind::Texture2D)}));
174   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV);
175   ASSERT_EQ(RTI.isTyped(), true);
176   EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::F32);
177   EXPECT_EQ(RTI.getTyped().ElementCount, 4u);
178   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2D);
179 
180   RBI = ResourceBindingInfo(
181       /*RecordID=*/2, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
182       RTI.getHandleTy());
183   GV = RBI.createSymbol(M, RTI.createElementStruct(), "ColorMapTexture");
184   Props = RBI.getAnnotateProps(M, RTI);
185   EXPECT_EQ(Props.first, 0x00000002U);
186   EXPECT_EQ(Props.second, 0x00000409U);
187   MD = RBI.getAsMetadata(M, RTI);
188   EXPECT_MDEQ(MD, TestMD.get(2, GV, "ColorMapTexture", 0, 2, 1, 2, 0,
189                              TestMD.get(0, 9)));
190 
191   // Texture2DMS<float, 8> DepthBuffer : register(t0);
192   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
193       Context, "dx.MSTexture", FloatTy,
194       {/*IsWriteable=*/0, /*SampleCount=*/8,
195        /*IsSigned=*/0, llvm::to_underlying(ResourceKind::Texture2DMS)}));
196   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::SRV);
197   ASSERT_EQ(RTI.isTyped(), true);
198   EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::F32);
199   EXPECT_EQ(RTI.getTyped().ElementCount, 1u);
200   ASSERT_EQ(RTI.isMultiSample(), true);
201   EXPECT_EQ(RTI.getMultiSampleCount(), 8u);
202   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2DMS);
203 
204   RBI = ResourceBindingInfo(
205       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
206       RTI.getHandleTy());
207   GV = RBI.createSymbol(M, RTI.createElementStruct(), "DepthBuffer");
208   Props = RBI.getAnnotateProps(M, RTI);
209   EXPECT_EQ(Props.first, 0x00000003U);
210   EXPECT_EQ(Props.second, 0x00080109U);
211   MD = RBI.getAsMetadata(M, RTI);
212   EXPECT_MDEQ(
213       MD, TestMD.get(0, GV, "DepthBuffer", 0, 0, 1, 3, 8, TestMD.get(0, 9)));
214 
215   // FeedbackTexture2D<SAMPLER_FEEDBACK_MIN_MIP> feedbackMinMip;
216   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
217       Context, "dx.FeedbackTexture", {},
218       {llvm::to_underlying(SamplerFeedbackType::MinMip),
219        llvm::to_underlying(ResourceKind::FeedbackTexture2D)}));
220   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
221   ASSERT_EQ(RTI.isFeedback(), true);
222   EXPECT_EQ(RTI.getFeedbackType(), SamplerFeedbackType::MinMip);
223   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::FeedbackTexture2D);
224 
225   RBI = ResourceBindingInfo(
226       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
227       RTI.getHandleTy());
228   GV = RBI.createSymbol(M, RTI.createElementStruct(), "feedbackMinMip");
229   Props = RBI.getAnnotateProps(M, RTI);
230   EXPECT_EQ(Props.first, 0x00001011U);
231   EXPECT_EQ(Props.second, 0U);
232   MD = RBI.getAsMetadata(M, RTI);
233   EXPECT_MDEQ(MD, TestMD.get(0, GV, "feedbackMinMip", 0, 0, 1, 17, false, false,
234                              false, TestMD.get(2, 0)));
235 
236   // FeedbackTexture2DArray<SAMPLER_FEEDBACK_MIP_REGION_USED> feedbackMipRegion;
237   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
238       Context, "dx.FeedbackTexture", {},
239       {llvm::to_underlying(SamplerFeedbackType::MipRegionUsed),
240        llvm::to_underlying(ResourceKind::FeedbackTexture2DArray)}));
241   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
242   ASSERT_EQ(RTI.isFeedback(), true);
243   EXPECT_EQ(RTI.getFeedbackType(), SamplerFeedbackType::MipRegionUsed);
244   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::FeedbackTexture2DArray);
245 
246   RBI = ResourceBindingInfo(
247       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
248       RTI.getHandleTy());
249   GV = RBI.createSymbol(M, RTI.createElementStruct(), "feedbackMipRegion");
250   Props = RBI.getAnnotateProps(M, RTI);
251   EXPECT_EQ(Props.first, 0x00001012U);
252   EXPECT_EQ(Props.second, 0x00000001U);
253   MD = RBI.getAsMetadata(M, RTI);
254   EXPECT_MDEQ(MD, TestMD.get(0, GV, "feedbackMipRegion", 0, 0, 1, 18, false,
255                              false, false, TestMD.get(2, 1)));
256 
257   // globallycoherent RWTexture2D<int2> OutputTexture : register(u0, space2);
258   RTI = ResourceTypeInfo(
259       llvm::TargetExtType::get(Context, "dx.Texture", Int32x2Ty,
260                                {/*IsWriteable=*/1,
261                                 /*IsROV=*/0, /*IsSigned=*/1,
262                                 llvm::to_underlying(ResourceKind::Texture2D)}),
263       /*GloballyCoherent=*/true, /*HasCounter=*/false);
264 
265   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
266   EXPECT_EQ(RTI.getUAV().GloballyCoherent, true);
267   EXPECT_EQ(RTI.getUAV().HasCounter, false);
268   EXPECT_EQ(RTI.getUAV().IsROV, false);
269   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2D);
270 
271   RBI = ResourceBindingInfo(
272       /*RecordID=*/0, /*Space=*/2, /*LowerBound=*/0, /*Size=*/1,
273       RTI.getHandleTy());
274   GV = RBI.createSymbol(M, RTI.createElementStruct(), "OutputTexture");
275   Props = RBI.getAnnotateProps(M, RTI);
276   EXPECT_EQ(Props.first, 0x00005002U);
277   EXPECT_EQ(Props.second, 0x00000204U);
278   MD = RBI.getAsMetadata(M, RTI);
279   EXPECT_MDEQ(MD, TestMD.get(0, GV, "OutputTexture", 2, 0, 1, 2, true, false,
280                              false, TestMD.get(0, 4)));
281 
282   // RasterizerOrderedBuffer<float4> ROB;
283   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
284       Context, "dx.TypedBuffer", Floatx4Ty,
285       {/*IsWriteable=*/1, /*IsROV=*/1, /*IsSigned=*/0}));
286   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
287   EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
288   EXPECT_EQ(RTI.getUAV().HasCounter, false);
289   EXPECT_EQ(RTI.getUAV().IsROV, true);
290   ASSERT_EQ(RTI.isTyped(), true);
291   EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::F32);
292   EXPECT_EQ(RTI.getTyped().ElementCount, 4u);
293   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::TypedBuffer);
294 
295   RBI = ResourceBindingInfo(
296       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
297       RTI.getHandleTy());
298   GV = RBI.createSymbol(M, RTI.createElementStruct(), "ROB");
299   Props = RBI.getAnnotateProps(M, RTI);
300   EXPECT_EQ(Props.first, 0x0000300aU);
301   EXPECT_EQ(Props.second, 0x00000409U);
302   MD = RBI.getAsMetadata(M, RTI);
303   EXPECT_MDEQ(MD, TestMD.get(0, GV, "ROB", 0, 0, 1, 10, false, false, true,
304                              TestMD.get(0, 9)));
305 
306   // RWStructuredBuffer<ParticleMotion> g_OutputBuffer : register(u2);
307   StructType *BufType1 = StructType::create(
308       Context, {Floatx3Ty, FloatTy, Int32Ty}, "ParticleMotion");
309   RTI = ResourceTypeInfo(
310       llvm::TargetExtType::get(Context, "dx.RawBuffer", BufType1,
311                                {/*IsWriteable=*/1, /*IsROV=*/0}),
312       /*GloballyCoherent=*/false, /*HasCounter=*/true);
313   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
314   EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
315   EXPECT_EQ(RTI.getUAV().HasCounter, true);
316   EXPECT_EQ(RTI.getUAV().IsROV, false);
317   ASSERT_EQ(RTI.isStruct(), true);
318   EXPECT_EQ(RTI.getStruct(DL).Stride, 20u);
319   EXPECT_EQ(RTI.getStruct(DL).AlignLog2, Log2(Align(4)));
320   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::StructuredBuffer);
321 
322   RBI = ResourceBindingInfo(
323       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/2, /*Size=*/1,
324       RTI.getHandleTy());
325   GV = RBI.createSymbol(M, RTI.createElementStruct(), "g_OutputBuffer");
326   Props = RBI.getAnnotateProps(M, RTI);
327   EXPECT_EQ(Props.first, 0x0000920cU);
328   EXPECT_EQ(Props.second, 0x00000014U);
329   MD = RBI.getAsMetadata(M, RTI);
330   EXPECT_MDEQ(MD, TestMD.get(0, GV, "g_OutputBuffer", 0, 2, 1, 12, false, true,
331                              false, TestMD.get(1, 20)));
332 
333   // RWTexture2DMSArray<uint, 8> g_rw_t2dmsa;
334   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
335       Context, "dx.MSTexture", Int32Ty,
336       {/*IsWriteable=*/1, /*SampleCount=*/8, /*IsSigned=*/0,
337        llvm::to_underlying(ResourceKind::Texture2DMSArray)}));
338   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::UAV);
339   EXPECT_EQ(RTI.getUAV().GloballyCoherent, false);
340   EXPECT_EQ(RTI.getUAV().HasCounter, false);
341   EXPECT_EQ(RTI.getUAV().IsROV, false);
342   ASSERT_EQ(RTI.isTyped(), true);
343   EXPECT_EQ(RTI.getTyped().ElementTy, ElementType::U32);
344   EXPECT_EQ(RTI.getTyped().ElementCount, 1u);
345   ASSERT_EQ(RTI.isMultiSample(), true);
346   EXPECT_EQ(RTI.getMultiSampleCount(), 8u);
347   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Texture2DMSArray);
348 
349   RBI = ResourceBindingInfo(
350       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
351       RTI.getHandleTy());
352   GV = RBI.createSymbol(M, RTI.createElementStruct(), "g_rw_t2dmsa");
353   Props = RBI.getAnnotateProps(M, RTI);
354   EXPECT_EQ(Props.first, 0x00001008U);
355   EXPECT_EQ(Props.second, 0x00080105U);
356   MD = RBI.getAsMetadata(M, RTI);
357   EXPECT_MDEQ(MD, TestMD.get(0, GV, "g_rw_t2dmsa", 0, 0, 1, 8, false, false,
358                              false, TestMD.get(0, 5)));
359 
360   // cbuffer cb0 { float4 g_X; float4 g_Y; }
361   StructType *CBufType0 =
362       StructType::create(Context, {Floatx4Ty, Floatx4Ty}, "cb0");
363   RTI = ResourceTypeInfo(llvm::TargetExtType::get(Context, "dx.CBuffer",
364                                                   CBufType0, {/*Size=*/32}));
365   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::CBuffer);
366   EXPECT_EQ(RTI.getCBufferSize(DL), 32u);
367   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::CBuffer);
368 
369   RBI = ResourceBindingInfo(
370       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
371       RTI.getHandleTy());
372   GV = RBI.createSymbol(M, RTI.createElementStruct(), "");
373   Props = RBI.getAnnotateProps(M, RTI);
374   EXPECT_EQ(Props.first, 0x0000000dU);
375   EXPECT_EQ(Props.second, 0x00000020U);
376   MD = RBI.getAsMetadata(M, RTI);
377   EXPECT_MDEQ(MD, TestMD.get(0, GV, "", 0, 0, 1, 32, nullptr));
378 
379   // SamplerState ColorMapSampler : register(s0);
380   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
381       Context, "dx.Sampler", {},
382       {llvm::to_underlying(dxil::SamplerType::Default)}));
383   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::Sampler);
384   EXPECT_EQ(RTI.getSamplerType(), dxil::SamplerType::Default);
385   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Sampler);
386 
387   RBI = ResourceBindingInfo(
388       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
389       RTI.getHandleTy());
390   GV = RBI.createSymbol(M, RTI.createElementStruct(), "ColorMapSampler");
391   Props = RBI.getAnnotateProps(M, RTI);
392   EXPECT_EQ(Props.first, 0x0000000eU);
393   EXPECT_EQ(Props.second, 0U);
394   MD = RBI.getAsMetadata(M, RTI);
395   EXPECT_MDEQ(MD, TestMD.get(0, GV, "ColorMapSampler", 0, 0, 1, 0, nullptr));
396 
397   RTI = ResourceTypeInfo(llvm::TargetExtType::get(
398       Context, "dx.Sampler", {},
399       {llvm::to_underlying(dxil::SamplerType::Comparison)}));
400   EXPECT_EQ(RTI.getResourceClass(), ResourceClass::Sampler);
401   EXPECT_EQ(RTI.getSamplerType(), dxil::SamplerType::Comparison);
402   EXPECT_EQ(RTI.getResourceKind(), ResourceKind::Sampler);
403 
404   RBI = ResourceBindingInfo(
405       /*RecordID=*/0, /*Space=*/0, /*LowerBound=*/0, /*Size=*/1,
406       RTI.getHandleTy());
407   GV = RBI.createSymbol(M, RTI.createElementStruct(), "CmpSampler");
408   Props = RBI.getAnnotateProps(M, RTI);
409   EXPECT_EQ(Props.first, 0x0000800eU);
410   EXPECT_EQ(Props.second, 0U);
411   MD = RBI.getAsMetadata(M, RTI);
412   EXPECT_MDEQ(MD, TestMD.get(0, GV, "CmpSampler", 0, 0, 1, 1, nullptr));
413 }
414