1 // Copyright (c) 2016 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "gmock/gmock.h"
21 #include "source/opt/instruction.h"
22 #include "source/opt/ir_context.h"
23 #include "spirv-tools/libspirv.h"
24 #include "test/opt/pass_fixture.h"
25 #include "test/opt/pass_utils.h"
26 #include "test/unit_spirv.h"
27
28 namespace spvtools {
29 namespace opt {
30 namespace {
31
32 using ::testing::Eq;
33 using spvtest::MakeInstruction;
34 using DescriptorTypeTest = PassTest<::testing::Test>;
35 using OpaqueTypeTest = PassTest<::testing::Test>;
36 using GetBaseTest = PassTest<::testing::Test>;
37 using ValidBasePointerTest = PassTest<::testing::Test>;
38 using VulkanBufferTest = PassTest<::testing::Test>;
39
TEST(InstructionTest,CreateTrivial)40 TEST(InstructionTest, CreateTrivial) {
41 Instruction empty;
42 EXPECT_EQ(SpvOpNop, empty.opcode());
43 EXPECT_EQ(0u, empty.type_id());
44 EXPECT_EQ(0u, empty.result_id());
45 EXPECT_EQ(0u, empty.NumOperands());
46 EXPECT_EQ(0u, empty.NumOperandWords());
47 EXPECT_EQ(0u, empty.NumInOperandWords());
48 EXPECT_EQ(empty.cend(), empty.cbegin());
49 EXPECT_EQ(empty.end(), empty.begin());
50 }
51
TEST(InstructionTest,CreateWithOpcodeAndNoOperands)52 TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
53 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
54 Instruction inst(&context, SpvOpReturn);
55 EXPECT_EQ(SpvOpReturn, inst.opcode());
56 EXPECT_EQ(0u, inst.type_id());
57 EXPECT_EQ(0u, inst.result_id());
58 EXPECT_EQ(0u, inst.NumOperands());
59 EXPECT_EQ(0u, inst.NumOperandWords());
60 EXPECT_EQ(0u, inst.NumInOperandWords());
61 EXPECT_EQ(inst.cend(), inst.cbegin());
62 EXPECT_EQ(inst.end(), inst.begin());
63 }
64
TEST(InstructionTest,OperandAsCString)65 TEST(InstructionTest, OperandAsCString) {
66 Operand::OperandData abcde{0x64636261, 0x65};
67 Operand operand(SPV_OPERAND_TYPE_LITERAL_STRING, std::move(abcde));
68 EXPECT_STREQ("abcde", operand.AsCString());
69 }
70
TEST(InstructionTest,OperandAsString)71 TEST(InstructionTest, OperandAsString) {
72 Operand::OperandData abcde{0x64636261, 0x65};
73 Operand operand(SPV_OPERAND_TYPE_LITERAL_STRING, std::move(abcde));
74 EXPECT_EQ("abcde", operand.AsString());
75 }
76
TEST(InstructionTest,OperandAsLiteralUint64_32bits)77 TEST(InstructionTest, OperandAsLiteralUint64_32bits) {
78 Operand::OperandData words{0x1234};
79 Operand operand(SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, std::move(words));
80 EXPECT_EQ(uint64_t(0x1234), operand.AsLiteralUint64());
81 }
82
TEST(InstructionTest,OperandAsLiteralUint64_64bits)83 TEST(InstructionTest, OperandAsLiteralUint64_64bits) {
84 Operand::OperandData words{0x1234, 0x89ab};
85 Operand operand(SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER, std::move(words));
86 EXPECT_EQ((uint64_t(0x89ab) << 32 | 0x1234), operand.AsLiteralUint64());
87 }
88
89 // The words for an OpTypeInt for 32-bit signed integer resulting in Id 44.
90 uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44,
91 32, 1};
92 // The operands that would be parsed from kSampleInstructionWords
93 spv_parsed_operand_t kSampleParsedOperands[] = {
94 {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
95 {2, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 32},
96 {3, 1, SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_NUMBER_UNSIGNED_INT, 1},
97 };
98
99 // A valid parse of kSampleParsedOperands.
100 spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords,
101 uint16_t(4),
102 uint16_t(SpvOpTypeInt),
103 SPV_EXT_INST_TYPE_NONE,
104 0, // type id
105 44, // result id
106 kSampleParsedOperands,
107 3};
108
109 // The words for an OpAccessChain instruction.
110 uint32_t kSampleAccessChainInstructionWords[] = {
111 (7 << 16) | uint32_t(SpvOpAccessChain), 100, 101, 102, 103, 104, 105};
112
113 // The operands that would be parsed from kSampleAccessChainInstructionWords.
114 spv_parsed_operand_t kSampleAccessChainOperands[] = {
115 {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
116 {2, 1, SPV_OPERAND_TYPE_TYPE_ID, SPV_NUMBER_NONE, 0},
117 {3, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
118 {4, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
119 {5, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
120 {6, 1, SPV_OPERAND_TYPE_ID, SPV_NUMBER_NONE, 0},
121 };
122
123 // A valid parse of kSampleAccessChainInstructionWords
124 spv_parsed_instruction_t kSampleAccessChainInstruction = {
125 kSampleAccessChainInstructionWords,
126 uint16_t(7),
127 uint16_t(SpvOpAccessChain),
128 SPV_EXT_INST_TYPE_NONE,
129 100, // type id
130 101, // result id
131 kSampleAccessChainOperands,
132 6};
133
134 // The words for an OpControlBarrier instruction.
135 uint32_t kSampleControlBarrierInstructionWords[] = {
136 (4 << 16) | uint32_t(SpvOpControlBarrier), 100, 101, 102};
137
138 // The operands that would be parsed from kSampleControlBarrierInstructionWords.
139 spv_parsed_operand_t kSampleControlBarrierOperands[] = {
140 {1, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0}, // Execution
141 {2, 1, SPV_OPERAND_TYPE_SCOPE_ID, SPV_NUMBER_NONE, 0}, // Memory
142 {3, 1, SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID, SPV_NUMBER_NONE,
143 0}, // Semantics
144 };
145
146 // A valid parse of kSampleControlBarrierInstructionWords
147 spv_parsed_instruction_t kSampleControlBarrierInstruction = {
148 kSampleControlBarrierInstructionWords,
149 uint16_t(4),
150 uint16_t(SpvOpControlBarrier),
151 SPV_EXT_INST_TYPE_NONE,
152 0, // type id
153 0, // result id
154 kSampleControlBarrierOperands,
155 3};
156
TEST(InstructionTest,CreateWithOpcodeAndOperands)157 TEST(InstructionTest, CreateWithOpcodeAndOperands) {
158 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
159 Instruction inst(&context, kSampleParsedInstruction);
160 EXPECT_EQ(SpvOpTypeInt, inst.opcode());
161 EXPECT_EQ(0u, inst.type_id());
162 EXPECT_EQ(44u, inst.result_id());
163 EXPECT_EQ(3u, inst.NumOperands());
164 EXPECT_EQ(3u, inst.NumOperandWords());
165 EXPECT_EQ(2u, inst.NumInOperandWords());
166 }
167
TEST(InstructionTest,GetOperand)168 TEST(InstructionTest, GetOperand) {
169 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
170 Instruction inst(&context, kSampleParsedInstruction);
171 EXPECT_THAT(inst.GetOperand(0).words, Eq(std::vector<uint32_t>{44}));
172 EXPECT_THAT(inst.GetOperand(1).words, Eq(std::vector<uint32_t>{32}));
173 EXPECT_THAT(inst.GetOperand(2).words, Eq(std::vector<uint32_t>{1}));
174 }
175
TEST(InstructionTest,GetInOperand)176 TEST(InstructionTest, GetInOperand) {
177 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
178 Instruction inst(&context, kSampleParsedInstruction);
179 EXPECT_THAT(inst.GetInOperand(0).words, Eq(std::vector<uint32_t>{32}));
180 EXPECT_THAT(inst.GetInOperand(1).words, Eq(std::vector<uint32_t>{1}));
181 }
182
TEST(InstructionTest,OperandConstIterators)183 TEST(InstructionTest, OperandConstIterators) {
184 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
185 Instruction inst(&context, kSampleParsedInstruction);
186 // Spot check iteration across operands.
187 auto cbegin = inst.cbegin();
188 auto cend = inst.cend();
189 EXPECT_NE(cend, inst.cbegin());
190
191 auto citer = inst.cbegin();
192 for (int i = 0; i < 3; ++i, ++citer) {
193 const auto& operand = *citer;
194 EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
195 EXPECT_THAT(operand.words,
196 Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
197 EXPECT_NE(cend, citer);
198 }
199 EXPECT_EQ(cend, citer);
200
201 // Check that cbegin and cend have not changed.
202 EXPECT_EQ(cbegin, inst.cbegin());
203 EXPECT_EQ(cend, inst.cend());
204
205 // Check arithmetic.
206 const Operand& operand2 = *(inst.cbegin() + 2);
207 EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
208 }
209
TEST(InstructionTest,OperandIterators)210 TEST(InstructionTest, OperandIterators) {
211 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
212 Instruction inst(&context, kSampleParsedInstruction);
213 // Spot check iteration across operands, with mutable iterators.
214 auto begin = inst.begin();
215 auto end = inst.end();
216 EXPECT_NE(end, inst.begin());
217
218 auto iter = inst.begin();
219 for (int i = 0; i < 3; ++i, ++iter) {
220 const auto& operand = *iter;
221 EXPECT_THAT(operand.type, Eq(kSampleParsedOperands[i].type));
222 EXPECT_THAT(operand.words,
223 Eq(std::vector<uint32_t>{kSampleInstructionWords[i + 1]}));
224 EXPECT_NE(end, iter);
225 }
226 EXPECT_EQ(end, iter);
227
228 // Check that begin and end have not changed.
229 EXPECT_EQ(begin, inst.begin());
230 EXPECT_EQ(end, inst.end());
231
232 // Check arithmetic.
233 Operand& operand2 = *(inst.begin() + 2);
234 EXPECT_EQ(SPV_OPERAND_TYPE_LITERAL_INTEGER, operand2.type);
235
236 // Check mutation through an iterator.
237 operand2.type = SPV_OPERAND_TYPE_TYPE_ID;
238 EXPECT_EQ(SPV_OPERAND_TYPE_TYPE_ID, (*(inst.cbegin() + 2)).type);
239 }
240
TEST(InstructionTest,ForInIdStandardIdTypes)241 TEST(InstructionTest, ForInIdStandardIdTypes) {
242 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
243 Instruction inst(&context, kSampleAccessChainInstruction);
244
245 std::vector<uint32_t> ids;
246 inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
247 EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
248
249 ids.clear();
250 inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
251 EXPECT_THAT(ids, Eq(std::vector<uint32_t>{102, 103, 104, 105}));
252 }
253
TEST(InstructionTest,ForInIdNonstandardIdTypes)254 TEST(InstructionTest, ForInIdNonstandardIdTypes) {
255 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
256 Instruction inst(&context, kSampleControlBarrierInstruction);
257
258 std::vector<uint32_t> ids;
259 inst.ForEachInId([&ids](const uint32_t* idptr) { ids.push_back(*idptr); });
260 EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
261
262 ids.clear();
263 inst.ForEachInId([&ids](uint32_t* idptr) { ids.push_back(*idptr); });
264 EXPECT_THAT(ids, Eq(std::vector<uint32_t>{100, 101, 102}));
265 }
266
TEST(InstructionTest,UniqueIds)267 TEST(InstructionTest, UniqueIds) {
268 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
269 Instruction inst1(&context);
270 Instruction inst2(&context);
271 EXPECT_NE(inst1.unique_id(), inst2.unique_id());
272 }
273
TEST(InstructionTest,CloneUniqueIdDifferent)274 TEST(InstructionTest, CloneUniqueIdDifferent) {
275 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
276 Instruction inst(&context);
277 std::unique_ptr<Instruction> clone(inst.Clone(&context));
278 EXPECT_EQ(inst.context(), clone->context());
279 EXPECT_NE(inst.unique_id(), clone->unique_id());
280 }
281
TEST(InstructionTest,CloneDifferentContext)282 TEST(InstructionTest, CloneDifferentContext) {
283 IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr);
284 IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr);
285 Instruction inst(&c1);
286 std::unique_ptr<Instruction> clone(inst.Clone(&c2));
287 EXPECT_EQ(&c1, inst.context());
288 EXPECT_EQ(&c2, clone->context());
289 EXPECT_NE(&c1, &c2);
290 }
291
TEST(InstructionTest,CloneDifferentContextDifferentUniqueId)292 TEST(InstructionTest, CloneDifferentContextDifferentUniqueId) {
293 IRContext c1(SPV_ENV_UNIVERSAL_1_2, nullptr);
294 IRContext c2(SPV_ENV_UNIVERSAL_1_2, nullptr);
295 Instruction inst(&c1);
296 Instruction other(&c2);
297 std::unique_ptr<Instruction> clone(inst.Clone(&c2));
298 EXPECT_EQ(&c2, clone->context());
299 EXPECT_NE(other.unique_id(), clone->unique_id());
300 }
301
TEST(InstructionTest,EqualsEqualsOperator)302 TEST(InstructionTest, EqualsEqualsOperator) {
303 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
304 Instruction i1(&context);
305 Instruction i2(&context);
306 std::unique_ptr<Instruction> clone(i1.Clone(&context));
307 EXPECT_TRUE(i1 == i1);
308 EXPECT_FALSE(i1 == i2);
309 EXPECT_FALSE(i1 == *clone);
310 EXPECT_FALSE(i2 == *clone);
311 }
312
TEST(InstructionTest,LessThanOperator)313 TEST(InstructionTest, LessThanOperator) {
314 IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
315 Instruction i1(&context);
316 Instruction i2(&context);
317 std::unique_ptr<Instruction> clone(i1.Clone(&context));
318 EXPECT_TRUE(i1 < i2);
319 EXPECT_TRUE(i1 < *clone);
320 EXPECT_TRUE(i2 < *clone);
321 }
322
TEST_F(DescriptorTypeTest,StorageImage)323 TEST_F(DescriptorTypeTest, StorageImage) {
324 const std::string text = R"(
325 OpCapability Shader
326 %1 = OpExtInstImport "GLSL.std.450"
327 OpMemoryModel Logical GLSL450
328 OpEntryPoint Fragment %2 "main"
329 OpExecutionMode %2 OriginUpperLeft
330 OpSource GLSL 430
331 OpName %3 "myStorageImage"
332 OpDecorate %3 DescriptorSet 0
333 OpDecorate %3 Binding 0
334 %4 = OpTypeVoid
335 %5 = OpTypeFunction %4
336 %6 = OpTypeFloat 32
337 %7 = OpTypeImage %6 2D 0 0 0 2 R32f
338 %8 = OpTypePointer UniformConstant %7
339 %3 = OpVariable %8 UniformConstant
340 %2 = OpFunction %4 None %5
341 %9 = OpLabel
342 %10 = OpCopyObject %8 %3
343 OpReturn
344 OpFunctionEnd
345 )";
346
347 std::unique_ptr<IRContext> context =
348 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
349 Instruction* type = context->get_def_use_mgr()->GetDef(8);
350 EXPECT_TRUE(type->IsVulkanStorageImage());
351 EXPECT_FALSE(type->IsVulkanSampledImage());
352 EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
353 EXPECT_FALSE(type->IsVulkanStorageBuffer());
354 EXPECT_FALSE(type->IsVulkanUniformBuffer());
355
356 Instruction* variable = context->get_def_use_mgr()->GetDef(3);
357 EXPECT_FALSE(variable->IsReadOnlyPointer());
358
359 Instruction* object_copy = context->get_def_use_mgr()->GetDef(10);
360 EXPECT_FALSE(object_copy->IsReadOnlyPointer());
361 }
362
TEST_F(DescriptorTypeTest,SampledImage)363 TEST_F(DescriptorTypeTest, SampledImage) {
364 const std::string text = R"(
365 OpCapability Shader
366 %1 = OpExtInstImport "GLSL.std.450"
367 OpMemoryModel Logical GLSL450
368 OpEntryPoint Fragment %2 "main"
369 OpExecutionMode %2 OriginUpperLeft
370 OpSource GLSL 430
371 OpName %3 "myStorageImage"
372 OpDecorate %3 DescriptorSet 0
373 OpDecorate %3 Binding 0
374 %4 = OpTypeVoid
375 %5 = OpTypeFunction %4
376 %6 = OpTypeFloat 32
377 %7 = OpTypeImage %6 2D 0 0 0 1 Unknown
378 %8 = OpTypePointer UniformConstant %7
379 %3 = OpVariable %8 UniformConstant
380 %2 = OpFunction %4 None %5
381 %9 = OpLabel
382 %10 = OpCopyObject %8 %3
383 OpReturn
384 OpFunctionEnd
385 )";
386
387 std::unique_ptr<IRContext> context =
388 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
389 Instruction* type = context->get_def_use_mgr()->GetDef(8);
390 EXPECT_FALSE(type->IsVulkanStorageImage());
391 EXPECT_TRUE(type->IsVulkanSampledImage());
392 EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
393 EXPECT_FALSE(type->IsVulkanStorageBuffer());
394 EXPECT_FALSE(type->IsVulkanUniformBuffer());
395
396 Instruction* variable = context->get_def_use_mgr()->GetDef(3);
397 EXPECT_TRUE(variable->IsReadOnlyPointer());
398
399 Instruction* object_copy = context->get_def_use_mgr()->GetDef(10);
400 EXPECT_TRUE(object_copy->IsReadOnlyPointer());
401 }
402
TEST_F(DescriptorTypeTest,StorageTexelBuffer)403 TEST_F(DescriptorTypeTest, StorageTexelBuffer) {
404 const std::string text = R"(
405 OpCapability Shader
406 %1 = OpExtInstImport "GLSL.std.450"
407 OpMemoryModel Logical GLSL450
408 OpEntryPoint Fragment %2 "main"
409 OpExecutionMode %2 OriginUpperLeft
410 OpSource GLSL 430
411 OpName %3 "myStorageImage"
412 OpDecorate %3 DescriptorSet 0
413 OpDecorate %3 Binding 0
414 %4 = OpTypeVoid
415 %5 = OpTypeFunction %4
416 %6 = OpTypeFloat 32
417 %7 = OpTypeImage %6 Buffer 0 0 0 2 R32f
418 %8 = OpTypePointer UniformConstant %7
419 %3 = OpVariable %8 UniformConstant
420 %2 = OpFunction %4 None %5
421 %9 = OpLabel
422 %10 = OpCopyObject %8 %3
423 OpReturn
424 OpFunctionEnd
425 )";
426
427 std::unique_ptr<IRContext> context =
428 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
429 Instruction* type = context->get_def_use_mgr()->GetDef(8);
430 EXPECT_FALSE(type->IsVulkanStorageImage());
431 EXPECT_FALSE(type->IsVulkanSampledImage());
432 EXPECT_TRUE(type->IsVulkanStorageTexelBuffer());
433 EXPECT_FALSE(type->IsVulkanStorageBuffer());
434 EXPECT_FALSE(type->IsVulkanUniformBuffer());
435
436 Instruction* variable = context->get_def_use_mgr()->GetDef(3);
437 EXPECT_FALSE(variable->IsReadOnlyPointer());
438
439 Instruction* object_copy = context->get_def_use_mgr()->GetDef(10);
440 EXPECT_FALSE(object_copy->IsReadOnlyPointer());
441 }
442
TEST_F(DescriptorTypeTest,StorageBuffer)443 TEST_F(DescriptorTypeTest, StorageBuffer) {
444 const std::string text = R"(
445 OpCapability Shader
446 %1 = OpExtInstImport "GLSL.std.450"
447 OpMemoryModel Logical GLSL450
448 OpEntryPoint Fragment %2 "main"
449 OpExecutionMode %2 OriginUpperLeft
450 OpSource GLSL 430
451 OpName %3 "myStorageImage"
452 OpDecorate %3 DescriptorSet 0
453 OpDecorate %3 Binding 0
454 OpDecorate %9 BufferBlock
455 %4 = OpTypeVoid
456 %5 = OpTypeFunction %4
457 %6 = OpTypeFloat 32
458 %7 = OpTypeVector %6 4
459 %8 = OpTypeRuntimeArray %7
460 %9 = OpTypeStruct %8
461 %10 = OpTypePointer Uniform %9
462 %3 = OpVariable %10 Uniform
463 %2 = OpFunction %4 None %5
464 %11 = OpLabel
465 %12 = OpCopyObject %8 %3
466 OpReturn
467 OpFunctionEnd
468 )";
469
470 std::unique_ptr<IRContext> context =
471 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
472 Instruction* type = context->get_def_use_mgr()->GetDef(10);
473 EXPECT_FALSE(type->IsVulkanStorageImage());
474 EXPECT_FALSE(type->IsVulkanSampledImage());
475 EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
476 EXPECT_TRUE(type->IsVulkanStorageBuffer());
477 EXPECT_FALSE(type->IsVulkanUniformBuffer());
478
479 Instruction* variable = context->get_def_use_mgr()->GetDef(3);
480 EXPECT_FALSE(variable->IsReadOnlyPointer());
481
482 Instruction* object_copy = context->get_def_use_mgr()->GetDef(12);
483 EXPECT_FALSE(object_copy->IsReadOnlyPointer());
484 }
485
TEST_F(DescriptorTypeTest,UniformBuffer)486 TEST_F(DescriptorTypeTest, UniformBuffer) {
487 const std::string text = R"(
488 OpCapability Shader
489 %1 = OpExtInstImport "GLSL.std.450"
490 OpMemoryModel Logical GLSL450
491 OpEntryPoint Fragment %2 "main"
492 OpExecutionMode %2 OriginUpperLeft
493 OpSource GLSL 430
494 OpName %3 "myStorageImage"
495 OpDecorate %3 DescriptorSet 0
496 OpDecorate %3 Binding 0
497 OpDecorate %9 Block
498 %4 = OpTypeVoid
499 %5 = OpTypeFunction %4
500 %6 = OpTypeFloat 32
501 %7 = OpTypeVector %6 4
502 %8 = OpTypeRuntimeArray %7
503 %9 = OpTypeStruct %8
504 %10 = OpTypePointer Uniform %9
505 %3 = OpVariable %10 Uniform
506 %2 = OpFunction %4 None %5
507 %11 = OpLabel
508 %12 = OpCopyObject %10 %3
509 OpReturn
510 OpFunctionEnd
511 )";
512
513 std::unique_ptr<IRContext> context =
514 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
515 Instruction* type = context->get_def_use_mgr()->GetDef(10);
516 EXPECT_FALSE(type->IsVulkanStorageImage());
517 EXPECT_FALSE(type->IsVulkanSampledImage());
518 EXPECT_FALSE(type->IsVulkanStorageTexelBuffer());
519 EXPECT_FALSE(type->IsVulkanStorageBuffer());
520 EXPECT_TRUE(type->IsVulkanUniformBuffer());
521
522 Instruction* variable = context->get_def_use_mgr()->GetDef(3);
523 EXPECT_TRUE(variable->IsReadOnlyPointer());
524
525 Instruction* object_copy = context->get_def_use_mgr()->GetDef(12);
526 EXPECT_TRUE(object_copy->IsReadOnlyPointer());
527 }
528
TEST_F(DescriptorTypeTest,NonWritableIsReadOnly)529 TEST_F(DescriptorTypeTest, NonWritableIsReadOnly) {
530 const std::string text = R"(
531 OpCapability Shader
532 %1 = OpExtInstImport "GLSL.std.450"
533 OpMemoryModel Logical GLSL450
534 OpEntryPoint Fragment %2 "main"
535 OpExecutionMode %2 OriginUpperLeft
536 OpSource GLSL 430
537 OpName %3 "myStorageImage"
538 OpDecorate %3 DescriptorSet 0
539 OpDecorate %3 Binding 0
540 OpDecorate %9 BufferBlock
541 OpDecorate %3 NonWritable
542 %4 = OpTypeVoid
543 %5 = OpTypeFunction %4
544 %6 = OpTypeFloat 32
545 %7 = OpTypeVector %6 4
546 %8 = OpTypeRuntimeArray %7
547 %9 = OpTypeStruct %8
548 %10 = OpTypePointer Uniform %9
549 %3 = OpVariable %10 Uniform
550 %2 = OpFunction %4 None %5
551 %11 = OpLabel
552 %12 = OpCopyObject %8 %3
553 OpReturn
554 OpFunctionEnd
555 )";
556
557 std::unique_ptr<IRContext> context =
558 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
559 Instruction* variable = context->get_def_use_mgr()->GetDef(3);
560 EXPECT_TRUE(variable->IsReadOnlyPointer());
561
562 // This demonstrates that the check for whether a pointer is read-only is not
563 // precise: copying a NonWritable-decorated variable can yield a pointer that
564 // the check does not regard as read-only.
565 Instruction* object_copy = context->get_def_use_mgr()->GetDef(12);
566 EXPECT_FALSE(object_copy->IsReadOnlyPointer());
567 }
568
TEST_F(DescriptorTypeTest,AccessChainIntoReadOnlyStructIsReadOnly)569 TEST_F(DescriptorTypeTest, AccessChainIntoReadOnlyStructIsReadOnly) {
570 const std::string text = R"(
571 OpCapability Shader
572 %1 = OpExtInstImport "GLSL.std.450"
573 OpMemoryModel Logical GLSL450
574 OpEntryPoint Fragment %2 "main"
575 OpExecutionMode %2 OriginUpperLeft
576 OpSource ESSL 320
577 OpMemberDecorate %3 0 Offset 0
578 OpMemberDecorate %3 1 Offset 4
579 OpDecorate %3 Block
580 %4 = OpTypeVoid
581 %5 = OpTypeFunction %4
582 %6 = OpTypeInt 32 1
583 %7 = OpTypePointer Function %6
584 %8 = OpTypeFloat 32
585 %3 = OpTypeStruct %6 %8
586 %9 = OpTypePointer PushConstant %3
587 %10 = OpVariable %9 PushConstant
588 %11 = OpConstant %6 0
589 %12 = OpTypePointer PushConstant %6
590 %13 = OpConstant %6 1
591 %14 = OpTypePointer PushConstant %8
592 %2 = OpFunction %4 None %5
593 %15 = OpLabel
594 %16 = OpVariable %7 Function
595 %17 = OpAccessChain %12 %10 %11
596 %18 = OpAccessChain %14 %10 %13
597 OpReturn
598 OpFunctionEnd
599 )";
600
601 std::unique_ptr<IRContext> context =
602 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
603
604 Instruction* push_constant_struct_variable =
605 context->get_def_use_mgr()->GetDef(10);
606 EXPECT_TRUE(push_constant_struct_variable->IsReadOnlyPointer());
607
608 Instruction* push_constant_struct_field_0 =
609 context->get_def_use_mgr()->GetDef(17);
610 EXPECT_TRUE(push_constant_struct_field_0->IsReadOnlyPointer());
611
612 Instruction* push_constant_struct_field_1 =
613 context->get_def_use_mgr()->GetDef(18);
614 EXPECT_TRUE(push_constant_struct_field_1->IsReadOnlyPointer());
615 }
616
TEST_F(DescriptorTypeTest,ReadOnlyPointerParameter)617 TEST_F(DescriptorTypeTest, ReadOnlyPointerParameter) {
618 const std::string text = R"(
619 OpCapability Shader
620 %1 = OpExtInstImport "GLSL.std.450"
621 OpMemoryModel Logical GLSL450
622 OpEntryPoint Fragment %2 "main"
623 OpExecutionMode %2 OriginUpperLeft
624 OpSource ESSL 320
625 OpMemberDecorate %3 0 Offset 0
626 OpMemberDecorate %3 1 Offset 4
627 OpDecorate %3 Block
628 %4 = OpTypeVoid
629 %5 = OpTypeFunction %4
630 %6 = OpTypeInt 32 1
631 %7 = OpTypePointer Function %6
632 %8 = OpTypeFloat 32
633 %3 = OpTypeStruct %6 %8
634 %9 = OpTypePointer PushConstant %3
635 %10 = OpVariable %9 PushConstant
636 %11 = OpConstant %6 0
637 %12 = OpTypePointer PushConstant %6
638 %13 = OpConstant %6 1
639 %14 = OpTypePointer PushConstant %8
640 %15 = OpTypeFunction %4 %9
641 %2 = OpFunction %4 None %5
642 %16 = OpLabel
643 %17 = OpVariable %7 Function
644 %18 = OpAccessChain %12 %10 %11
645 %19 = OpAccessChain %14 %10 %13
646 OpReturn
647 OpFunctionEnd
648 %20 = OpFunction %4 None %15
649 %21 = OpFunctionParameter %9
650 %22 = OpLabel
651 OpReturn
652 OpFunctionEnd
653 )";
654
655 std::unique_ptr<IRContext> context =
656 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
657
658 Instruction* push_constant_struct_parameter =
659 context->get_def_use_mgr()->GetDef(21);
660 EXPECT_TRUE(push_constant_struct_parameter->IsReadOnlyPointer());
661 }
662
TEST_F(OpaqueTypeTest,BaseOpaqueTypesShader)663 TEST_F(OpaqueTypeTest, BaseOpaqueTypesShader) {
664 const std::string text = R"(
665 OpCapability Shader
666 %1 = OpExtInstImport "GLSL.std.450"
667 OpMemoryModel Logical GLSL450
668 OpEntryPoint Fragment %2 "main"
669 OpExecutionMode %2 OriginUpperLeft
670 OpSource GLSL 430
671 %3 = OpTypeVoid
672 %4 = OpTypeFunction %3
673 %5 = OpTypeFloat 32
674 %6 = OpTypeImage %5 2D 1 0 0 1 Unknown
675 %7 = OpTypeSampler
676 %8 = OpTypeSampledImage %6
677 %9 = OpTypeRuntimeArray %5
678 %2 = OpFunction %3 None %4
679 %10 = OpLabel
680 OpReturn
681 OpFunctionEnd
682 )";
683
684 std::unique_ptr<IRContext> context =
685 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
686 Instruction* image_type = context->get_def_use_mgr()->GetDef(6);
687 EXPECT_TRUE(image_type->IsOpaqueType());
688 Instruction* sampler_type = context->get_def_use_mgr()->GetDef(7);
689 EXPECT_TRUE(sampler_type->IsOpaqueType());
690 Instruction* sampled_image_type = context->get_def_use_mgr()->GetDef(8);
691 EXPECT_TRUE(sampled_image_type->IsOpaqueType());
692 Instruction* runtime_array_type = context->get_def_use_mgr()->GetDef(9);
693 EXPECT_TRUE(runtime_array_type->IsOpaqueType());
694 Instruction* float_type = context->get_def_use_mgr()->GetDef(5);
695 EXPECT_FALSE(float_type->IsOpaqueType());
696 Instruction* void_type = context->get_def_use_mgr()->GetDef(3);
697 EXPECT_FALSE(void_type->IsOpaqueType());
698 }
699
TEST_F(OpaqueTypeTest,OpaqueStructTypes)700 TEST_F(OpaqueTypeTest, OpaqueStructTypes) {
701 const std::string text = R"(
702 OpCapability Shader
703 %1 = OpExtInstImport "GLSL.std.450"
704 OpMemoryModel Logical GLSL450
705 OpEntryPoint Fragment %2 "main"
706 OpExecutionMode %2 OriginUpperLeft
707 OpSource GLSL 430
708 %3 = OpTypeVoid
709 %4 = OpTypeFunction %3
710 %5 = OpTypeFloat 32
711 %6 = OpTypeRuntimeArray %5
712 %7 = OpTypeStruct %6 %6
713 %8 = OpTypeStruct %5 %6
714 %9 = OpTypeStruct %6 %5
715 %10 = OpTypeStruct %7
716 %2 = OpFunction %3 None %4
717 %11 = OpLabel
718 OpReturn
719 OpFunctionEnd
720 )";
721
722 std::unique_ptr<IRContext> context =
723 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
724 for (int i = 7; i <= 10; i++) {
725 Instruction* type = context->get_def_use_mgr()->GetDef(i);
726 EXPECT_TRUE(type->IsOpaqueType());
727 }
728 }
729
TEST_F(GetBaseTest,SampleImage)730 TEST_F(GetBaseTest, SampleImage) {
731 const std::string text = R"(
732 OpCapability Shader
733 %1 = OpExtInstImport "GLSL.std.450"
734 OpMemoryModel Logical GLSL450
735 OpEntryPoint Fragment %2 "main"
736 OpExecutionMode %2 OriginUpperLeft
737 OpSource GLSL 430
738 OpName %3 "myStorageImage"
739 OpDecorate %3 DescriptorSet 0
740 OpDecorate %3 Binding 0
741 %4 = OpTypeVoid
742 %5 = OpTypeFunction %4
743 %6 = OpTypeFloat 32
744 %7 = OpTypeVector %6 2
745 %8 = OpTypeVector %6 4
746 %9 = OpConstant %6 0
747 %10 = OpConstantComposite %7 %9 %9
748 %11 = OpTypeImage %6 2D 0 0 0 1 R32f
749 %12 = OpTypePointer UniformConstant %11
750 %3 = OpVariable %12 UniformConstant
751 %13 = OpTypeSampledImage %11
752 %14 = OpTypeSampler
753 %15 = OpTypePointer UniformConstant %14
754 %16 = OpVariable %15 UniformConstant
755 %2 = OpFunction %4 None %5
756 %17 = OpLabel
757 %18 = OpLoad %11 %3
758 %19 = OpLoad %14 %16
759 %20 = OpSampledImage %13 %18 %19
760 %21 = OpImageSampleImplicitLod %8 %20 %10
761 OpReturn
762 OpFunctionEnd
763 )";
764
765 std::unique_ptr<IRContext> context =
766 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
767 Instruction* load = context->get_def_use_mgr()->GetDef(21);
768 Instruction* base = context->get_def_use_mgr()->GetDef(20);
769 EXPECT_TRUE(load->GetBaseAddress() == base);
770 }
771
TEST_F(GetBaseTest,PtrAccessChain)772 TEST_F(GetBaseTest, PtrAccessChain) {
773 const std::string text = R"(
774 OpCapability VariablePointers
775 OpMemoryModel Logical GLSL450
776 OpEntryPoint Fragment %1 "PSMain" %2
777 OpExecutionMode %1 OriginUpperLeft
778 %void = OpTypeVoid
779 %4 = OpTypeFunction %void
780 %float = OpTypeFloat 32
781 %v4float = OpTypeVector %float 4
782 %int = OpTypeInt 32 8388353
783 %int_0 = OpConstant %int 0
784 %_ptr_Function_v4float = OpTypePointer Function %v4float
785 %2 = OpVariable %_ptr_Function_v4float Input
786 %1 = OpFunction %void None %4
787 %10 = OpLabel
788 %11 = OpPtrAccessChain %_ptr_Function_v4float %2 %int_0
789 %12 = OpLoad %v4float %11
790 OpReturn
791 OpFunctionEnd
792 )";
793
794 std::unique_ptr<IRContext> context =
795 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
796 Instruction* load = context->get_def_use_mgr()->GetDef(12);
797 Instruction* base = context->get_def_use_mgr()->GetDef(2);
798 EXPECT_TRUE(load->GetBaseAddress() == base);
799 }
800
TEST_F(GetBaseTest,ImageRead)801 TEST_F(GetBaseTest, ImageRead) {
802 const std::string text = R"(
803 OpCapability Shader
804 %1 = OpExtInstImport "GLSL.std.450"
805 OpMemoryModel Logical GLSL450
806 OpEntryPoint Fragment %2 "main"
807 OpExecutionMode %2 OriginUpperLeft
808 OpSource GLSL 430
809 OpName %3 "myStorageImage"
810 OpDecorate %3 DescriptorSet 0
811 OpDecorate %3 Binding 0
812 %4 = OpTypeVoid
813 %5 = OpTypeFunction %4
814 %6 = OpTypeInt 32 0
815 %7 = OpTypeVector %6 2
816 %8 = OpConstant %6 0
817 %9 = OpConstantComposite %7 %8 %8
818 %10 = OpTypeImage %6 2D 0 0 0 2 R32f
819 %11 = OpTypePointer UniformConstant %10
820 %3 = OpVariable %11 UniformConstant
821 %2 = OpFunction %4 None %5
822 %12 = OpLabel
823 %13 = OpLoad %10 %3
824 %14 = OpImageRead %6 %13 %9
825 OpReturn
826 OpFunctionEnd
827 )";
828
829 std::unique_ptr<IRContext> context =
830 BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
831 Instruction* load = context->get_def_use_mgr()->GetDef(14);
832 Instruction* base = context->get_def_use_mgr()->GetDef(13);
833 EXPECT_TRUE(load->GetBaseAddress() == base);
834 }
835
TEST_F(ValidBasePointerTest,OpSelectBadNoVariablePointersStorageBuffer)836 TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointersStorageBuffer) {
837 const std::string text = R"(
838 OpCapability Shader
839 OpMemoryModel Logical GLSL450
840 OpEntryPoint Fragment %1 "func"
841 %2 = OpTypeVoid
842 %3 = OpTypeInt 32 0
843 %4 = OpTypePointer StorageBuffer %3
844 %5 = OpVariable %4 StorageBuffer
845 %6 = OpTypeFunction %2
846 %7 = OpTypeBool
847 %8 = OpConstantTrue %7
848 %1 = OpFunction %2 None %6
849 %9 = OpLabel
850 %10 = OpSelect %4 %8 %5 %5
851 OpReturn
852 OpFunctionEnd
853 )";
854
855 std::unique_ptr<IRContext> context =
856 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
857 EXPECT_NE(context, nullptr);
858 Instruction* select = context->get_def_use_mgr()->GetDef(10);
859 EXPECT_NE(select, nullptr);
860 EXPECT_FALSE(select->IsValidBasePointer());
861 }
862
TEST_F(ValidBasePointerTest,OpSelectBadNoVariablePointers)863 TEST_F(ValidBasePointerTest, OpSelectBadNoVariablePointers) {
864 const std::string text = R"(
865 OpCapability Shader
866 OpCapability VariablePointersStorageBuffer
867 OpMemoryModel Logical GLSL450
868 OpEntryPoint Fragment %1 "func"
869 %2 = OpTypeVoid
870 %3 = OpTypeInt 32 0
871 %4 = OpTypePointer Workgroup %3
872 %5 = OpVariable %4 Workgroup
873 %6 = OpTypeFunction %2
874 %7 = OpTypeBool
875 %8 = OpConstantTrue %7
876 %1 = OpFunction %2 None %6
877 %9 = OpLabel
878 %10 = OpSelect %4 %8 %5 %5
879 OpReturn
880 OpFunctionEnd
881 )";
882
883 std::unique_ptr<IRContext> context =
884 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
885 EXPECT_NE(context, nullptr);
886 Instruction* select = context->get_def_use_mgr()->GetDef(10);
887 EXPECT_NE(select, nullptr);
888 EXPECT_FALSE(select->IsValidBasePointer());
889 }
890
TEST_F(ValidBasePointerTest,OpSelectGoodVariablePointersStorageBuffer)891 TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointersStorageBuffer) {
892 const std::string text = R"(
893 OpCapability Shader
894 OpCapability VariablePointersStorageBuffer
895 OpMemoryModel Logical GLSL450
896 OpEntryPoint Fragment %1 "func"
897 %2 = OpTypeVoid
898 %3 = OpTypeInt 32 0
899 %4 = OpTypePointer StorageBuffer %3
900 %5 = OpVariable %4 StorageBuffer
901 %6 = OpTypeFunction %2
902 %7 = OpTypeBool
903 %8 = OpConstantTrue %7
904 %1 = OpFunction %2 None %6
905 %9 = OpLabel
906 %10 = OpSelect %4 %8 %5 %5
907 OpReturn
908 OpFunctionEnd
909 )";
910
911 std::unique_ptr<IRContext> context =
912 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
913 EXPECT_NE(context, nullptr);
914 Instruction* select = context->get_def_use_mgr()->GetDef(10);
915 EXPECT_NE(select, nullptr);
916 EXPECT_TRUE(select->IsValidBasePointer());
917 }
918
TEST_F(ValidBasePointerTest,OpSelectGoodVariablePointers)919 TEST_F(ValidBasePointerTest, OpSelectGoodVariablePointers) {
920 const std::string text = R"(
921 OpCapability Shader
922 OpCapability VariablePointers
923 OpMemoryModel Logical GLSL450
924 OpEntryPoint Fragment %1 "func"
925 %2 = OpTypeVoid
926 %3 = OpTypeInt 32 0
927 %4 = OpTypePointer Workgroup %3
928 %5 = OpVariable %4 Workgroup
929 %6 = OpTypeFunction %2
930 %7 = OpTypeBool
931 %8 = OpConstantTrue %7
932 %1 = OpFunction %2 None %6
933 %9 = OpLabel
934 %10 = OpSelect %4 %8 %5 %5
935 OpReturn
936 OpFunctionEnd
937 )";
938
939 std::unique_ptr<IRContext> context =
940 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
941 EXPECT_NE(context, nullptr);
942 Instruction* select = context->get_def_use_mgr()->GetDef(10);
943 EXPECT_NE(select, nullptr);
944 EXPECT_TRUE(select->IsValidBasePointer());
945 }
946
TEST_F(ValidBasePointerTest,OpConstantNullBadNoVariablePointersStorageBuffer)947 TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointersStorageBuffer) {
948 const std::string text = R"(
949 OpCapability Shader
950 OpMemoryModel Logical GLSL450
951 OpEntryPoint Fragment %1 "func"
952 %2 = OpTypeVoid
953 %3 = OpTypeInt 32 0
954 %4 = OpTypePointer StorageBuffer %3
955 %5 = OpConstantNull %4
956 %6 = OpTypeFunction %2
957 %1 = OpFunction %2 None %6
958 %7 = OpLabel
959 OpReturn
960 OpFunctionEnd
961 )";
962
963 std::unique_ptr<IRContext> context =
964 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
965 EXPECT_NE(context, nullptr);
966 Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
967 EXPECT_NE(null_inst, nullptr);
968 EXPECT_FALSE(null_inst->IsValidBasePointer());
969 }
970
TEST_F(ValidBasePointerTest,OpConstantNullBadNoVariablePointers)971 TEST_F(ValidBasePointerTest, OpConstantNullBadNoVariablePointers) {
972 const std::string text = R"(
973 OpCapability Shader
974 OpCapability VariablePointersStorageBuffer
975 OpMemoryModel Logical GLSL450
976 OpEntryPoint Fragment %1 "func"
977 %2 = OpTypeVoid
978 %3 = OpTypeInt 32 0
979 %4 = OpTypePointer Workgroup %3
980 %5 = OpConstantNull %4
981 %6 = OpTypeFunction %2
982 %1 = OpFunction %2 None %6
983 %7 = OpLabel
984 OpReturn
985 OpFunctionEnd
986 )";
987
988 std::unique_ptr<IRContext> context =
989 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
990 EXPECT_NE(context, nullptr);
991 Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
992 EXPECT_NE(null_inst, nullptr);
993 EXPECT_FALSE(null_inst->IsValidBasePointer());
994 }
995
TEST_F(ValidBasePointerTest,OpConstantNullGoodVariablePointersStorageBuffer)996 TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointersStorageBuffer) {
997 const std::string text = R"(
998 OpCapability Shader
999 OpCapability VariablePointersStorageBuffer
1000 OpMemoryModel Logical GLSL450
1001 OpEntryPoint Fragment %1 "func"
1002 %2 = OpTypeVoid
1003 %3 = OpTypeInt 32 0
1004 %4 = OpTypePointer StorageBuffer %3
1005 %5 = OpConstantNull %4
1006 %6 = OpTypeFunction %2
1007 %1 = OpFunction %2 None %6
1008 %9 = OpLabel
1009 OpReturn
1010 OpFunctionEnd
1011 )";
1012
1013 std::unique_ptr<IRContext> context =
1014 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1015 EXPECT_NE(context, nullptr);
1016 Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
1017 EXPECT_NE(null_inst, nullptr);
1018 EXPECT_TRUE(null_inst->IsValidBasePointer());
1019 }
1020
TEST_F(ValidBasePointerTest,OpConstantNullGoodVariablePointers)1021 TEST_F(ValidBasePointerTest, OpConstantNullGoodVariablePointers) {
1022 const std::string text = R"(
1023 OpCapability Shader
1024 OpCapability VariablePointers
1025 OpMemoryModel Logical GLSL450
1026 OpEntryPoint Fragment %1 "func"
1027 %2 = OpTypeVoid
1028 %3 = OpTypeInt 32 0
1029 %4 = OpTypePointer Workgroup %3
1030 %5 = OpConstantNull %4
1031 %6 = OpTypeFunction %2
1032 %1 = OpFunction %2 None %6
1033 %7 = OpLabel
1034 OpReturn
1035 OpFunctionEnd
1036 )";
1037
1038 std::unique_ptr<IRContext> context =
1039 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1040 EXPECT_NE(context, nullptr);
1041 Instruction* null_inst = context->get_def_use_mgr()->GetDef(5);
1042 EXPECT_NE(null_inst, nullptr);
1043 EXPECT_TRUE(null_inst->IsValidBasePointer());
1044 }
1045
TEST_F(ValidBasePointerTest,OpPhiBadNoVariablePointersStorageBuffer)1046 TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointersStorageBuffer) {
1047 const std::string text = R"(
1048 OpCapability Shader
1049 OpMemoryModel Logical GLSL450
1050 OpEntryPoint Fragment %1 "func"
1051 %2 = OpTypeVoid
1052 %3 = OpTypeInt 32 0
1053 %4 = OpTypePointer StorageBuffer %3
1054 %5 = OpVariable %4 StorageBuffer
1055 %6 = OpTypeFunction %2
1056 %1 = OpFunction %2 None %6
1057 %7 = OpLabel
1058 OpBranch %8
1059 %8 = OpLabel
1060 %9 = OpPhi %4 %5 %7
1061 OpReturn
1062 OpFunctionEnd
1063 )";
1064
1065 std::unique_ptr<IRContext> context =
1066 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1067 EXPECT_NE(context, nullptr);
1068 Instruction* phi = context->get_def_use_mgr()->GetDef(9);
1069 EXPECT_NE(phi, nullptr);
1070 EXPECT_FALSE(phi->IsValidBasePointer());
1071 }
1072
TEST_F(ValidBasePointerTest,OpPhiBadNoVariablePointers)1073 TEST_F(ValidBasePointerTest, OpPhiBadNoVariablePointers) {
1074 const std::string text = R"(
1075 OpCapability Shader
1076 OpCapability VariablePointersStorageBuffer
1077 OpMemoryModel Logical GLSL450
1078 OpEntryPoint Fragment %1 "func"
1079 %2 = OpTypeVoid
1080 %3 = OpTypeInt 32 0
1081 %4 = OpTypePointer Workgroup %3
1082 %5 = OpVariable %4 Workgroup
1083 %6 = OpTypeFunction %2
1084 %1 = OpFunction %2 None %6
1085 %7 = OpLabel
1086 OpBranch %8
1087 %8 = OpLabel
1088 %9 = OpPhi %4 %5 %7
1089 OpReturn
1090 OpFunctionEnd
1091 )";
1092
1093 std::unique_ptr<IRContext> context =
1094 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1095 EXPECT_NE(context, nullptr);
1096 Instruction* phi = context->get_def_use_mgr()->GetDef(9);
1097 EXPECT_NE(phi, nullptr);
1098 EXPECT_FALSE(phi->IsValidBasePointer());
1099 }
1100
TEST_F(ValidBasePointerTest,OpPhiGoodVariablePointersStorageBuffer)1101 TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointersStorageBuffer) {
1102 const std::string text = R"(
1103 OpCapability Shader
1104 OpCapability VariablePointersStorageBuffer
1105 OpMemoryModel Logical GLSL450
1106 OpEntryPoint Fragment %1 "func"
1107 %2 = OpTypeVoid
1108 %3 = OpTypeInt 32 0
1109 %4 = OpTypePointer StorageBuffer %3
1110 %5 = OpVariable %4 StorageBuffer
1111 %6 = OpTypeFunction %2
1112 %1 = OpFunction %2 None %6
1113 %7 = OpLabel
1114 OpBranch %8
1115 %8 = OpLabel
1116 %9 = OpPhi %4 %5 %7
1117 OpReturn
1118 OpFunctionEnd
1119 )";
1120
1121 std::unique_ptr<IRContext> context =
1122 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1123 EXPECT_NE(context, nullptr);
1124 Instruction* phi = context->get_def_use_mgr()->GetDef(9);
1125 EXPECT_NE(phi, nullptr);
1126 EXPECT_TRUE(phi->IsValidBasePointer());
1127 }
1128
TEST_F(ValidBasePointerTest,OpPhiGoodVariablePointers)1129 TEST_F(ValidBasePointerTest, OpPhiGoodVariablePointers) {
1130 const std::string text = R"(
1131 OpCapability Shader
1132 OpCapability VariablePointers
1133 OpMemoryModel Logical GLSL450
1134 OpEntryPoint Fragment %1 "func"
1135 %2 = OpTypeVoid
1136 %3 = OpTypeInt 32 0
1137 %4 = OpTypePointer Workgroup %3
1138 %5 = OpVariable %4 Workgroup
1139 %6 = OpTypeFunction %2
1140 %1 = OpFunction %2 None %6
1141 %7 = OpLabel
1142 OpBranch %8
1143 %8 = OpLabel
1144 %9 = OpPhi %4 %5 %7
1145 OpReturn
1146 OpFunctionEnd
1147 )";
1148
1149 std::unique_ptr<IRContext> context =
1150 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1151 EXPECT_NE(context, nullptr);
1152 Instruction* phi = context->get_def_use_mgr()->GetDef(9);
1153 EXPECT_NE(phi, nullptr);
1154 EXPECT_TRUE(phi->IsValidBasePointer());
1155 }
1156
TEST_F(ValidBasePointerTest,OpFunctionCallBadNoVariablePointersStorageBuffer)1157 TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointersStorageBuffer) {
1158 const std::string text = R"(
1159 OpCapability Shader
1160 OpMemoryModel Logical GLSL450
1161 OpEntryPoint Fragment %1 "func"
1162 %2 = OpTypeVoid
1163 %3 = OpTypeInt 32 0
1164 %4 = OpTypePointer StorageBuffer %3
1165 %5 = OpConstantNull %4
1166 %6 = OpTypeFunction %2
1167 %7 = OpTypeFunction %4
1168 %1 = OpFunction %2 None %6
1169 %8 = OpLabel
1170 %9 = OpFunctionCall %4 %10
1171 OpReturn
1172 OpFunctionEnd
1173 %10 = OpFunction %4 None %7
1174 %11 = OpLabel
1175 OpReturnValue %5
1176 OpFunctionEnd
1177 )";
1178
1179 std::unique_ptr<IRContext> context =
1180 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1181 EXPECT_NE(context, nullptr);
1182 Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1183 EXPECT_NE(null_inst, nullptr);
1184 EXPECT_FALSE(null_inst->IsValidBasePointer());
1185 }
1186
TEST_F(ValidBasePointerTest,OpFunctionCallBadNoVariablePointers)1187 TEST_F(ValidBasePointerTest, OpFunctionCallBadNoVariablePointers) {
1188 const std::string text = R"(
1189 OpCapability Shader
1190 OpCapability VariablePointersStorageBuffer
1191 OpMemoryModel Logical GLSL450
1192 OpEntryPoint Fragment %1 "func"
1193 %2 = OpTypeVoid
1194 %3 = OpTypeInt 32 0
1195 %4 = OpTypePointer Workgroup %3
1196 %5 = OpConstantNull %4
1197 %6 = OpTypeFunction %2
1198 %7 = OpTypeFunction %4
1199 %1 = OpFunction %2 None %6
1200 %8 = OpLabel
1201 %9 = OpFunctionCall %4 %10
1202 OpReturn
1203 OpFunctionEnd
1204 %10 = OpFunction %4 None %7
1205 %11 = OpLabel
1206 OpReturnValue %5
1207 OpFunctionEnd
1208 )";
1209
1210 std::unique_ptr<IRContext> context =
1211 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1212 EXPECT_NE(context, nullptr);
1213 Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1214 EXPECT_NE(null_inst, nullptr);
1215 EXPECT_FALSE(null_inst->IsValidBasePointer());
1216 }
1217
TEST_F(ValidBasePointerTest,OpFunctionCallGoodVariablePointersStorageBuffer)1218 TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointersStorageBuffer) {
1219 const std::string text = R"(
1220 OpCapability Shader
1221 OpCapability VariablePointersStorageBuffer
1222 OpMemoryModel Logical GLSL450
1223 OpEntryPoint Fragment %1 "func"
1224 %2 = OpTypeVoid
1225 %3 = OpTypeInt 32 0
1226 %4 = OpTypePointer StorageBuffer %3
1227 %5 = OpConstantNull %4
1228 %6 = OpTypeFunction %2
1229 %7 = OpTypeFunction %4
1230 %1 = OpFunction %2 None %6
1231 %8 = OpLabel
1232 %9 = OpFunctionCall %4 %10
1233 OpReturn
1234 OpFunctionEnd
1235 %10 = OpFunction %4 None %7
1236 %11 = OpLabel
1237 OpReturnValue %5
1238 OpFunctionEnd
1239 )";
1240
1241 std::unique_ptr<IRContext> context =
1242 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1243 EXPECT_NE(context, nullptr);
1244 Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1245 EXPECT_NE(null_inst, nullptr);
1246 EXPECT_TRUE(null_inst->IsValidBasePointer());
1247 }
1248
TEST_F(ValidBasePointerTest,OpFunctionCallGoodVariablePointers)1249 TEST_F(ValidBasePointerTest, OpFunctionCallGoodVariablePointers) {
1250 const std::string text = R"(
1251 OpCapability Shader
1252 OpCapability VariablePointers
1253 OpMemoryModel Logical GLSL450
1254 OpEntryPoint Fragment %1 "func"
1255 %2 = OpTypeVoid
1256 %3 = OpTypeInt 32 0
1257 %4 = OpTypePointer Workgroup %3
1258 %5 = OpConstantNull %4
1259 %6 = OpTypeFunction %2
1260 %7 = OpTypeFunction %4
1261 %1 = OpFunction %2 None %6
1262 %8 = OpLabel
1263 %9 = OpFunctionCall %4 %10
1264 OpReturn
1265 OpFunctionEnd
1266 %10 = OpFunction %4 None %7
1267 %11 = OpLabel
1268 OpReturnValue %5
1269 OpFunctionEnd
1270 )";
1271
1272 std::unique_ptr<IRContext> context =
1273 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1274 EXPECT_NE(context, nullptr);
1275 Instruction* null_inst = context->get_def_use_mgr()->GetDef(9);
1276 EXPECT_NE(null_inst, nullptr);
1277 EXPECT_TRUE(null_inst->IsValidBasePointer());
1278 }
1279
TEST_F(VulkanBufferTest,VulkanStorageBuffer)1280 TEST_F(VulkanBufferTest, VulkanStorageBuffer) {
1281 const std::string text = R"(
1282 OpCapability Shader
1283 OpCapability RuntimeDescriptorArray
1284 OpMemoryModel Logical GLSL450
1285 OpEntryPoint GLCompute %1 "main"
1286 OpExecutionMode %1 LocalSize 1 1 1
1287 OpDecorate %2 Block
1288 OpMemberDecorate %2 0 Offset 0
1289 OpDecorate %3 BufferBlock
1290 OpMemberDecorate %3 0 Offset 0
1291 %4 = OpTypeVoid
1292 %5 = OpTypeInt 32 0
1293 %2 = OpTypeStruct %5
1294 %3 = OpTypeStruct %5
1295
1296 %6 = OpTypePointer StorageBuffer %2
1297 %7 = OpTypePointer Uniform %2
1298 %8 = OpTypePointer Uniform %3
1299
1300 %9 = OpConstant %5 1
1301 %10 = OpTypeArray %2 %9
1302 %11 = OpTypeArray %3 %9
1303 %12 = OpTypePointer StorageBuffer %10
1304 %13 = OpTypePointer Uniform %10
1305 %14 = OpTypePointer Uniform %11
1306
1307 %15 = OpTypeRuntimeArray %2
1308 %16 = OpTypeRuntimeArray %3
1309 %17 = OpTypePointer StorageBuffer %15
1310 %18 = OpTypePointer Uniform %15
1311 %19 = OpTypePointer Uniform %16
1312
1313 %50 = OpTypeFunction %4
1314 %1 = OpFunction %4 None %50
1315 %51 = OpLabel
1316 OpReturn
1317 OpFunctionEnd
1318 )";
1319
1320 std::unique_ptr<IRContext> context =
1321 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1322 EXPECT_NE(context, nullptr);
1323
1324 // Standard SSBO and UBO
1325 Instruction* inst = context->get_def_use_mgr()->GetDef(6);
1326 EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1327 inst = context->get_def_use_mgr()->GetDef(7);
1328 EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
1329 inst = context->get_def_use_mgr()->GetDef(8);
1330 EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1331
1332 // Arrayed SSBO and UBO
1333 inst = context->get_def_use_mgr()->GetDef(12);
1334 EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1335 inst = context->get_def_use_mgr()->GetDef(13);
1336 EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
1337 inst = context->get_def_use_mgr()->GetDef(14);
1338 EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1339
1340 // Runtime arrayed SSBO and UBO
1341 inst = context->get_def_use_mgr()->GetDef(17);
1342 EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1343 inst = context->get_def_use_mgr()->GetDef(18);
1344 EXPECT_EQ(false, inst->IsVulkanStorageBuffer());
1345 inst = context->get_def_use_mgr()->GetDef(19);
1346 EXPECT_EQ(true, inst->IsVulkanStorageBuffer());
1347 }
1348
TEST_F(VulkanBufferTest,VulkanUniformBuffer)1349 TEST_F(VulkanBufferTest, VulkanUniformBuffer) {
1350 const std::string text = R"(
1351 OpCapability Shader
1352 OpCapability RuntimeDescriptorArray
1353 OpMemoryModel Logical GLSL450
1354 OpEntryPoint GLCompute %1 "main"
1355 OpExecutionMode %1 LocalSize 1 1 1
1356 OpDecorate %2 Block
1357 OpMemberDecorate %2 0 Offset 0
1358 OpDecorate %3 BufferBlock
1359 OpMemberDecorate %3 0 Offset 0
1360 %4 = OpTypeVoid
1361 %5 = OpTypeInt 32 0
1362 %2 = OpTypeStruct %5
1363 %3 = OpTypeStruct %5
1364
1365 %6 = OpTypePointer StorageBuffer %2
1366 %7 = OpTypePointer Uniform %2
1367 %8 = OpTypePointer Uniform %3
1368
1369 %9 = OpConstant %5 1
1370 %10 = OpTypeArray %2 %9
1371 %11 = OpTypeArray %3 %9
1372 %12 = OpTypePointer StorageBuffer %10
1373 %13 = OpTypePointer Uniform %10
1374 %14 = OpTypePointer Uniform %11
1375
1376 %15 = OpTypeRuntimeArray %2
1377 %16 = OpTypeRuntimeArray %3
1378 %17 = OpTypePointer StorageBuffer %15
1379 %18 = OpTypePointer Uniform %15
1380 %19 = OpTypePointer Uniform %16
1381
1382 %50 = OpTypeFunction %4
1383 %1 = OpFunction %4 None %50
1384 %51 = OpLabel
1385 OpReturn
1386 OpFunctionEnd
1387 )";
1388
1389 std::unique_ptr<IRContext> context =
1390 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1391 EXPECT_NE(context, nullptr);
1392
1393 // Standard SSBO and UBO
1394 Instruction* inst = context->get_def_use_mgr()->GetDef(6);
1395 EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1396 inst = context->get_def_use_mgr()->GetDef(7);
1397 EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
1398 inst = context->get_def_use_mgr()->GetDef(8);
1399 EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1400
1401 // Arrayed SSBO and UBO
1402 inst = context->get_def_use_mgr()->GetDef(12);
1403 EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1404 inst = context->get_def_use_mgr()->GetDef(13);
1405 EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
1406 inst = context->get_def_use_mgr()->GetDef(14);
1407 EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1408
1409 // Runtime arrayed SSBO and UBO
1410 inst = context->get_def_use_mgr()->GetDef(17);
1411 EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1412 inst = context->get_def_use_mgr()->GetDef(18);
1413 EXPECT_EQ(true, inst->IsVulkanUniformBuffer());
1414 inst = context->get_def_use_mgr()->GetDef(19);
1415 EXPECT_EQ(false, inst->IsVulkanUniformBuffer());
1416 }
1417
TEST_F(VulkanBufferTest,ImageQueries)1418 TEST_F(VulkanBufferTest, ImageQueries) {
1419 const std::string text = R"(
1420 OpCapability Shader
1421 OpCapability ImageBuffer
1422 OpCapability RuntimeDescriptorArray
1423 OpMemoryModel Logical GLSL450
1424 OpEntryPoint GLCompute %1 "main"
1425 OpExecutionMode %1 LocalSize 1 1 1
1426 %2 = OpTypeVoid
1427 %3 = OpTypeFloat 32
1428
1429 %4 = OpTypeImage %3 Buffer 0 0 0 1 Rgba32f
1430 %5 = OpTypeImage %3 Buffer 0 0 0 2 Rgba32f
1431 %6 = OpTypeImage %3 2D 0 0 0 1 Rgba32f
1432 %7 = OpTypeImage %3 2D 0 0 0 2 Rgba32f
1433
1434 %8 = OpTypePointer UniformConstant %4
1435 %9 = OpTypePointer UniformConstant %5
1436 %10 = OpTypePointer UniformConstant %6
1437 %11 = OpTypePointer UniformConstant %7
1438
1439 %12 = OpTypeInt 32 0
1440 %13 = OpConstant %12 1
1441 %14 = OpTypeArray %4 %13
1442 %15 = OpTypeArray %5 %13
1443 %16 = OpTypeArray %6 %13
1444 %17 = OpTypeArray %7 %13
1445 %18 = OpTypePointer UniformConstant %14
1446 %19 = OpTypePointer UniformConstant %15
1447 %20 = OpTypePointer UniformConstant %16
1448 %21 = OpTypePointer UniformConstant %17
1449
1450 %22 = OpTypeRuntimeArray %4
1451 %23 = OpTypeRuntimeArray %5
1452 %24 = OpTypeRuntimeArray %6
1453 %25 = OpTypeRuntimeArray %7
1454 %26 = OpTypePointer UniformConstant %22
1455 %27 = OpTypePointer UniformConstant %23
1456 %28 = OpTypePointer UniformConstant %24
1457 %29 = OpTypePointer UniformConstant %25
1458
1459 %50 = OpTypeFunction %4
1460 %1 = OpFunction %4 None %50
1461 %51 = OpLabel
1462 OpReturn
1463 OpFunctionEnd
1464 )";
1465
1466 std::unique_ptr<IRContext> context =
1467 BuildModule(SPV_ENV_UNIVERSAL_1_3, nullptr, text);
1468 EXPECT_NE(context, nullptr);
1469
1470 // Bare pointers
1471 Instruction* inst = context->get_def_use_mgr()->GetDef(8);
1472 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1473 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1474 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1475
1476 inst = context->get_def_use_mgr()->GetDef(9);
1477 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1478 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1479 EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
1480
1481 inst = context->get_def_use_mgr()->GetDef(10);
1482 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1483 EXPECT_EQ(true, inst->IsVulkanSampledImage());
1484 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1485
1486 inst = context->get_def_use_mgr()->GetDef(11);
1487 EXPECT_EQ(true, inst->IsVulkanStorageImage());
1488 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1489 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1490
1491 // Array pointers
1492 inst = context->get_def_use_mgr()->GetDef(18);
1493 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1494 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1495 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1496
1497 inst = context->get_def_use_mgr()->GetDef(19);
1498 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1499 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1500 EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
1501
1502 inst = context->get_def_use_mgr()->GetDef(20);
1503 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1504 EXPECT_EQ(true, inst->IsVulkanSampledImage());
1505 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1506
1507 inst = context->get_def_use_mgr()->GetDef(21);
1508 EXPECT_EQ(true, inst->IsVulkanStorageImage());
1509 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1510 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1511
1512 // Runtime array pointers
1513 inst = context->get_def_use_mgr()->GetDef(26);
1514 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1515 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1516 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1517
1518 inst = context->get_def_use_mgr()->GetDef(27);
1519 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1520 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1521 EXPECT_EQ(true, inst->IsVulkanStorageTexelBuffer());
1522
1523 inst = context->get_def_use_mgr()->GetDef(28);
1524 EXPECT_EQ(false, inst->IsVulkanStorageImage());
1525 EXPECT_EQ(true, inst->IsVulkanSampledImage());
1526 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1527
1528 inst = context->get_def_use_mgr()->GetDef(29);
1529 EXPECT_EQ(true, inst->IsVulkanStorageImage());
1530 EXPECT_EQ(false, inst->IsVulkanSampledImage());
1531 EXPECT_EQ(false, inst->IsVulkanStorageTexelBuffer());
1532 }
1533
1534 } // namespace
1535 } // namespace opt
1536 } // namespace spvtools
1537