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