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