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