1 // Copyright (c) 2015-2016 The Khronos Group Inc.
2 // Modifications Copyright (C) 2024 Advanced Micro Devices, Inc. All rights
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
21 #include "gmock/gmock.h"
22 #include "test/test_fixture.h"
23 #include "test/unit_spirv.h"
24 #include "test/val/val_fixtures.h"
26 // NOTE: The tests in this file are ONLY testing ID usage, there for the input
27 // SPIR-V does not follow the logical layout rules from the spec in all cases in
28 // order to makes the tests smaller. Validation of the whole module is handled
29 // in stages, ID validation is only one of these stages. All validation stages
36 using spvtest::ScopedContext
;
37 using ::testing::HasSubstr
;
38 using ::testing::ValuesIn
;
40 class ValidateIdWithMessage
: public spvtest::ValidateBase
<bool> {
42 ValidateIdWithMessage() {
43 const bool use_friendly_names
= GetParam();
44 spvValidatorOptionsSetFriendlyNames(options_
, use_friendly_names
);
47 std::string
make_message(const char* msg
);
50 std::string kOpCapabilitySetupWithoutVector16
= R
"(
53 OpCapability Addresses
58 OpCapability LiteralSampler
60 OpCapability DeviceEnqueue
63 std::string kOpCapabilitySetup
= R
"(
66 OpCapability Addresses
71 OpCapability LiteralSampler
73 OpCapability DeviceEnqueue
77 std::string kOpVariablePtrSetUp
= R
"(
78 OpCapability VariablePointers
79 OpExtension "SPV_KHR_variable_pointers
"
82 std::string kGLSL450MemoryModel
=
83 kOpCapabilitySetup
+ kOpVariablePtrSetUp
+ R
"(
84 OpMemoryModel Logical GLSL450
87 std::string kGLSL450MemoryModelWithoutVector16
=
88 kOpCapabilitySetupWithoutVector16
+ kOpVariablePtrSetUp
+ R
"(
89 OpMemoryModel Logical GLSL450
92 std::string kNoKernelGLSL450MemoryModel
= R
"(
95 OpCapability Addresses
100 OpMemoryModel Logical GLSL450
103 std::string kOpenCLMemoryModel32
= R
"(
104 OpCapability Addresses
107 %1 = OpExtInstImport "OpenCL
.std
"
108 OpMemoryModel Physical32 OpenCL
111 std::string kOpenCLMemoryModel64
= R
"(
112 OpCapability Addresses
116 %1 = OpExtInstImport "OpenCL
.std
"
117 OpMemoryModel Physical64 OpenCL
120 std::string sampledImageSetup
= R
"(
122 %typeFuncVoid = OpTypeFunction %void
123 %float = OpTypeFloat 32
124 %v4float = OpTypeVector %float 4
125 %image_type = OpTypeImage %float 2D 0 0 0 1 Unknown
126 %_ptr_UniformConstant_img = OpTypePointer UniformConstant %image_type
127 %tex = OpVariable %_ptr_UniformConstant_img UniformConstant
128 %sampler_type = OpTypeSampler
129 %_ptr_UniformConstant_sam = OpTypePointer UniformConstant %sampler_type
130 %s = OpVariable %_ptr_UniformConstant_sam UniformConstant
131 %sampled_image_type = OpTypeSampledImage %image_type
132 %v2float = OpTypeVector %float 2
133 %float_1 = OpConstant %float 1
134 %float_2 = OpConstant %float 2
135 %const_vec_1_1 = OpConstantComposite %v2float %float_1 %float_1
136 %const_vec_2_2 = OpConstantComposite %v2float %float_2 %float_2
137 %bool_type = OpTypeBool
138 %spec_true = OpSpecConstantTrue %bool_type
139 %main = OpFunction %void None %typeFuncVoid
141 %image_inst = OpLoad %image_type %tex
142 %sampler_inst = OpLoad %sampler_type %s
145 std::string BranchConditionalSetup
= R
"(
147 %1 = OpExtInstImport "GLSL
.std
.450"
148 OpMemoryModel Logical GLSL450
149 OpEntryPoint Fragment %main "main
"
150 OpExecutionMode %main OriginUpperLeft
156 %uint = OpTypeInt 32 0
157 %int = OpTypeInt 32 1
158 %float = OpTypeFloat 32
159 %v4float = OpTypeVector %float 4
162 %true = OpConstantTrue %bool
163 %i0 = OpConstant %int 0
164 %i1 = OpConstant %int 1
165 %f0 = OpConstant %float 0
166 %f1 = OpConstant %float 1
169 ; main function header
171 %voidfunc = OpTypeFunction %void
172 %main = OpFunction %void None %voidfunc
176 std::string BranchConditionalTail
= R
"(
190 // Transform an expected validation message to either use friendly names (as
191 // provided in the message) or replace the friendly names by the corresponding
192 // id. The same flag used to configure the validator to output friendly names
193 // or not is used here.
194 std::string
ValidateIdWithMessage::make_message(const char* msg
) {
195 const bool use_friendly_names
= GetParam();
196 if (use_friendly_names
) {
200 std::string
message(msg
);
201 std::ostringstream result
;
204 while (next
< message
.size()) {
205 // Parse 'num[%name]'
206 size_t open_quote
= message
.find('\'', next
);
208 if (open_quote
== std::string::npos
) {
212 // Copy up to the first quote
213 result
.write(msg
+ next
, open_quote
- next
);
214 // Handle apostrophes
215 if (!isdigit(message
[open_quote
+ 1])) {
217 next
= open_quote
+ 1;
221 size_t open_bracket
= message
.find('[', open_quote
+ 1);
222 assert(open_bracket
!= std::string::npos
);
224 size_t close_bracket
= message
.find(']', open_bracket
+ 1);
225 assert(close_bracket
!= std::string::npos
);
227 size_t close_quote
= close_bracket
+ 1;
228 assert(close_quote
< message
.size() && message
[close_quote
] == '\'');
230 // Change to 'num[%num]' because friendly names are not being used.
231 result
.write(msg
+ open_quote
, open_bracket
- open_quote
+ 1);
233 result
.write(msg
+ open_quote
+ 1, open_bracket
- open_quote
- 1);
236 // Continue to the next id, or end of string.
237 next
= close_quote
+ 1;
245 TEST_P(ValidateIdWithMessage
, OpName
) {
246 std::string spirv
= kGLSL450MemoryModel
+ R
"(
249 %2 = OpTypePointer UniformConstant %1
250 %3 = OpVariable %2 UniformConstant)";
251 CompileSuccessfully(spirv
.c_str());
252 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
255 TEST_P(ValidateIdWithMessage
, OpMemberNameGood
) {
256 std::string spirv
= kGLSL450MemoryModel
+ R
"(
257 OpMemberName %2 0 "foo
"
259 %2 = OpTypeStruct %1)";
260 CompileSuccessfully(spirv
.c_str());
261 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
263 TEST_P(ValidateIdWithMessage
, OpMemberNameTypeBad
) {
264 std::string spirv
= kGLSL450MemoryModel
+ R
"(
265 OpMemberName %1 0 "foo
"
266 %1 = OpTypeInt 32 0)";
267 CompileSuccessfully(spirv
.c_str());
268 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
269 EXPECT_THAT(getDiagnosticString(),
270 HasSubstr(make_message(
271 "OpMemberName Type <id> '1[%uint]' is not a struct type.")));
273 TEST_P(ValidateIdWithMessage
, OpMemberNameMemberBad
) {
274 std::string spirv
= kGLSL450MemoryModel
+ R
"(
275 OpMemberName %1 1 "foo
"
277 %1 = OpTypeStruct %2)";
278 CompileSuccessfully(spirv
.c_str());
279 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
280 EXPECT_THAT(getDiagnosticString(),
281 HasSubstr(make_message(
282 "OpMemberName Member <id> '1[%_struct_1]' index is larger "
283 "than Type <id> '1[%_struct_1]'s member count.")));
286 TEST_P(ValidateIdWithMessage
, OpLineGood
) {
287 std::string spirv
= kGLSL450MemoryModel
+ R
"(
288 %1 = OpString "/path
/to
/source
.file
"
291 %3 = OpTypePointer Input %2
292 %4 = OpVariable %3 Input)";
293 CompileSuccessfully(spirv
.c_str());
294 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
297 TEST_P(ValidateIdWithMessage
, OpLineFileBad
) {
298 std::string spirv
= kGLSL450MemoryModel
+ R
"(
302 CompileSuccessfully(spirv
.c_str());
303 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
304 EXPECT_THAT(getDiagnosticString(),
305 HasSubstr(make_message(
306 "OpLine Target <id> '1[%uint]' is not an OpString.")));
309 TEST_P(ValidateIdWithMessage
, OpDecorateGood
) {
310 std::string spirv
= kGLSL450MemoryModel
+ R
"(
311 OpDecorate %2 GLSLShared
313 %2 = OpTypeStruct %1 %1)";
314 CompileSuccessfully(spirv
.c_str());
315 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
317 TEST_P(ValidateIdWithMessage
, OpDecorateBad
) {
318 std::string spirv
= kGLSL450MemoryModel
+ R
"(
319 OpDecorate %1 GLSLShared)";
320 CompileSuccessfully(spirv
.c_str());
321 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
323 getDiagnosticString(),
324 HasSubstr(make_message("forward referenced IDs have not been defined")));
327 TEST_P(ValidateIdWithMessage
, OpMemberDecorateGood
) {
328 std::string spirv
= kGLSL450MemoryModel
+ R
"(
329 OpMemberDecorate %2 0 RelaxedPrecision
331 %2 = OpTypeStruct %1 %1)";
332 CompileSuccessfully(spirv
.c_str());
333 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
335 TEST_P(ValidateIdWithMessage
, OpMemberDecorateBad
) {
336 std::string spirv
= kGLSL450MemoryModel
+ R
"(
337 OpMemberDecorate %1 0 RelaxedPrecision
338 %1 = OpTypeInt 32 0)";
339 CompileSuccessfully(spirv
.c_str());
340 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
341 EXPECT_THAT(getDiagnosticString(),
342 HasSubstr(make_message(
343 "OpMemberDecorate Structure type <id> '1[%uint]' is "
344 "not a struct type.")));
346 TEST_P(ValidateIdWithMessage
, OpMemberDecorateMemberBad
) {
347 std::string spirv
= kGLSL450MemoryModel
+ R
"(
348 OpMemberDecorate %1 3 RelaxedPrecision
349 %int = OpTypeInt 32 0
350 %1 = OpTypeStruct %int %int)";
351 CompileSuccessfully(spirv
.c_str());
352 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
353 EXPECT_THAT(getDiagnosticString(),
354 HasSubstr(make_message(
355 "Index 3 provided in OpMemberDecorate for struct <id> "
356 "'1[%_struct_1]' is out of bounds. The structure has 2 "
357 "members. Largest valid index is 1.")));
360 TEST_P(ValidateIdWithMessage
, OpGroupDecorateGood
) {
361 std::string spirv
= kGLSL450MemoryModel
+ R
"(
362 %1 = OpDecorationGroup
363 OpDecorate %1 RelaxedPrecision
364 OpDecorate %1 GLSLShared
365 OpGroupDecorate %1 %3 %4
367 %3 = OpConstant %2 42
368 %4 = OpConstant %2 23)";
369 CompileSuccessfully(spirv
.c_str());
370 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
372 TEST_P(ValidateIdWithMessage
, OpDecorationGroupBad
) {
373 std::string spirv
= kGLSL450MemoryModel
+ R
"(
374 %1 = OpDecorationGroup
375 OpDecorate %1 RelaxedPrecision
376 OpDecorate %1 GLSLShared
377 OpMemberDecorate %1 0 Constant
379 CompileSuccessfully(spirv
.c_str());
380 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
381 EXPECT_THAT(getDiagnosticString(),
382 HasSubstr(make_message(
383 "Result id of OpDecorationGroup can only "
384 "be targeted by OpName, OpGroupDecorate, "
385 "OpDecorate, OpDecorateId, and OpGroupMemberDecorate")));
387 TEST_P(ValidateIdWithMessage
, OpGroupDecorateDecorationGroupBad
) {
388 std::string spirv
= R
"(
391 %1 = OpExtInstImport "GLSL
.std
.450"
392 OpMemoryModel Logical GLSL450
393 OpGroupDecorate %1 %2 %3
395 %3 = OpConstant %2 42)";
396 CompileSuccessfully(spirv
.c_str());
397 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
398 EXPECT_THAT(getDiagnosticString(),
399 HasSubstr(make_message(
400 "OpGroupDecorate Decoration group <id> '1[%1]' is not "
401 "a decoration group.")));
403 TEST_P(ValidateIdWithMessage
, OpGroupDecorateTargetBad
) {
404 std::string spirv
= kGLSL450MemoryModel
+ R
"(
405 %1 = OpDecorationGroup
406 OpDecorate %1 RelaxedPrecision
407 OpDecorate %1 GLSLShared
408 OpGroupDecorate %1 %3
409 %2 = OpTypeInt 32 0)";
410 CompileSuccessfully(spirv
.c_str());
411 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
413 getDiagnosticString(),
414 HasSubstr(make_message("forward referenced IDs have not been defined")));
416 TEST_P(ValidateIdWithMessage
, OpGroupMemberDecorateDecorationGroupBad
) {
417 std::string spirv
= R
"(
420 %1 = OpExtInstImport "GLSL
.std
.450"
421 OpMemoryModel Logical GLSL450
422 OpGroupMemberDecorate %1 %2 0
423 %2 = OpTypeInt 32 0)";
424 CompileSuccessfully(spirv
.c_str());
425 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
426 EXPECT_THAT(getDiagnosticString(),
427 HasSubstr(make_message(
428 "OpGroupMemberDecorate Decoration group <id> '1[%1]' "
429 "is not a decoration group.")));
431 TEST_P(ValidateIdWithMessage
, OpGroupMemberDecorateIdNotStructBad
) {
432 std::string spirv
= kGLSL450MemoryModel
+ R
"(
433 %1 = OpDecorationGroup
434 OpGroupMemberDecorate %1 %2 0
435 %2 = OpTypeInt 32 0)";
436 CompileSuccessfully(spirv
.c_str());
437 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
438 EXPECT_THAT(getDiagnosticString(),
439 HasSubstr(make_message(
440 "OpGroupMemberDecorate Structure type <id> '2[%uint]' "
441 "is not a struct type.")));
443 TEST_P(ValidateIdWithMessage
, OpGroupMemberDecorateIndexOutOfBoundBad
) {
444 std::string spirv
= kGLSL450MemoryModel
+ R
"(
445 OpDecorate %1 Offset 0
446 %1 = OpDecorationGroup
447 OpGroupMemberDecorate %1 %struct 3
448 %float = OpTypeFloat 32
449 %struct = OpTypeStruct %float %float %float
451 CompileSuccessfully(spirv
.c_str());
452 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
453 EXPECT_THAT(getDiagnosticString(),
454 HasSubstr(make_message(
455 "Index 3 provided in OpGroupMemberDecorate for struct "
456 "<id> '2[%_struct_2]' is out of bounds. The structure "
457 "has 3 members. Largest valid index is 2.")));
462 TEST_P(ValidateIdWithMessage
, OpEntryPointGood
) {
463 std::string spirv
= kGLSL450MemoryModel
+ R
"(
464 OpEntryPoint GLCompute %3 ""
466 %2 = OpTypeFunction %1
467 %3 = OpFunction %1 None %2
472 CompileSuccessfully(spirv
.c_str());
473 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
475 TEST_P(ValidateIdWithMessage
, OpEntryPointFunctionBad
) {
476 std::string spirv
= kGLSL450MemoryModel
+ R
"(
477 OpEntryPoint GLCompute %1 ""
479 CompileSuccessfully(spirv
.c_str());
480 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
481 EXPECT_THAT(getDiagnosticString(),
482 HasSubstr(make_message(
483 "OpEntryPoint Entry Point <id> '1[%void]' is not a "
486 TEST_P(ValidateIdWithMessage
, OpEntryPointParameterCountBad
) {
487 std::string spirv
= kGLSL450MemoryModel
+ R
"(
488 OpEntryPoint GLCompute %1 ""
490 %3 = OpTypeFunction %2 %2
491 %1 = OpFunction %2 None %3
495 CompileSuccessfully(spirv
.c_str());
496 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
498 getDiagnosticString(),
499 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
500 "parameter count is not zero")));
502 TEST_P(ValidateIdWithMessage
, OpEntryPointReturnTypeBad
) {
503 std::string spirv
= kGLSL450MemoryModel
+ R
"(
504 OpEntryPoint GLCompute %1 ""
506 %ret = OpConstant %2 0
507 %3 = OpTypeFunction %2
508 %1 = OpFunction %2 None %3
512 CompileSuccessfully(spirv
.c_str());
513 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
515 getDiagnosticString(),
516 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
517 "return type is not void.")));
519 TEST_P(ValidateIdWithMessage
, OpEntryPointParameterCountBadInVulkan
) {
520 std::string spirv
= R
"(
522 OpMemoryModel Logical GLSL450
523 OpEntryPoint GLCompute %1 ""
525 %3 = OpTypeFunction %2 %2
526 %1 = OpFunction %2 None %3
530 CompileSuccessfully(spirv
.c_str(), SPV_ENV_VULKAN_1_0
);
531 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_VULKAN_1_0
));
532 EXPECT_THAT(getDiagnosticString(),
533 AnyVUID("VUID-StandaloneSpirv-None-04633"));
535 getDiagnosticString(),
536 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
537 "parameter count is not zero")));
539 TEST_P(ValidateIdWithMessage
, OpEntryPointReturnTypeBadInVulkan
) {
540 std::string spirv
= R
"(
542 OpMemoryModel Logical GLSL450
543 OpEntryPoint GLCompute %1 ""
545 %ret = OpConstant %2 0
546 %3 = OpTypeFunction %2
547 %1 = OpFunction %2 None %3
551 CompileSuccessfully(spirv
.c_str(), SPV_ENV_VULKAN_1_0
);
552 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_VULKAN_1_0
));
553 EXPECT_THAT(getDiagnosticString(),
554 AnyVUID("VUID-StandaloneSpirv-None-04633"));
556 getDiagnosticString(),
557 HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
558 "return type is not void.")));
561 TEST_P(ValidateIdWithMessage
, OpEntryPointInterfaceIsNotVariableTypeBad
) {
562 std::string spirv
= R
"(
564 OpCapability Geometry
565 OpMemoryModel Logical GLSL450
566 OpEntryPoint Geometry %main "main
" %ptr_builtin_1
567 OpExecutionMode %main InputPoints
568 OpExecutionMode %main OutputPoints
569 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
570 %int = OpTypeInt 32 1
572 %func = OpTypeFunction %void
573 %struct_1 = OpTypeStruct %int
574 %ptr_builtin_1 = OpTypePointer Input %struct_1
575 %main = OpFunction %void None %func
580 CompileSuccessfully(spirv
);
581 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
582 EXPECT_THAT(getDiagnosticString(),
583 HasSubstr("Interfaces passed to OpEntryPoint must be variables. "
584 "Found OpTypePointer."));
587 TEST_P(ValidateIdWithMessage
, OpEntryPointInterfaceStorageClassBad
) {
588 std::string spirv
= R
"(
590 OpCapability Geometry
591 OpMemoryModel Logical GLSL450
592 OpEntryPoint Geometry %main "main
" %in_1
593 OpExecutionMode %main InputPoints
594 OpExecutionMode %main OutputPoints
595 OpMemberDecorate %struct_1 0 BuiltIn InvocationId
596 %int = OpTypeInt 32 1
598 %func = OpTypeFunction %void
599 %struct_1 = OpTypeStruct %int
600 %ptr_builtin_1 = OpTypePointer Uniform %struct_1
601 %in_1 = OpVariable %ptr_builtin_1 Uniform
602 %main = OpFunction %void None %func
607 CompileSuccessfully(spirv
);
608 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
609 EXPECT_THAT(getDiagnosticString(),
610 HasSubstr(make_message(
611 "OpEntryPoint interfaces must be OpVariables with "
612 "Storage Class of Input(1) or Output(3). Found Storage "
613 "Class 2 for Entry Point id 1.")));
616 TEST_P(ValidateIdWithMessage
, OpExecutionModeGood
) {
617 std::string spirv
= kGLSL450MemoryModel
+ R
"(
618 OpEntryPoint GLCompute %3 ""
619 OpExecutionMode %3 LocalSize 1 1 1
621 %2 = OpTypeFunction %1
622 %3 = OpFunction %1 None %2
626 CompileSuccessfully(spirv
.c_str());
627 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
630 TEST_P(ValidateIdWithMessage
, OpExecutionModeEntryPointMissing
) {
631 std::string spirv
= kGLSL450MemoryModel
+ R
"(
632 OpExecutionMode %3 LocalSize 1 1 1
634 %2 = OpTypeFunction %1
635 %3 = OpFunction %1 None %2
639 CompileSuccessfully(spirv
.c_str());
640 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
641 EXPECT_THAT(getDiagnosticString(),
642 HasSubstr(make_message(
643 "OpExecutionMode Entry Point <id> '1[%1]' is not the "
644 "Entry Point operand of an OpEntryPoint.")));
647 TEST_P(ValidateIdWithMessage
, OpExecutionModeEntryPointBad
) {
648 std::string spirv
= kGLSL450MemoryModel
+ R
"(
649 OpEntryPoint GLCompute %3 "" %a
650 OpExecutionMode %a LocalSize 1 1 1
652 %ptr = OpTypePointer Input %void
653 %a = OpVariable %ptr Input
654 %2 = OpTypeFunction %void
655 %3 = OpFunction %void None %2
659 CompileSuccessfully(spirv
.c_str());
660 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
661 EXPECT_THAT(getDiagnosticString(),
662 HasSubstr(make_message(
663 "OpExecutionMode Entry Point <id> '2[%2]' is not the "
664 "Entry Point operand of an OpEntryPoint.")));
667 TEST_P(ValidateIdWithMessage
, OpTypeVectorFloat
) {
668 std::string spirv
= kGLSL450MemoryModel
+ R
"(
670 %2 = OpTypeVector %1 4)";
671 CompileSuccessfully(spirv
.c_str());
672 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
675 TEST_P(ValidateIdWithMessage
, OpTypeVectorInt
) {
676 std::string spirv
= kGLSL450MemoryModel
+ R
"(
678 %2 = OpTypeVector %1 4)";
679 CompileSuccessfully(spirv
.c_str());
680 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
683 TEST_P(ValidateIdWithMessage
, OpTypeVectorUInt
) {
684 std::string spirv
= kGLSL450MemoryModel
+ R
"(
686 %2 = OpTypeVector %1 4)";
687 CompileSuccessfully(spirv
.c_str());
688 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
691 TEST_P(ValidateIdWithMessage
, OpTypeVectorBool
) {
692 std::string spirv
= kGLSL450MemoryModel
+ R
"(
694 %2 = OpTypeVector %1 4)";
695 CompileSuccessfully(spirv
.c_str());
696 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
699 TEST_P(ValidateIdWithMessage
, OpTypeVectorComponentTypeBad
) {
700 std::string spirv
= kGLSL450MemoryModel
+ R
"(
702 %2 = OpTypePointer UniformConstant %1
703 %3 = OpTypeVector %2 4)";
704 CompileSuccessfully(spirv
.c_str());
705 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
706 EXPECT_THAT(getDiagnosticString(),
707 HasSubstr(make_message(
708 "OpTypeVector Component Type <id> "
709 "'2[%_ptr_UniformConstant_float]' is not a scalar type.")));
712 TEST_P(ValidateIdWithMessage
, OpTypeVectorColumnCountLessThanTwoBad
) {
713 std::string spirv
= kGLSL450MemoryModel
+ R
"(
715 %2 = OpTypeVector %1 1)";
716 CompileSuccessfully(spirv
.c_str());
717 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
719 getDiagnosticString(),
720 HasSubstr(make_message(
721 "Illegal number of components (1) for TypeVector\n %v1float = "
722 "OpTypeVector %float 1\n")));
725 TEST_P(ValidateIdWithMessage
, OpTypeVectorColumnCountGreaterThanFourBad
) {
726 std::string spirv
= kGLSL450MemoryModel
+ R
"(
728 %2 = OpTypeVector %1 5)";
729 CompileSuccessfully(spirv
.c_str());
730 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
732 getDiagnosticString(),
733 HasSubstr(make_message(
734 "Illegal number of components (5) for TypeVector\n %v5float = "
735 "OpTypeVector %float 5\n")));
738 TEST_P(ValidateIdWithMessage
, OpTypeVectorColumnCountEightWithoutVector16Bad
) {
739 std::string spirv
= kGLSL450MemoryModelWithoutVector16
+ R
"(
741 %2 = OpTypeVector %1 8)";
743 CompileSuccessfully(spirv
.c_str());
744 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
745 EXPECT_THAT(getDiagnosticString(),
746 HasSubstr(make_message(
747 "Having 8 components for TypeVector requires the Vector16 "
748 "capability\n %v8float = OpTypeVector %float 8\n")));
751 TEST_P(ValidateIdWithMessage
,
752 OpTypeVectorColumnCountSixteenWithoutVector16Bad
) {
753 std::string spirv
= kGLSL450MemoryModelWithoutVector16
+ R
"(
755 %2 = OpTypeVector %1 16)";
757 CompileSuccessfully(spirv
.c_str());
758 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
759 EXPECT_THAT(getDiagnosticString(),
760 HasSubstr(make_message(
761 "Having 16 components for TypeVector requires the Vector16 "
762 "capability\n %v16float = OpTypeVector %float 16\n")));
765 TEST_P(ValidateIdWithMessage
, OpTypeVectorColumnCountOfEightWithVector16Good
) {
766 std::string spirv
= kGLSL450MemoryModel
+ R
"(
768 %2 = OpTypeVector %1 8)";
769 CompileSuccessfully(spirv
.c_str());
770 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
773 TEST_P(ValidateIdWithMessage
,
774 OpTypeVectorColumnCountOfSixteenWithVector16Good
) {
775 std::string spirv
= kGLSL450MemoryModel
+ R
"(
777 %2 = OpTypeVector %1 16)";
778 CompileSuccessfully(spirv
.c_str());
779 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
782 TEST_P(ValidateIdWithMessage
, OpTypeMatrixGood
) {
783 std::string spirv
= kGLSL450MemoryModel
+ R
"(
785 %2 = OpTypeVector %1 2
786 %3 = OpTypeMatrix %2 3)";
787 CompileSuccessfully(spirv
.c_str());
788 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
791 TEST_P(ValidateIdWithMessage
, OpTypeMatrixColumnTypeNonVectorBad
) {
792 std::string spirv
= kGLSL450MemoryModel
+ R
"(
794 %2 = OpTypeMatrix %1 3)";
795 CompileSuccessfully(spirv
.c_str());
796 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
797 EXPECT_THAT(getDiagnosticString(),
798 HasSubstr(make_message(
799 "olumns in a matrix must be of type vector.\n %mat3float = "
800 "OpTypeMatrix %float 3\n")));
803 TEST_P(ValidateIdWithMessage
, OpTypeMatrixVectorTypeNonFloatBad
) {
804 std::string spirv
= kGLSL450MemoryModel
+ R
"(
806 %2 = OpTypeVector %1 2
807 %3 = OpTypeMatrix %2 2)";
808 CompileSuccessfully(spirv
.c_str());
809 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
810 EXPECT_THAT(getDiagnosticString(),
811 HasSubstr(make_message(
812 "Matrix types can only be parameterized with floating-point "
813 "types.\n %mat2v2ushort = OpTypeMatrix %v2ushort 2\n")));
816 TEST_P(ValidateIdWithMessage
, OpTypeMatrixColumnCountLessThanTwoBad
) {
817 std::string spirv
= kGLSL450MemoryModel
+ R
"(
819 %2 = OpTypeVector %1 2
820 %3 = OpTypeMatrix %2 1)";
821 CompileSuccessfully(spirv
.c_str());
822 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
824 getDiagnosticString(),
825 HasSubstr(make_message(
826 "Matrix types can only be parameterized as having only 2, 3, "
827 "or 4 columns.\n %mat1v2float = OpTypeMatrix %v2float 1\n")));
830 TEST_P(ValidateIdWithMessage
, OpTypeMatrixColumnCountGreaterThanFourBad
) {
831 std::string spirv
= kGLSL450MemoryModel
+ R
"(
833 %2 = OpTypeVector %1 2
834 %3 = OpTypeMatrix %2 8)";
835 CompileSuccessfully(spirv
.c_str());
836 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
838 getDiagnosticString(),
839 HasSubstr(make_message(
840 "Matrix types can only be parameterized as having only 2, 3, "
841 "or 4 columns.\n %mat8v2float = OpTypeMatrix %v2float 8\n")));
844 TEST_P(ValidateIdWithMessage
, OpTypeSamplerGood
) {
845 // In Rev31, OpTypeSampler takes no arguments.
846 std::string spirv
= kGLSL450MemoryModel
+ R
"(
847 %s = OpTypeSampler)";
848 CompileSuccessfully(spirv
.c_str());
849 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
852 TEST_P(ValidateIdWithMessage
, OpTypeArrayGood
) {
853 std::string spirv
= kGLSL450MemoryModel
+ R
"(
856 %3 = OpTypeArray %1 %2)";
857 CompileSuccessfully(spirv
.c_str());
858 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
861 TEST_P(ValidateIdWithMessage
, OpTypeArrayElementTypeBad
) {
862 std::string spirv
= kGLSL450MemoryModel
+ R
"(
865 %3 = OpTypeArray %2 %2)";
866 CompileSuccessfully(spirv
.c_str());
867 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
868 EXPECT_THAT(getDiagnosticString(),
869 HasSubstr(make_message(
870 "OpTypeArray Element Type <id> '2[%uint_1]' is not a "
874 // Signed or unsigned.
875 enum Signed
{ kSigned
, kUnsigned
};
877 // Creates an assembly module declaring OpTypeArray with the given length.
878 std::string
MakeArrayLength(const std::string
& len
, Signed isSigned
, int width
,
879 int max_int_width
= 64,
880 bool use_vulkan_memory_model
= false) {
881 std::ostringstream ss
;
885 if (use_vulkan_memory_model
) {
886 ss
<< " OpCapability VulkanMemoryModel\n";
889 ss
<< " OpCapability Int16\n";
891 if (max_int_width
> 32) {
892 ss
<< "\n OpCapability Int64\n";
894 if (use_vulkan_memory_model
) {
895 ss
<< " OpExtension \"SPV_KHR_vulkan_memory_model\"\n";
896 ss
<< "OpMemoryModel Logical Vulkan\n";
898 ss
<< "OpMemoryModel Logical GLSL450\n";
900 ss
<< "OpEntryPoint GLCompute %main \"main\"\n";
901 ss
<< "OpExecutionMode %main LocalSize 1 1 1\n";
902 ss
<< " %t = OpTypeInt " << width
<< (isSigned
== kSigned
? " 1" : " 0");
903 ss
<< " %l = OpConstant %t " << len
;
904 ss
<< " %a = OpTypeArray %t %l";
905 ss
<< " %void = OpTypeVoid \n"
906 " %voidfn = OpTypeFunction %void \n"
907 " %main = OpFunction %void None %voidfn \n"
908 " %entry = OpLabel\n"
914 // Tests OpTypeArray. Parameter is the width (in bits) of the array-length's
916 class OpTypeArrayLengthTest
917 : public spvtest::TextToBinaryTestBase
<::testing::TestWithParam
<int>> {
919 OpTypeArrayLengthTest()
920 : env_(SPV_ENV_UNIVERSAL_1_0
),
921 position_(spv_position_t
{0, 0, 0}),
922 diagnostic_(spvDiagnosticCreate(&position_
, "")) {}
924 ~OpTypeArrayLengthTest() override
{ spvDiagnosticDestroy(diagnostic_
); }
926 // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
927 spv_result_t
Val(const SpirvVector
& v
, const std::string
& expected_err
= "") {
928 spv_const_binary_t cbinary
{v
.data(), v
.size()};
929 spvDiagnosticDestroy(diagnostic_
);
930 diagnostic_
= nullptr;
932 spvValidate(ScopedContext(env_
).context
, &cbinary
, &diagnostic_
);
933 if (status
!= SPV_SUCCESS
) {
934 spvDiagnosticPrint(diagnostic_
);
935 EXPECT_THAT(std::string(diagnostic_
->error
),
936 testing::ContainsRegex(expected_err
));
945 spv_position_t position_
; // For creating diagnostic_.
946 spv_diagnostic diagnostic_
;
949 TEST_P(OpTypeArrayLengthTest
, LengthPositiveSmall
) {
950 const int width
= GetParam();
951 EXPECT_EQ(SPV_SUCCESS
,
952 Val(CompileSuccessfully(MakeArrayLength("1", kSigned
, width
))));
953 EXPECT_EQ(SPV_SUCCESS
,
954 Val(CompileSuccessfully(MakeArrayLength("1", kUnsigned
, width
))));
955 EXPECT_EQ(SPV_SUCCESS
,
956 Val(CompileSuccessfully(MakeArrayLength("2", kSigned
, width
))));
957 EXPECT_EQ(SPV_SUCCESS
,
958 Val(CompileSuccessfully(MakeArrayLength("2", kUnsigned
, width
))));
959 EXPECT_EQ(SPV_SUCCESS
,
960 Val(CompileSuccessfully(MakeArrayLength("55", kSigned
, width
))));
961 EXPECT_EQ(SPV_SUCCESS
,
962 Val(CompileSuccessfully(MakeArrayLength("55", kUnsigned
, width
))));
963 const std::string
fpad(width
/ 4 - 1, 'F');
966 Val(CompileSuccessfully(MakeArrayLength("0x7" + fpad
, kSigned
, width
))))
967 << MakeArrayLength("0x7" + fpad
, kSigned
, width
);
970 TEST_P(OpTypeArrayLengthTest
, LengthZero
) {
971 const int width
= GetParam();
972 EXPECT_EQ(SPV_ERROR_INVALID_ID
,
973 Val(CompileSuccessfully(MakeArrayLength("0", kSigned
, width
)),
974 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
976 EXPECT_EQ(SPV_ERROR_INVALID_ID
,
977 Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned
, width
)),
978 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
982 TEST_P(OpTypeArrayLengthTest
, LengthNegative
) {
983 const int width
= GetParam();
984 EXPECT_EQ(SPV_ERROR_INVALID_ID
,
985 Val(CompileSuccessfully(MakeArrayLength("-1", kSigned
, width
)),
986 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
988 EXPECT_EQ(SPV_ERROR_INVALID_ID
,
989 Val(CompileSuccessfully(MakeArrayLength("-2", kSigned
, width
)),
990 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
992 EXPECT_EQ(SPV_ERROR_INVALID_ID
,
993 Val(CompileSuccessfully(MakeArrayLength("-123", kSigned
, width
)),
994 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
996 const std::string neg_max
= "0x8" + std::string(width
/ 4 - 1, '0');
997 EXPECT_EQ(SPV_ERROR_INVALID_ID
,
998 Val(CompileSuccessfully(MakeArrayLength(neg_max
, kSigned
, width
)),
999 "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
1003 // Returns the string form of an integer of the form 0x80....0 of the
1005 std::string
big_num_ending_0(int bit_width
) {
1006 return "0x8" + std::string(bit_width
/ 4 - 1, '0');
1009 // Returns the string form of an integer of the form 0x80..001 of the
1011 std::string
big_num_ending_1(int bit_width
) {
1012 return "0x8" + std::string(bit_width
/ 4 - 2, '0') + "1";
1015 TEST_P(OpTypeArrayLengthTest
, LengthPositiveHugeEnding0InVulkan
) {
1016 env_
= SPV_ENV_VULKAN_1_0
;
1017 const int width
= GetParam();
1018 for (int max_int_width
: {32, 64}) {
1019 if (width
> max_int_width
) {
1020 // Not valid to even make the OpConstant in this case.
1023 const auto module
= CompileSuccessfully(MakeArrayLength(
1024 big_num_ending_0(width
), kUnsigned
, width
, max_int_width
));
1025 EXPECT_EQ(SPV_SUCCESS
, Val(module
));
1029 TEST_P(OpTypeArrayLengthTest
, LengthPositiveHugeEnding1InVulkan
) {
1030 env_
= SPV_ENV_VULKAN_1_0
;
1031 const int width
= GetParam();
1032 for (int max_int_width
: {32, 64}) {
1033 if (width
> max_int_width
) {
1034 // Not valid to even make the OpConstant in this case.
1037 const auto module
= CompileSuccessfully(MakeArrayLength(
1038 big_num_ending_1(width
), kUnsigned
, width
, max_int_width
));
1039 EXPECT_EQ(SPV_SUCCESS
, Val(module
));
1043 // The only valid widths for integers are 8, 16, 32, and 64.
1044 // Since the Int8 capability requires the Kernel capability, and the Kernel
1045 // capability prohibits usage of signed integers, we can skip 8-bit integers
1046 // here since the purpose of these tests is to check the validity of
1047 // OpTypeArray, not OpTypeInt.
1048 INSTANTIATE_TEST_SUITE_P(Widths
, OpTypeArrayLengthTest
,
1049 ValuesIn(std::vector
<int>{16, 32, 64}));
1051 TEST_P(ValidateIdWithMessage
, OpTypeArrayLengthNull
) {
1052 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1053 %i32 = OpTypeInt 32 0
1054 %len = OpConstantNull %i32
1055 %ary = OpTypeArray %i32 %len)";
1056 CompileSuccessfully(spirv
.c_str());
1057 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1058 EXPECT_THAT(getDiagnosticString(),
1059 HasSubstr(make_message("OpTypeArray Length <id> '2[%2]' default "
1060 "value must be at least 1: found 0")));
1063 TEST_P(ValidateIdWithMessage
, OpTypeArrayLengthSpecConst
) {
1064 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1065 %i32 = OpTypeInt 32 0
1066 %len = OpSpecConstant %i32 2
1067 %ary = OpTypeArray %i32 %len)";
1068 CompileSuccessfully(spirv
.c_str());
1069 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1072 TEST_P(ValidateIdWithMessage
, OpTypeArrayLengthSpecConstOp
) {
1073 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1074 %i32 = OpTypeInt 32 0
1075 %c1 = OpConstant %i32 1
1076 %c2 = OpConstant %i32 2
1077 %len = OpSpecConstantOp %i32 IAdd %c1 %c2
1078 %ary = OpTypeArray %i32 %len)";
1079 CompileSuccessfully(spirv
.c_str());
1080 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1083 TEST_P(ValidateIdWithMessage
, OpTypeRuntimeArrayGood
) {
1084 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1086 %2 = OpTypeRuntimeArray %1)";
1087 CompileSuccessfully(spirv
.c_str());
1088 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1090 TEST_P(ValidateIdWithMessage
, OpTypeRuntimeArrayBad
) {
1091 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1093 %2 = OpConstant %1 0
1094 %3 = OpTypeRuntimeArray %2)";
1095 CompileSuccessfully(spirv
.c_str());
1096 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1097 EXPECT_THAT(getDiagnosticString(),
1098 HasSubstr(make_message(
1099 "OpTypeRuntimeArray Element Type <id> '2[%uint_0]' is not a "
1102 // TODO: Object of this type can only be created with OpVariable using the
1103 // Uniform Storage Class
1105 TEST_P(ValidateIdWithMessage
, OpTypeStructGood
) {
1106 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1109 %3 = OpTypePointer Input %1
1110 %4 = OpTypeStruct %1 %2 %3)";
1111 CompileSuccessfully(spirv
.c_str());
1112 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1114 TEST_P(ValidateIdWithMessage
, OpTypeStructMemberTypeBad
) {
1115 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1118 %3 = OpConstant %2 0.0
1119 %4 = OpTypeStruct %1 %2 %3)";
1120 CompileSuccessfully(spirv
.c_str());
1121 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1122 EXPECT_THAT(getDiagnosticString(),
1123 HasSubstr(make_message(
1124 "OpTypeStruct Member Type <id> '3[%double_0]' is not "
1128 TEST_P(ValidateIdWithMessage
, OpTypeStructOpaqueTypeBad
) {
1129 std::string spirv
= R
"(
1131 OpMemoryModel Logical GLSL450
1132 OpEntryPoint Vertex %main "main
"
1134 %2 = OpTypeStruct %1
1136 %3 = OpTypeFunction %void
1137 %main = OpFunction %void None %3
1142 CompileSuccessfully(spirv
.c_str(), SPV_ENV_VULKAN_1_0
);
1143 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_VULKAN_1_0
));
1144 EXPECT_THAT(getDiagnosticString(),
1145 AnyVUID("VUID-StandaloneSpirv-None-04667"));
1147 getDiagnosticString(),
1148 HasSubstr(make_message("OpTypeStruct must not contain an opaque type")));
1151 TEST_P(ValidateIdWithMessage
, OpTypePointerGood
) {
1152 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1154 %2 = OpTypePointer Input %1)";
1155 CompileSuccessfully(spirv
.c_str());
1156 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1158 TEST_P(ValidateIdWithMessage
, OpTypePointerBad
) {
1159 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1161 %2 = OpConstant %1 0
1162 %3 = OpTypePointer Input %2)";
1163 CompileSuccessfully(spirv
.c_str());
1164 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1166 getDiagnosticString(),
1167 HasSubstr(make_message("OpTypePointer Type <id> '2[%uint_0]' is not a "
1171 TEST_P(ValidateIdWithMessage
, OpTypePointerCanHaveUntypedPointer
) {
1172 const std::string spirv
= R
"(
1174 OpCapability Linkage
1175 OpCapability UntypedPointersKHR
1176 OpCapability WorkgroupMemoryExplicitLayoutKHR
1177 OpExtension "SPV_KHR_workgroup_memory_explicit_layout
"
1178 OpExtension "SPV_KHR_untyped_pointers
"
1179 OpMemoryModel Logical OpenCL
1180 %ptr = OpTypeUntypedPointerKHR Workgroup
1181 %ptr2 = OpTypePointer Private %ptr
1184 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_4
);
1185 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4
));
1188 TEST_P(ValidateIdWithMessage
, OpTypeUntypedPointerWorkgroupGood
) {
1189 const std::string spirv
= R
"(
1191 OpCapability Linkage
1192 OpCapability UntypedPointersKHR
1193 OpCapability WorkgroupMemoryExplicitLayoutKHR
1194 OpExtension "SPV_KHR_workgroup_memory_explicit_layout
"
1195 OpExtension "SPV_KHR_untyped_pointers
"
1196 OpMemoryModel Logical GLSL450
1197 %ptr = OpTypeUntypedPointerKHR Workgroup
1200 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_4
);
1201 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4
));
1204 TEST_P(ValidateIdWithMessage
,
1205 OpTypeUntypedPointerWorkgroupMissingExplicitLayout
) {
1206 const std::string spirv
= R
"(
1208 OpCapability UntypedPointersKHR
1209 OpExtension "SPV_KHR_untyped_pointers
"
1210 OpMemoryModel Logical GLSL450
1211 OpEntryPoint GLCompute %main "main
"
1212 OpExecutionMode %main LocalSize 1 1 1
1213 %ptr = OpTypeUntypedPointerKHR Workgroup
1215 %void_fn = OpTypeFunction %void
1216 %main = OpFunction %void None %void_fn
1222 CompileSuccessfully(spirv
, SPV_ENV_VULKAN_1_1
);
1223 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_VULKAN_1_1
));
1225 getDiagnosticString(),
1226 HasSubstr("Workgroup storage class untyped pointers in Vulkan require "
1227 "WorkgroupMemoryExplicitLayoutKHR be declared"));
1230 TEST_P(ValidateIdWithMessage
, OpTypeUntypedPointerWorkgroupGoodAll
) {
1231 const std::string spirv
= R
"(
1233 OpCapability Linkage
1234 OpCapability UntypedPointersKHR
1235 OpExtension "SPV_KHR_untyped_pointers
"
1236 OpMemoryModel Logical GLSL450
1237 %ptr = OpTypeUntypedPointerKHR Workgroup
1240 CompileSuccessfully(spirv
);
1241 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1244 TEST_P(ValidateIdWithMessage
, OpTypeUntypedPointerStorageBufferGood
) {
1245 const std::string spirv
= R
"(
1247 OpCapability Linkage
1248 OpCapability UntypedPointersKHR
1249 OpExtension "SPV_KHR_storage_buffer_storage_class
"
1250 OpExtension "SPV_KHR_untyped_pointers
"
1251 OpMemoryModel Logical GLSL450
1252 %ptr = OpTypeUntypedPointerKHR StorageBuffer
1255 CompileSuccessfully(spirv
);
1256 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1259 TEST_P(ValidateIdWithMessage
, OpTypeUntypedPointerUniformGood
) {
1260 const std::string spirv
= R
"(
1262 OpCapability Linkage
1263 OpCapability UntypedPointersKHR
1264 OpExtension "SPV_KHR_untyped_pointers
"
1265 OpMemoryModel Logical GLSL450
1266 %ptr = OpTypeUntypedPointerKHR Uniform
1269 CompileSuccessfully(spirv
);
1270 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1273 TEST_P(ValidateIdWithMessage
, OpTypeUntypedPointerPushConstantGood
) {
1274 const std::string spirv
= R
"(
1276 OpCapability Linkage
1277 OpCapability UntypedPointersKHR
1278 OpExtension "SPV_KHR_untyped_pointers
"
1279 OpMemoryModel Logical GLSL450
1280 %ptr = OpTypeUntypedPointerKHR PushConstant
1283 CompileSuccessfully(spirv
);
1284 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1287 TEST_P(ValidateIdWithMessage
, OpTypeUntypedPointerCrossWorkgroupGood
) {
1288 const std::string spirv
= R
"(
1290 OpCapability Linkage
1291 OpCapability UntypedPointersKHR
1292 OpExtension "SPV_KHR_untyped_pointers
"
1293 OpMemoryModel Logical OpenCL
1294 %ptr = OpTypeUntypedPointerKHR CrossWorkgroup
1297 CompileSuccessfully(spirv
);
1298 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1301 TEST_P(ValidateIdWithMessage
, OpTypeUntypedPointerVulkanInvalidStorageClass
) {
1302 const std::string spirv
= R
"(
1304 OpCapability UntypedPointersKHR
1305 OpExtension "SPV_KHR_untyped_pointers
"
1306 OpMemoryModel Logical GLSL450
1307 OpEntryPoint GLCompute %main "main
"
1308 OpExecutionMode %main LocalSize 1 1 1
1310 %void_fn = OpTypeFunction %void
1311 %ptr = OpTypeUntypedPointerKHR Private
1312 %main = OpFunction %void None %void_fn
1318 CompileSuccessfully(spirv
, SPV_ENV_VULKAN_1_0
);
1319 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_VULKAN_1_0
));
1320 EXPECT_THAT(getDiagnosticString(),
1321 HasSubstr("In Vulkan, untyped pointers can only be used in an "
1322 "explicitly laid out storage class"));
1325 TEST_P(ValidateIdWithMessage
, OpTypeFunctionGood
) {
1326 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1328 %2 = OpTypeFunction %1)";
1329 CompileSuccessfully(spirv
.c_str());
1330 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1332 TEST_P(ValidateIdWithMessage
, OpTypeFunctionReturnTypeBad
) {
1333 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1335 %2 = OpConstant %1 0
1336 %3 = OpTypeFunction %2)";
1337 CompileSuccessfully(spirv
.c_str());
1338 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1339 EXPECT_THAT(getDiagnosticString(),
1340 HasSubstr(make_message(
1341 "OpTypeFunction Return Type <id> '2[%uint_0]' is not "
1344 TEST_P(ValidateIdWithMessage
, OpTypeFunctionParameterBad
) {
1345 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1348 %3 = OpConstant %2 0
1349 %4 = OpTypeFunction %1 %2 %3)";
1350 CompileSuccessfully(spirv
.c_str());
1351 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1352 EXPECT_THAT(getDiagnosticString(),
1353 HasSubstr(make_message(
1354 "OpTypeFunction Parameter Type <id> '3[%uint_0]' is not a "
1358 TEST_P(ValidateIdWithMessage
, OpTypeFunctionParameterTypeVoidBad
) {
1359 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1362 %4 = OpTypeFunction %1 %2 %1)";
1363 CompileSuccessfully(spirv
.c_str());
1364 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1365 EXPECT_THAT(getDiagnosticString(),
1366 HasSubstr(make_message(
1367 "OpTypeFunction Parameter Type <id> '1[%void]' cannot "
1368 "be OpTypeVoid.")));
1371 TEST_P(ValidateIdWithMessage
, OpTypePipeGood
) {
1372 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1374 %2 = OpTypeVector %1 16
1375 %3 = OpTypePipe ReadOnly)";
1376 CompileSuccessfully(spirv
.c_str());
1377 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1380 TEST_P(ValidateIdWithMessage
, OpConstantTrueGood
) {
1381 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1383 %2 = OpConstantTrue %1)";
1384 CompileSuccessfully(spirv
.c_str());
1385 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1387 TEST_P(ValidateIdWithMessage
, OpConstantTrueBad
) {
1388 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1390 %2 = OpConstantTrue %1)";
1391 CompileSuccessfully(spirv
.c_str());
1392 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1393 EXPECT_THAT(getDiagnosticString(),
1394 HasSubstr(make_message(
1395 "OpConstantTrue Result Type <id> '1[%void]' is not a boolean "
1399 TEST_P(ValidateIdWithMessage
, OpConstantFalseGood
) {
1400 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1402 %2 = OpConstantTrue %1)";
1403 CompileSuccessfully(spirv
.c_str());
1404 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1406 TEST_P(ValidateIdWithMessage
, OpConstantFalseBad
) {
1407 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1409 %2 = OpConstantFalse %1)";
1410 CompileSuccessfully(spirv
.c_str());
1411 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1413 getDiagnosticString(),
1414 HasSubstr(make_message(
1415 "OpConstantFalse Result Type <id> '1[%void]' is not a boolean "
1419 TEST_P(ValidateIdWithMessage
, OpConstantGood
) {
1420 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1422 %2 = OpConstant %1 1)";
1423 CompileSuccessfully(spirv
.c_str());
1424 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1426 TEST_P(ValidateIdWithMessage
, OpConstantBad
) {
1427 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1429 %2 = OpConstant !1 !0)";
1430 // The expected failure code is implementation dependent (currently
1431 // INVALID_BINARY because the binary parser catches these cases) and may
1432 // change over time, but this must always fail.
1433 CompileSuccessfully(spirv
.c_str());
1434 EXPECT_EQ(SPV_ERROR_INVALID_BINARY
, ValidateInstructions());
1437 TEST_P(ValidateIdWithMessage
, OpConstantCompositeVectorGood
) {
1438 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1440 %2 = OpTypeVector %1 4
1441 %3 = OpConstant %1 3.14
1442 %4 = OpConstantComposite %2 %3 %3 %3 %3)";
1443 CompileSuccessfully(spirv
.c_str());
1444 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1446 TEST_P(ValidateIdWithMessage
, OpConstantCompositeVectorWithUndefGood
) {
1447 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1449 %2 = OpTypeVector %1 4
1450 %3 = OpConstant %1 3.14
1452 %4 = OpConstantComposite %2 %3 %3 %3 %9)";
1453 CompileSuccessfully(spirv
.c_str());
1454 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1456 TEST_P(ValidateIdWithMessage
, OpConstantCompositeVectorResultTypeBad
) {
1457 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1459 %2 = OpTypeVector %1 4
1460 %3 = OpConstant %1 3.14
1461 %4 = OpConstantComposite %1 %3 %3 %3 %3)";
1462 CompileSuccessfully(spirv
.c_str());
1463 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1464 EXPECT_THAT(getDiagnosticString(),
1465 HasSubstr(make_message(
1466 "OpConstantComposite Result Type <id> '1[%float]' is not a "
1467 "composite type.")));
1469 TEST_P(ValidateIdWithMessage
, OpConstantCompositeVectorConstituentTypeBad
) {
1470 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1472 %2 = OpTypeVector %1 4
1474 %3 = OpConstant %1 3.14
1475 %5 = OpConstant %4 42 ; bad type for constant value
1476 %6 = OpConstantComposite %2 %3 %5 %3 %3)";
1477 CompileSuccessfully(spirv
.c_str());
1478 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1479 EXPECT_THAT(getDiagnosticString(),
1480 HasSubstr(make_message(
1481 "OpConstantComposite Constituent <id> '5[%uint_42]'s type "
1482 "does not match Result Type <id> '2[%v4float]'s vector "
1485 TEST_P(ValidateIdWithMessage
,
1486 OpConstantCompositeVectorConstituentUndefTypeBad
) {
1487 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1489 %2 = OpTypeVector %1 4
1491 %3 = OpConstant %1 3.14
1492 %5 = OpUndef %4 ; bad type for undef value
1493 %6 = OpConstantComposite %2 %3 %5 %3 %3)";
1494 CompileSuccessfully(spirv
.c_str());
1495 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1497 getDiagnosticString(),
1498 HasSubstr(make_message(
1499 "OpConstantComposite Constituent <id> '5[%5]'s type does not "
1500 "match Result Type <id> '2[%v4float]'s vector element type.")));
1502 TEST_P(ValidateIdWithMessage
, OpConstantCompositeMatrixGood
) {
1503 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1505 %2 = OpTypeVector %1 4
1506 %3 = OpTypeMatrix %2 4
1507 %4 = OpConstant %1 1.0
1508 %5 = OpConstant %1 0.0
1509 %6 = OpConstantComposite %2 %4 %5 %5 %5
1510 %7 = OpConstantComposite %2 %5 %4 %5 %5
1511 %8 = OpConstantComposite %2 %5 %5 %4 %5
1512 %9 = OpConstantComposite %2 %5 %5 %5 %4
1513 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1514 CompileSuccessfully(spirv
.c_str());
1515 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1517 TEST_P(ValidateIdWithMessage
, OpConstantCompositeMatrixUndefGood
) {
1518 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1520 %2 = OpTypeVector %1 4
1521 %3 = OpTypeMatrix %2 4
1522 %4 = OpConstant %1 1.0
1523 %5 = OpConstant %1 0.0
1524 %6 = OpConstantComposite %2 %4 %5 %5 %5
1525 %7 = OpConstantComposite %2 %5 %4 %5 %5
1526 %8 = OpConstantComposite %2 %5 %5 %4 %5
1528 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1529 CompileSuccessfully(spirv
.c_str());
1530 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1532 TEST_P(ValidateIdWithMessage
, OpConstantCompositeMatrixConstituentTypeBad
) {
1533 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1535 %2 = OpTypeVector %1 4
1536 %11 = OpTypeVector %1 3
1537 %3 = OpTypeMatrix %2 4
1538 %4 = OpConstant %1 1.0
1539 %5 = OpConstant %1 0.0
1540 %6 = OpConstantComposite %2 %4 %5 %5 %5
1541 %7 = OpConstantComposite %2 %5 %4 %5 %5
1542 %8 = OpConstantComposite %2 %5 %5 %4 %5
1543 %9 = OpConstantComposite %11 %5 %5 %5
1544 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1545 CompileSuccessfully(spirv
.c_str());
1546 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1547 EXPECT_THAT(getDiagnosticString(),
1548 HasSubstr(make_message(
1549 "OpConstantComposite Constituent <id> '10[%10]' vector "
1550 "component count does not match Result Type <id> "
1551 "'4[%mat4v4float]'s vector component count.")));
1553 TEST_P(ValidateIdWithMessage
,
1554 OpConstantCompositeMatrixConstituentUndefTypeBad
) {
1555 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1557 %2 = OpTypeVector %1 4
1558 %11 = OpTypeVector %1 3
1559 %3 = OpTypeMatrix %2 4
1560 %4 = OpConstant %1 1.0
1561 %5 = OpConstant %1 0.0
1562 %6 = OpConstantComposite %2 %4 %5 %5 %5
1563 %7 = OpConstantComposite %2 %5 %4 %5 %5
1564 %8 = OpConstantComposite %2 %5 %5 %4 %5
1566 %10 = OpConstantComposite %3 %6 %7 %8 %9)";
1567 CompileSuccessfully(spirv
.c_str());
1568 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1569 EXPECT_THAT(getDiagnosticString(),
1570 HasSubstr(make_message(
1571 "OpConstantComposite Constituent <id> '10[%10]' vector "
1572 "component count does not match Result Type <id> "
1573 "'4[%mat4v4float]'s vector component count.")));
1575 TEST_P(ValidateIdWithMessage
, OpConstantCompositeArrayGood
) {
1576 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1578 %2 = OpConstant %1 4
1579 %3 = OpTypeArray %1 %2
1580 %4 = OpConstantComposite %3 %2 %2 %2 %2)";
1581 CompileSuccessfully(spirv
.c_str());
1582 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1584 TEST_P(ValidateIdWithMessage
, OpConstantCompositeArrayWithUndefGood
) {
1585 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1587 %2 = OpConstant %1 4
1589 %3 = OpTypeArray %1 %2
1590 %4 = OpConstantComposite %3 %2 %2 %2 %9)";
1591 CompileSuccessfully(spirv
.c_str());
1592 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1595 TEST_P(ValidateIdWithMessage
, OpConstantCompositeArrayConstConstituentTypeBad
) {
1596 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1598 %2 = OpConstant %1 4
1599 %3 = OpTypeArray %1 %2
1600 %4 = OpConstantComposite %3 %2 %2 %2 %1)"; // Uses a type as operand
1601 CompileSuccessfully(spirv
.c_str());
1602 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1603 EXPECT_THAT(getDiagnosticString(),
1604 HasSubstr(make_message("Operand '1[%uint]' cannot be a "
1607 TEST_P(ValidateIdWithMessage
, OpConstantCompositeArrayConstConstituentBad
) {
1608 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1610 %2 = OpConstant %1 4
1611 %3 = OpTypeArray %1 %2
1612 %4 = OpTypePointer Uniform %1
1613 %5 = OpVariable %4 Uniform
1614 %6 = OpConstantComposite %3 %2 %2 %2 %5)";
1615 CompileSuccessfully(spirv
.c_str());
1616 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1617 EXPECT_THAT(getDiagnosticString(),
1618 HasSubstr(make_message(
1619 "OpConstantComposite Constituent <id> '5[%5]' is not a "
1620 "constant or undef.")));
1622 TEST_P(ValidateIdWithMessage
, OpConstantCompositeArrayConstituentTypeBad
) {
1623 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1625 %2 = OpConstant %1 4
1626 %3 = OpTypeArray %1 %2
1628 %6 = OpConstant %5 3.14 ; bad type for const value
1629 %4 = OpConstantComposite %3 %2 %2 %2 %6)";
1630 CompileSuccessfully(spirv
.c_str());
1631 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1632 EXPECT_THAT(getDiagnosticString(),
1633 HasSubstr(make_message(
1634 "OpConstantComposite Constituent <id> "
1635 "'5[%float_3_1400001]'s type does not match Result "
1636 "Type <id> '3[%_arr_uint_uint_4]'s array element "
1639 TEST_P(ValidateIdWithMessage
, OpConstantCompositeArrayConstituentUndefTypeBad
) {
1640 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1642 %2 = OpConstant %1 4
1643 %3 = OpTypeArray %1 %2
1645 %6 = OpUndef %5 ; bad type for undef
1646 %4 = OpConstantComposite %3 %2 %2 %2 %6)";
1647 CompileSuccessfully(spirv
.c_str());
1648 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1650 getDiagnosticString(),
1651 HasSubstr(make_message("OpConstantComposite Constituent <id> "
1652 "'5[%5]'s type does not match Result "
1653 "Type <id> '3[%_arr_uint_uint_4]'s array element "
1656 TEST_P(ValidateIdWithMessage
, OpConstantCompositeStructGood
) {
1657 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1660 %3 = OpTypeStruct %1 %1 %2
1661 %4 = OpConstant %1 42
1662 %5 = OpConstant %2 4300000000
1663 %6 = OpConstantComposite %3 %4 %4 %5)";
1664 CompileSuccessfully(spirv
.c_str());
1665 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1667 TEST_P(ValidateIdWithMessage
, OpConstantCompositeStructUndefGood
) {
1668 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1671 %3 = OpTypeStruct %1 %1 %2
1672 %4 = OpConstant %1 42
1674 %6 = OpConstantComposite %3 %4 %4 %5)";
1675 CompileSuccessfully(spirv
.c_str());
1676 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1678 TEST_P(ValidateIdWithMessage
, OpConstantCompositeStructMemberTypeBad
) {
1679 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1682 %3 = OpTypeStruct %1 %1 %2
1683 %4 = OpConstant %1 42
1684 %5 = OpConstant %2 4300000000
1685 %6 = OpConstantComposite %3 %4 %5 %4)";
1686 CompileSuccessfully(spirv
.c_str());
1687 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1688 EXPECT_THAT(getDiagnosticString(),
1689 HasSubstr(make_message(
1690 "OpConstantComposite Constituent <id> "
1691 "'5[%ulong_4300000000]' type does not match the "
1692 "Result Type <id> '3[%_struct_3]'s member type.")));
1695 TEST_P(ValidateIdWithMessage
, OpConstantCompositeStructMemberUndefTypeBad
) {
1696 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1699 %3 = OpTypeStruct %1 %1 %2
1700 %4 = OpConstant %1 42
1702 %6 = OpConstantComposite %3 %4 %5 %4)";
1703 CompileSuccessfully(spirv
.c_str());
1704 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1705 EXPECT_THAT(getDiagnosticString(),
1706 HasSubstr(make_message(
1707 "OpConstantComposite Constituent <id> '5[%5]' type "
1708 "does not match the Result Type <id> '3[%_struct_3]'s "
1712 TEST_P(ValidateIdWithMessage
, OpConstantSamplerGood
) {
1713 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1714 %float = OpTypeFloat 32
1715 %samplerType = OpTypeSampler
1716 %3 = OpConstantSampler %samplerType ClampToEdge 0 Nearest)";
1717 CompileSuccessfully(spirv
.c_str());
1718 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1720 TEST_P(ValidateIdWithMessage
, OpConstantSamplerResultTypeBad
) {
1721 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1723 %2 = OpConstantSampler %1 Clamp 0 Nearest)";
1724 CompileSuccessfully(spirv
.c_str());
1725 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1727 getDiagnosticString(),
1728 HasSubstr(make_message(
1729 "OpConstantSampler Result Type <id> '1[%float]' is not a sampler "
1733 TEST_P(ValidateIdWithMessage
, OpConstantNullGood
) {
1734 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1736 %2 = OpConstantNull %1
1738 %4 = OpConstantNull %3
1740 %6 = OpConstantNull %5
1741 %7 = OpTypePointer UniformConstant %3
1742 %8 = OpConstantNull %7
1744 %10 = OpConstantNull %9
1745 %11 = OpTypeDeviceEvent
1746 %12 = OpConstantNull %11
1747 %13 = OpTypeReserveId
1748 %14 = OpConstantNull %13
1750 %16 = OpConstantNull %15
1751 %17 = OpTypeVector %5 2
1752 %18 = OpConstantNull %17
1753 %19 = OpTypeMatrix %17 2
1754 %20 = OpConstantNull %19
1755 %25 = OpConstant %3 8
1756 %21 = OpTypeArray %3 %25
1757 %22 = OpConstantNull %21
1758 %23 = OpTypeStruct %3 %5 %1
1759 %24 = OpConstantNull %23
1760 %26 = OpTypeArray %17 %25
1761 %27 = OpConstantNull %26
1762 %28 = OpTypeStruct %7 %26 %26 %1
1763 %29 = OpConstantNull %28
1765 CompileSuccessfully(spirv
.c_str());
1766 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1769 TEST_P(ValidateIdWithMessage
, OpConstantNullBasicBad
) {
1770 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1772 %2 = OpConstantNull %1)";
1773 CompileSuccessfully(spirv
.c_str());
1774 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1776 getDiagnosticString(),
1777 HasSubstr(make_message(
1778 "OpConstantNull Result Type <id> '1[%void]' cannot have a null "
1782 TEST_P(ValidateIdWithMessage
, OpConstantNullArrayBad
) {
1783 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1786 %4 = OpConstant %2 4
1787 %5 = OpTypeArray %3 %4
1788 %6 = OpConstantNull %5)";
1789 CompileSuccessfully(spirv
.c_str());
1790 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1792 getDiagnosticString(),
1793 HasSubstr(make_message(
1794 "OpConstantNull Result Type <id> '4[%_arr_2_uint_4]' cannot have a "
1798 TEST_P(ValidateIdWithMessage
, OpConstantNullStructBad
) {
1799 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1801 %3 = OpTypeStruct %2 %2
1802 %4 = OpConstantNull %3)";
1803 CompileSuccessfully(spirv
.c_str());
1804 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1806 getDiagnosticString(),
1807 HasSubstr(make_message("OpConstantNull Result Type <id> '2[%_struct_2]' "
1808 "cannot have a null value.")));
1811 TEST_P(ValidateIdWithMessage
, OpConstantNullRuntimeArrayBad
) {
1812 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1814 %array = OpTypeRuntimeArray %bool
1815 %null = OpConstantNull %array)";
1816 CompileSuccessfully(spirv
.c_str());
1817 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1819 getDiagnosticString(),
1820 HasSubstr(make_message(
1821 "OpConstantNull Result Type <id> '2[%_runtimearr_bool]' cannot have "
1825 TEST_P(ValidateIdWithMessage
, OpSpecConstantTrueGood
) {
1826 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1828 %2 = OpSpecConstantTrue %1)";
1829 CompileSuccessfully(spirv
.c_str());
1830 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1832 TEST_P(ValidateIdWithMessage
, OpSpecConstantTrueBad
) {
1833 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1835 %2 = OpSpecConstantTrue %1)";
1836 CompileSuccessfully(spirv
.c_str());
1837 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1838 EXPECT_THAT(getDiagnosticString(),
1839 HasSubstr(make_message(
1840 "OpSpecConstantTrue Result Type <id> '1[%void]' is not "
1841 "a boolean type")));
1844 TEST_P(ValidateIdWithMessage
, OpSpecConstantFalseGood
) {
1845 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1847 %2 = OpSpecConstantFalse %1)";
1848 CompileSuccessfully(spirv
.c_str());
1849 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1851 TEST_P(ValidateIdWithMessage
, OpSpecConstantFalseBad
) {
1852 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1854 %2 = OpSpecConstantFalse %1)";
1855 CompileSuccessfully(spirv
.c_str());
1856 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1857 EXPECT_THAT(getDiagnosticString(),
1858 HasSubstr(make_message(
1859 "OpSpecConstantFalse Result Type <id> '1[%void]' is not "
1860 "a boolean type")));
1863 TEST_P(ValidateIdWithMessage
, OpSpecConstantGood
) {
1864 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1866 %2 = OpSpecConstant %1 42)";
1867 CompileSuccessfully(spirv
.c_str());
1868 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1870 TEST_P(ValidateIdWithMessage
, OpSpecConstantBad
) {
1871 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1873 %2 = OpSpecConstant !1 !4)";
1874 // The expected failure code is implementation dependent (currently
1875 // INVALID_BINARY because the binary parser catches these cases) and may
1876 // change over time, but this must always fail.
1877 CompileSuccessfully(spirv
.c_str());
1878 EXPECT_EQ(SPV_ERROR_INVALID_BINARY
, ValidateInstructions());
1880 getDiagnosticString(),
1881 HasSubstr(make_message("Type Id 1 is not a scalar numeric type")));
1884 // Valid: SpecConstantComposite specializes to a vector.
1885 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeVectorGood
) {
1886 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1888 %2 = OpTypeVector %1 4
1889 %3 = OpSpecConstant %1 3.14
1890 %4 = OpConstant %1 3.14
1891 %5 = OpSpecConstantComposite %2 %3 %3 %4 %4)";
1892 CompileSuccessfully(spirv
.c_str());
1893 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1896 // Valid: Vector of floats and Undefs.
1897 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeVectorWithUndefGood
) {
1898 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1900 %2 = OpTypeVector %1 4
1901 %3 = OpSpecConstant %1 3.14
1902 %5 = OpConstant %1 3.14
1904 %4 = OpSpecConstantComposite %2 %3 %5 %3 %9)";
1905 CompileSuccessfully(spirv
.c_str());
1906 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
1909 // Invalid: result type is float.
1910 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeVectorResultTypeBad
) {
1911 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1913 %2 = OpTypeVector %1 4
1914 %3 = OpSpecConstant %1 3.14
1915 %4 = OpSpecConstantComposite %1 %3 %3 %3 %3)";
1916 CompileSuccessfully(spirv
.c_str());
1917 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1918 EXPECT_THAT(getDiagnosticString(),
1919 HasSubstr(make_message("is not a composite type")));
1922 // Invalid: Vector contains a mix of Int and Float.
1923 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeVectorConstituentTypeBad
) {
1924 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1926 %2 = OpTypeVector %1 4
1928 %3 = OpSpecConstant %1 3.14
1929 %5 = OpConstant %4 42 ; bad type for constant value
1930 %6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1931 CompileSuccessfully(spirv
.c_str());
1932 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1933 EXPECT_THAT(getDiagnosticString(),
1934 HasSubstr(make_message(
1935 "OpSpecConstantComposite Constituent <id> "
1936 "'5[%uint_42]'s type does not match Result Type <id> "
1937 "'2[%v4float]'s vector element type.")));
1940 // Invalid: Constituent is not a constant
1941 TEST_P(ValidateIdWithMessage
,
1942 OpSpecConstantCompositeVectorConstituentNotConstantBad
) {
1943 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1945 %2 = OpTypeVector %1 4
1947 %4 = OpSpecConstant %1 3.14
1948 %5 = OpTypePointer Uniform %1
1949 %6 = OpVariable %5 Uniform
1950 %7 = OpSpecConstantComposite %2 %6 %4 %4 %4)";
1951 CompileSuccessfully(spirv
.c_str());
1952 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1953 EXPECT_THAT(getDiagnosticString(),
1954 HasSubstr(make_message(
1955 "OpSpecConstantComposite Constituent <id> '6[%6]' is "
1956 "not a constant or undef.")));
1959 // Invalid: Vector contains a mix of Undef-int and Float.
1960 TEST_P(ValidateIdWithMessage
,
1961 OpSpecConstantCompositeVectorConstituentUndefTypeBad
) {
1962 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1964 %2 = OpTypeVector %1 4
1966 %3 = OpSpecConstant %1 3.14
1967 %5 = OpUndef %4 ; bad type for undef value
1968 %6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1969 CompileSuccessfully(spirv
.c_str());
1970 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1971 EXPECT_THAT(getDiagnosticString(),
1972 HasSubstr(make_message(
1973 "OpSpecConstantComposite Constituent <id> '5[%5]'s "
1974 "type does not match Result Type <id> '2[%v4float]'s "
1975 "vector element type.")));
1978 // Invalid: Vector expects 3 components, but 4 specified.
1979 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeVectorNumComponentsBad
) {
1980 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1982 %2 = OpTypeVector %1 3
1983 %3 = OpConstant %1 3.14
1984 %5 = OpSpecConstant %1 4.0
1985 %6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1986 CompileSuccessfully(spirv
.c_str());
1987 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
1988 EXPECT_THAT(getDiagnosticString(),
1989 HasSubstr(make_message(
1990 "OpSpecConstantComposite Constituent <id> count does "
1991 "not match Result Type <id> '2[%v3float]'s vector "
1992 "component count.")));
1995 // Valid: 4x4 matrix of floats
1996 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeMatrixGood
) {
1997 std::string spirv
= kGLSL450MemoryModel
+ R
"(
1999 %2 = OpTypeVector %1 4
2000 %3 = OpTypeMatrix %2 4
2001 %4 = OpConstant %1 1.0
2002 %5 = OpSpecConstant %1 0.0
2003 %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
2004 %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
2005 %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
2006 %9 = OpSpecConstantComposite %2 %5 %5 %5 %4
2007 %10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
2008 CompileSuccessfully(spirv
.c_str());
2009 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2012 // Valid: Matrix in which one column is Undef
2013 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeMatrixUndefGood
) {
2014 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2016 %2 = OpTypeVector %1 4
2017 %3 = OpTypeMatrix %2 4
2018 %4 = OpConstant %1 1.0
2019 %5 = OpSpecConstant %1 0.0
2020 %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
2021 %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
2022 %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
2024 %10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
2025 CompileSuccessfully(spirv
.c_str());
2026 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2029 // Invalid: Matrix in which the sizes of column vectors are not equal.
2030 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeMatrixConstituentTypeBad
) {
2031 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2033 %2 = OpTypeVector %1 4
2034 %3 = OpTypeVector %1 3
2035 %4 = OpTypeMatrix %2 4
2036 %5 = OpSpecConstant %1 1.0
2037 %6 = OpConstant %1 0.0
2038 %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
2039 %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
2040 %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
2041 %10 = OpSpecConstantComposite %3 %6 %6 %6
2042 %11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
2043 CompileSuccessfully(spirv
.c_str());
2044 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2045 EXPECT_THAT(getDiagnosticString(),
2046 HasSubstr(make_message(
2047 "OpSpecConstantComposite Constituent <id> '10[%10]' "
2048 "vector component count does not match Result Type "
2049 "<id> '4[%mat4v4float]'s vector component count.")));
2052 // Invalid: Matrix type expects 4 columns but only 3 specified.
2053 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeMatrixNumColsBad
) {
2054 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2056 %2 = OpTypeVector %1 4
2057 %3 = OpTypeMatrix %2 4
2058 %4 = OpSpecConstant %1 1.0
2059 %5 = OpConstant %1 0.0
2060 %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
2061 %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
2062 %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
2063 %10 = OpSpecConstantComposite %3 %6 %7 %8)";
2064 CompileSuccessfully(spirv
.c_str());
2065 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2066 EXPECT_THAT(getDiagnosticString(),
2067 HasSubstr(make_message(
2068 "OpSpecConstantComposite Constituent <id> count does "
2069 "not match Result Type <id> '3[%mat4v4float]'s matrix column "
2073 // Invalid: Composite contains a non-const/undef component
2074 TEST_P(ValidateIdWithMessage
,
2075 OpSpecConstantCompositeMatrixConstituentNotConstBad
) {
2076 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2078 %2 = OpConstant %1 0.0
2079 %3 = OpTypeVector %1 4
2080 %4 = OpTypeMatrix %3 4
2081 %5 = OpSpecConstantComposite %3 %2 %2 %2 %2
2082 %6 = OpTypePointer Uniform %1
2083 %7 = OpVariable %6 Uniform
2084 %8 = OpSpecConstantComposite %4 %5 %5 %5 %7)";
2085 CompileSuccessfully(spirv
.c_str());
2086 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2087 EXPECT_THAT(getDiagnosticString(),
2088 HasSubstr(make_message(
2089 "OpSpecConstantComposite Constituent <id> '7[%7]' is "
2090 "not a constant or undef.")));
2093 // Invalid: Composite contains a column that is *not* a vector (it's an array)
2094 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeMatrixColTypeBad
) {
2095 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2098 %3 = OpSpecConstant %2 4
2099 %4 = OpConstant %1 0.0
2100 %5 = OpTypeVector %1 4
2101 %6 = OpTypeArray %2 %3
2102 %7 = OpTypeMatrix %5 4
2103 %8 = OpSpecConstantComposite %6 %3 %3 %3 %3
2104 %9 = OpSpecConstantComposite %5 %4 %4 %4 %4
2105 %10 = OpSpecConstantComposite %7 %9 %9 %9 %8)";
2106 CompileSuccessfully(spirv
.c_str());
2107 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2108 EXPECT_THAT(getDiagnosticString(),
2109 HasSubstr(make_message(
2110 "OpSpecConstantComposite Constituent <id> '8[%8]' type "
2111 "does not match Result Type <id> '7[%mat4v4float]'s "
2112 "matrix column type.")));
2115 // Invalid: Matrix with an Undef column of the wrong size.
2116 TEST_P(ValidateIdWithMessage
,
2117 OpSpecConstantCompositeMatrixConstituentUndefTypeBad
) {
2118 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2120 %2 = OpTypeVector %1 4
2121 %3 = OpTypeVector %1 3
2122 %4 = OpTypeMatrix %2 4
2123 %5 = OpSpecConstant %1 1.0
2124 %6 = OpSpecConstant %1 0.0
2125 %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
2126 %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
2127 %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
2129 %11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
2130 CompileSuccessfully(spirv
.c_str());
2131 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2132 EXPECT_THAT(getDiagnosticString(),
2133 HasSubstr(make_message(
2134 "OpSpecConstantComposite Constituent <id> '10[%10]' "
2135 "vector component count does not match Result Type "
2136 "<id> '4[%mat4v4float]'s vector component count.")));
2139 // Invalid: Matrix in which some columns are Int and some are Float.
2140 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeMatrixColumnTypeBad
) {
2141 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2144 %3 = OpTypeVector %1 2
2145 %4 = OpTypeVector %2 2
2146 %5 = OpTypeMatrix %4 2
2147 %6 = OpSpecConstant %1 42
2148 %7 = OpConstant %2 3.14
2149 %8 = OpSpecConstantComposite %3 %6 %6
2150 %9 = OpSpecConstantComposite %4 %7 %7
2151 %10 = OpSpecConstantComposite %5 %8 %9)";
2152 CompileSuccessfully(spirv
.c_str());
2153 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2154 EXPECT_THAT(getDiagnosticString(),
2155 HasSubstr(make_message(
2156 "OpSpecConstantComposite Constituent <id> '8[%8]' "
2157 "component type does not match Result Type <id> "
2158 "'5[%mat2v2float]'s matrix column component type.")));
2161 // Valid: Array of integers
2162 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeArrayGood
) {
2163 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2165 %2 = OpSpecConstant %1 4
2166 %5 = OpConstant %1 5
2167 %3 = OpTypeArray %1 %2
2168 %6 = OpTypeArray %1 %5
2169 %4 = OpSpecConstantComposite %3 %2 %2 %2 %2
2170 %7 = OpSpecConstantComposite %3 %5 %5 %5 %5)";
2171 CompileSuccessfully(spirv
.c_str());
2172 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2175 // Invalid: Expecting an array of 4 components, but 3 specified.
2176 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeArrayNumComponentsBad
) {
2177 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2179 %2 = OpConstant %1 4
2180 %3 = OpTypeArray %1 %2
2181 %4 = OpSpecConstantComposite %3 %2 %2 %2)";
2182 CompileSuccessfully(spirv
.c_str());
2183 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2184 EXPECT_THAT(getDiagnosticString(),
2185 HasSubstr(make_message(
2186 "OpSpecConstantComposite Constituent count does not "
2187 "match Result Type <id> '3[%_arr_uint_uint_4]'s array "
2191 // Valid: Array of Integers and Undef-int
2192 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeArrayWithUndefGood
) {
2193 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2195 %2 = OpSpecConstant %1 4
2197 %3 = OpTypeArray %1 %2
2198 %4 = OpSpecConstantComposite %3 %2 %2 %2 %9)";
2199 CompileSuccessfully(spirv
.c_str());
2200 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2203 // Invalid: Array uses a type as operand.
2204 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeArrayConstConstituentBad
) {
2205 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2207 %2 = OpConstant %1 4
2208 %3 = OpTypeArray %1 %2
2209 %4 = OpTypePointer Uniform %1
2210 %5 = OpVariable %4 Uniform
2211 %6 = OpSpecConstantComposite %3 %2 %2 %2 %5)";
2212 CompileSuccessfully(spirv
.c_str());
2213 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2214 EXPECT_THAT(getDiagnosticString(),
2215 HasSubstr(make_message(
2216 "OpSpecConstantComposite Constituent <id> '5[%5]' is "
2217 "not a constant or undef.")));
2220 // Invalid: Array has a mix of Int and Float components.
2221 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeArrayConstituentTypeBad
) {
2222 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2224 %2 = OpConstant %1 4
2225 %3 = OpTypeArray %1 %2
2227 %5 = OpSpecConstant %4 3.14 ; bad type for const value
2228 %6 = OpSpecConstantComposite %3 %2 %2 %2 %5)";
2229 CompileSuccessfully(spirv
.c_str());
2230 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2231 EXPECT_THAT(getDiagnosticString(),
2232 HasSubstr(make_message(
2233 "OpSpecConstantComposite Constituent <id> '5[%5]'s "
2234 "type does not match Result Type <id> "
2235 "'3[%_arr_uint_uint_4]'s array element type.")));
2238 // Invalid: Array has a mix of Int and Undef-float.
2239 TEST_P(ValidateIdWithMessage
,
2240 OpSpecConstantCompositeArrayConstituentUndefTypeBad
) {
2241 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2243 %2 = OpSpecConstant %1 4
2244 %3 = OpTypeArray %1 %2
2246 %6 = OpUndef %5 ; bad type for undef
2247 %4 = OpSpecConstantComposite %3 %2 %2 %2 %6)";
2248 CompileSuccessfully(spirv
.c_str());
2249 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2250 EXPECT_THAT(getDiagnosticString(),
2251 HasSubstr(make_message(
2252 "OpSpecConstantComposite Constituent <id> '5[%5]'s "
2253 "type does not match Result Type <id> "
2254 "'3[%_arr_uint_2]'s array element type.")));
2257 // Valid: Struct of {Int32,Int32,Int64}.
2258 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeStructGood
) {
2259 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2262 %3 = OpTypeStruct %1 %1 %2
2263 %4 = OpConstant %1 42
2264 %5 = OpSpecConstant %2 4300000000
2265 %6 = OpSpecConstantComposite %3 %4 %4 %5)";
2266 CompileSuccessfully(spirv
.c_str());
2267 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2270 // Invalid: missing one int32 struct member.
2271 TEST_P(ValidateIdWithMessage
,
2272 OpSpecConstantCompositeStructMissingComponentBad
) {
2273 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2275 %3 = OpTypeStruct %1 %1 %1
2276 %4 = OpConstant %1 42
2277 %5 = OpSpecConstant %1 430
2278 %6 = OpSpecConstantComposite %3 %4 %5)";
2279 CompileSuccessfully(spirv
.c_str());
2280 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2282 getDiagnosticString(),
2283 HasSubstr(make_message("OpSpecConstantComposite Constituent <id> "
2284 "'2[%_struct_2]' count does not match Result Type "
2285 "<id> '2[%_struct_2]'s struct member count.")));
2288 // Valid: Struct uses Undef-int64.
2289 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeStructUndefGood
) {
2290 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2293 %3 = OpTypeStruct %1 %1 %2
2294 %4 = OpSpecConstant %1 42
2296 %6 = OpSpecConstantComposite %3 %4 %4 %5)";
2297 CompileSuccessfully(spirv
.c_str());
2298 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2301 // Invalid: Composite contains non-const/undef component.
2302 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeStructNonConstBad
) {
2303 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2306 %3 = OpTypeStruct %1 %1 %2
2307 %4 = OpSpecConstant %1 42
2309 %6 = OpTypePointer Uniform %1
2310 %7 = OpVariable %6 Uniform
2311 %8 = OpSpecConstantComposite %3 %4 %7 %5)";
2312 CompileSuccessfully(spirv
.c_str());
2313 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2314 EXPECT_THAT(getDiagnosticString(),
2315 HasSubstr(make_message(
2316 "OpSpecConstantComposite Constituent <id> '7[%7]' is "
2317 "not a constant or undef.")));
2320 // Invalid: Struct component type does not match expected specialization type.
2321 // Second component was expected to be Int32, but got Int64.
2322 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeStructMemberTypeBad
) {
2323 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2326 %3 = OpTypeStruct %1 %1 %2
2327 %4 = OpConstant %1 42
2328 %5 = OpSpecConstant %2 4300000000
2329 %6 = OpSpecConstantComposite %3 %4 %5 %4)";
2330 CompileSuccessfully(spirv
.c_str());
2331 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2332 EXPECT_THAT(getDiagnosticString(),
2333 HasSubstr(make_message(
2334 "OpSpecConstantComposite Constituent <id> '5[%5]' type "
2335 "does not match the Result Type <id> '3[%_struct_3]'s "
2339 // Invalid: Undef-int64 used when Int32 was expected.
2340 TEST_P(ValidateIdWithMessage
, OpSpecConstantCompositeStructMemberUndefTypeBad
) {
2341 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2344 %3 = OpTypeStruct %1 %1 %2
2345 %4 = OpSpecConstant %1 42
2347 %6 = OpSpecConstantComposite %3 %4 %5 %4)";
2348 CompileSuccessfully(spirv
.c_str());
2349 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2350 EXPECT_THAT(getDiagnosticString(),
2351 HasSubstr(make_message(
2352 "OpSpecConstantComposite Constituent <id> '5[%5]' type "
2353 "does not match the Result Type <id> '3[%_struct_3]'s "
2357 // TODO: OpSpecConstantOp
2359 TEST_P(ValidateIdWithMessage
, OpVariableGood
) {
2360 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2362 %2 = OpTypePointer Input %1
2363 %3 = OpVariable %2 Input)";
2364 CompileSuccessfully(spirv
.c_str());
2365 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2367 TEST_P(ValidateIdWithMessage
, OpVariableInitializerConstantGood
) {
2368 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2370 %2 = OpTypePointer Output %1
2371 %3 = OpConstant %1 42
2372 %4 = OpVariable %2 Output %3)";
2373 CompileSuccessfully(spirv
.c_str());
2374 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2376 TEST_P(ValidateIdWithMessage
, OpVariableInitializerGlobalVariableGood
) {
2377 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2379 %2 = OpTypePointer Uniform %1
2380 %3 = OpVariable %2 Uniform
2381 %4 = OpTypePointer Private %2 ; pointer to pointer
2382 %5 = OpVariable %4 Private %3
2384 CompileSuccessfully(spirv
.c_str());
2385 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2387 // TODO: Positive test OpVariable with OpConstantNull of OpTypePointer
2388 TEST_P(ValidateIdWithMessage
, OpVariableResultTypeBad
) {
2389 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2391 %2 = OpVariable %1 Input)";
2392 CompileSuccessfully(spirv
.c_str());
2393 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2394 EXPECT_THAT(getDiagnosticString(),
2395 HasSubstr(make_message(
2396 "OpVariable Result Type <id> '1[%uint]' is not a pointer "
2399 TEST_P(ValidateIdWithMessage
, OpVariableInitializerIsTypeBad
) {
2400 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2402 %2 = OpTypePointer Input %1
2403 %3 = OpVariable %2 Input %2)";
2404 CompileSuccessfully(spirv
.c_str());
2405 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2406 EXPECT_THAT(getDiagnosticString(),
2407 HasSubstr(make_message("Operand '2[%_ptr_Input_uint]' "
2408 "cannot be a type")));
2411 TEST_P(ValidateIdWithMessage
, OpVariableInitializerIsFunctionVarBad
) {
2412 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2413 %int = OpTypeInt 32 0
2414 %ptrint = OpTypePointer Function %int
2415 %ptrptrint = OpTypePointer Function %ptrint
2417 %fnty = OpTypeFunction %void
2418 %main = OpFunction %void None %fnty
2420 %var = OpVariable %ptrint Function
2421 %varinit = OpVariable %ptrptrint Function %var ; Can't initialize function variable.
2425 CompileSuccessfully(spirv
.c_str());
2426 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2427 EXPECT_THAT(getDiagnosticString(),
2428 HasSubstr("Variable Initializer <id> '8[%8]' is not a constant "
2429 "or module-scope variable"));
2432 TEST_P(ValidateIdWithMessage
, OpVariableInitializerIsModuleVarGood
) {
2433 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2434 %int = OpTypeInt 32 0
2435 %ptrint = OpTypePointer Uniform %int
2436 %mvar = OpVariable %ptrint Uniform
2437 %ptrptrint = OpTypePointer Function %ptrint
2439 %fnty = OpTypeFunction %void
2440 %main = OpFunction %void None %fnty
2442 %goodvar = OpVariable %ptrptrint Function %mvar ; This is ok
2446 CompileSuccessfully(spirv
.c_str());
2447 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2450 TEST_P(ValidateIdWithMessage
, OpVariableContainsBoolBad
) {
2451 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2453 %int = OpTypeInt 32 0
2454 %block = OpTypeStruct %bool %int
2455 %_ptr_Uniform_block = OpTypePointer Uniform %block
2456 %var = OpVariable %_ptr_Uniform_block Uniform
2458 %fnty = OpTypeFunction %void
2459 %main = OpFunction %void None %fnty
2461 %load = OpLoad %block %var
2465 CompileSuccessfully(spirv
.c_str());
2466 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2468 getDiagnosticString(),
2469 HasSubstr(make_message(
2470 "If OpTypeBool is stored in conjunction with OpVariable, it can only "
2471 "be used with non-externally visible shader Storage Classes: "
2472 "Workgroup, CrossWorkgroup, Private, Function, Input, Output, "
2473 "RayPayloadKHR, IncomingRayPayloadKHR, HitAttributeKHR, "
2474 "CallableDataKHR, IncomingCallableDataKHR, NodePayloadAMDX, or "
2475 "UniformConstant")));
2478 TEST_P(ValidateIdWithMessage
, OpVariableContainsBoolPrivateGood
) {
2479 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2481 %int = OpTypeInt 32 0
2482 %block = OpTypeStruct %bool %int
2483 %_ptr_Private_block = OpTypePointer Private %block
2484 %var = OpVariable %_ptr_Private_block Private
2486 %fnty = OpTypeFunction %void
2487 %main = OpFunction %void None %fnty
2489 %load = OpLoad %block %var
2493 CompileSuccessfully(spirv
.c_str());
2494 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2497 TEST_P(ValidateIdWithMessage
, OpVariableContainsBoolUniformConstantGood
) {
2498 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2500 %int = OpTypeInt 32 0
2501 %block = OpTypeStruct %bool %int
2502 %_ptr_UniformConstant_block = OpTypePointer UniformConstant %block
2503 %var = OpVariable %_ptr_UniformConstant_block UniformConstant
2505 %fnty = OpTypeFunction %void
2506 %main = OpFunction %void None %fnty
2508 %load = OpLoad %block %var
2512 CompileSuccessfully(spirv
.c_str());
2513 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2516 TEST_P(ValidateIdWithMessage
, OpVariableContainsBoolPointerGood
) {
2517 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2519 %boolptr = OpTypePointer Uniform %bool
2520 %int = OpTypeInt 32 0
2521 %block = OpTypeStruct %boolptr %int
2522 %_ptr_Uniform_block = OpTypePointer Uniform %block
2523 %var = OpVariable %_ptr_Uniform_block Uniform
2525 %fnty = OpTypeFunction %void
2526 %main = OpFunction %void None %fnty
2528 %load = OpLoad %block %var
2532 CompileSuccessfully(spirv
.c_str());
2533 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2536 TEST_P(ValidateIdWithMessage
, OpVariableContainsBuiltinBoolGood
) {
2537 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2538 OpMemberDecorate %input 0 BuiltIn FrontFacing
2540 %input = OpTypeStruct %bool
2541 %_ptr_input = OpTypePointer Input %input
2542 %var = OpVariable %_ptr_input Input
2544 %fnty = OpTypeFunction %void
2545 %main = OpFunction %void None %fnty
2547 %load = OpLoad %input %var
2551 CompileSuccessfully(spirv
.c_str());
2552 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2555 TEST_P(ValidateIdWithMessage
, OpVariableContainsNoBuiltinBoolBad
) {
2556 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2558 %input = OpTypeStruct %bool
2559 %_ptr_input = OpTypePointer Input %input
2560 %var = OpVariable %_ptr_input Input
2562 %fnty = OpTypeFunction %void
2563 %main = OpFunction %void None %fnty
2565 %load = OpLoad %input %var
2569 CompileSuccessfully(spirv
.c_str());
2570 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2572 getDiagnosticString(),
2573 HasSubstr(make_message(
2574 "If OpTypeBool is stored in conjunction with OpVariable using Input "
2575 "or Output Storage Classes it requires a BuiltIn decoration")));
2578 TEST_P(ValidateIdWithMessage
, OpVariableContainsNoBuiltinBoolBadVulkan
) {
2579 std::string spirv
= R
"(
2581 OpMemoryModel Logical GLSL450
2582 OpEntryPoint Fragment %main "main
" %var
2583 OpExecutionMode %main OriginUpperLeft
2585 %input = OpTypeStruct %bool
2586 %_ptr_input = OpTypePointer Input %input
2587 %var = OpVariable %_ptr_input Input
2589 %fnty = OpTypeFunction %void
2590 %main = OpFunction %void None %fnty
2592 %load = OpLoad %input %var
2596 CompileSuccessfully(spirv
.c_str(), SPV_ENV_VULKAN_1_0
);
2597 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_VULKAN_1_0
));
2598 EXPECT_THAT(getDiagnosticString(),
2599 AnyVUID("VUID-StandaloneSpirv-Input-07290"));
2601 getDiagnosticString(),
2602 HasSubstr(make_message(
2603 "If OpTypeBool is stored in conjunction with OpVariable using Input "
2604 "or Output Storage Classes it requires a BuiltIn decoration")));
2607 TEST_P(ValidateIdWithMessage
, OpVariableContainsRayPayloadBoolGood
) {
2608 std::string spirv
= R
"(
2609 OpCapability RayTracingNV
2611 OpCapability Linkage
2612 OpExtension "SPV_NV_ray_tracing
"
2613 OpMemoryModel Logical GLSL450
2615 %PerRayData = OpTypeStruct %bool
2616 %_ptr_PerRayData = OpTypePointer RayPayloadNV %PerRayData
2617 %var = OpVariable %_ptr_PerRayData RayPayloadNV
2619 %fnty = OpTypeFunction %void
2620 %main = OpFunction %void None %fnty
2622 %load = OpLoad %PerRayData %var
2626 CompileSuccessfully(spirv
.c_str());
2627 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2630 TEST_P(ValidateIdWithMessage
, OpVariablePointerNoVariablePointersBad
) {
2631 const std::string spirv
= R
"(
2633 OpCapability Linkage
2634 OpMemoryModel Logical GLSL450
2636 %int = OpTypeInt 32 0
2637 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2638 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2639 %voidfn = OpTypeFunction %void
2640 %func = OpFunction %void None %voidfn
2642 %var = OpVariable %_ptr_function_ptr Function
2647 CompileSuccessfully(spirv
);
2648 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2650 getDiagnosticString(),
2651 HasSubstr(make_message(
2652 "In Logical addressing, variables may not allocate a pointer type")));
2655 TEST_P(ValidateIdWithMessage
,
2656 OpVariablePointerNoVariablePointersRelaxedLogicalGood
) {
2657 const std::string spirv
= R
"(
2659 OpCapability Linkage
2660 OpMemoryModel Logical GLSL450
2662 %int = OpTypeInt 32 0
2663 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2664 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2665 %voidfn = OpTypeFunction %void
2666 %func = OpFunction %void None %voidfn
2668 %var = OpVariable %_ptr_function_ptr Function
2673 auto options
= getValidatorOptions();
2674 options
->relax_logical_pointer
= true;
2675 CompileSuccessfully(spirv
);
2676 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2679 TEST_P(ValidateIdWithMessage
, OpFunctionWithNonMemoryObject
) {
2680 // DXC generates code that looks like when given something like:
2683 // This needs to be accepted before legalization takes place, so we
2684 // will include it with the relaxed logical pointer.
2686 const std::string spirv
= R
"(
2688 OpMemoryModel Logical GLSL450
2689 OpEntryPoint Vertex %1 "main
"
2691 %int = OpTypeInt 32 1
2692 %int_0 = OpConstant %int 0
2694 %9 = OpTypeFunction %void
2695 %_struct_5 = OpTypeStruct
2696 %_struct_6 = OpTypeStruct %_struct_5
2697 %_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
2698 %_ptr_Function__struct_5 = OpTypePointer Function %_struct_5
2699 %23 = OpTypeFunction %void %_ptr_Function__struct_5
2700 %1 = OpFunction %void None %9
2702 %11 = OpVariable %_ptr_Function__struct_6 Function
2703 %20 = OpAccessChain %_ptr_Function__struct_5 %11 %int_0
2704 %21 = OpFunctionCall %void %12 %20
2707 %12 = OpFunction %void None %23
2708 %13 = OpFunctionParameter %_ptr_Function__struct_5
2714 auto options
= getValidatorOptions();
2715 options
->relax_logical_pointer
= true;
2716 CompileSuccessfully(spirv
);
2717 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2720 TEST_P(ValidateIdWithMessage
,
2721 OpVariablePointerVariablePointersStorageBufferGood
) {
2722 const std::string spirv
= R
"(
2724 OpCapability Linkage
2725 OpCapability VariablePointersStorageBuffer
2726 OpExtension "SPV_KHR_variable_pointers
"
2727 OpMemoryModel Logical GLSL450
2729 %int = OpTypeInt 32 0
2730 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2731 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2732 %voidfn = OpTypeFunction %void
2733 %func = OpFunction %void None %voidfn
2735 %var = OpVariable %_ptr_function_ptr Function
2740 CompileSuccessfully(spirv
);
2741 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2744 TEST_P(ValidateIdWithMessage
, OpVariablePointerVariablePointersGood
) {
2745 const std::string spirv
= R
"(
2747 OpCapability Linkage
2748 OpCapability VariablePointers
2749 OpExtension "SPV_KHR_variable_pointers
"
2750 OpMemoryModel Logical GLSL450
2752 %int = OpTypeInt 32 0
2753 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2754 %_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2755 %voidfn = OpTypeFunction %void
2756 %func = OpFunction %void None %voidfn
2758 %var = OpVariable %_ptr_function_ptr Function
2763 CompileSuccessfully(spirv
);
2764 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2767 TEST_P(ValidateIdWithMessage
, OpVariablePointerVariablePointersBad
) {
2768 const std::string spirv
= R
"(
2770 OpCapability VariablePointers
2771 OpExtension "SPV_KHR_variable_pointers
"
2772 OpMemoryModel Logical GLSL450
2774 %int = OpTypeInt 32 0
2775 %_ptr_workgroup_int = OpTypePointer Workgroup %int
2776 %_ptr_uniform_ptr = OpTypePointer Uniform %_ptr_workgroup_int
2777 %var = OpVariable %_ptr_uniform_ptr Uniform
2780 CompileSuccessfully(spirv
);
2781 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2782 EXPECT_THAT(getDiagnosticString(),
2783 HasSubstr(make_message(
2784 "In Logical addressing with variable pointers, "
2785 "variables that allocate pointers must be in Function "
2786 "or Private storage classes")));
2789 TEST_P(ValidateIdWithMessage
, OpLoadGood
) {
2790 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2793 %3 = OpTypePointer UniformConstant %2
2794 %4 = OpTypeFunction %1
2795 %5 = OpVariable %3 UniformConstant
2796 %6 = OpFunction %1 None %4
2802 CompileSuccessfully(spirv
.c_str());
2803 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2806 // TODO: Add tests that exercise VariablePointersStorageBuffer instead of
2807 // VariablePointers.
2808 void createVariablePointerSpirvProgram(std::ostringstream
* spirv
,
2809 std::string result_strategy
,
2810 bool use_varptr_cap
,
2811 bool add_helper_function
) {
2812 *spirv
<< "OpCapability Shader ";
2813 if (use_varptr_cap
) {
2814 *spirv
<< "OpCapability VariablePointers ";
2815 *spirv
<< "OpExtension \"SPV_KHR_variable_pointers\" ";
2817 *spirv
<< "OpExtension \"SPV_KHR_storage_buffer_storage_class\" ";
2819 OpMemoryModel Logical GLSL450
2820 OpEntryPoint GLCompute %main "main
"
2822 %voidf = OpTypeFunction %void
2824 %i32 = OpTypeInt 32 1
2825 %f32 = OpTypeFloat 32
2826 %f32ptr = OpTypePointer StorageBuffer %f32
2827 %i = OpConstant %i32 1
2828 %zero = OpConstant %i32 0
2829 %float_1 = OpConstant %f32 1.0
2830 %ptr1 = OpVariable %f32ptr StorageBuffer
2831 %ptr2 = OpVariable %f32ptr StorageBuffer
2833 if (add_helper_function
) {
2835 ; ////////////////////////////////////////////////////////////
2836 ;;;; Function that returns a pointer
2837 ; ////////////////////////////////////////////////////////////
2838 %selector_func_type = OpTypeFunction %f32ptr %bool %f32ptr %f32ptr
2839 %choose_input_func = OpFunction %f32ptr None %selector_func_type
2840 %is_neg_param = OpFunctionParameter %bool
2841 %first_ptr_param = OpFunctionParameter %f32ptr
2842 %second_ptr_param = OpFunctionParameter %f32ptr
2843 %selector_func_begin = OpLabel
2844 %result_ptr = OpSelect %f32ptr %is_neg_param %first_ptr_param %second_ptr_param
2845 OpReturnValue %result_ptr
2850 %main = OpFunction %void None %voidf
2853 *spirv
<< result_strategy
;
2860 // With the VariablePointer Capability, OpLoad should allow loading a
2861 // VaiablePointer. In this test the variable pointer is obtained by an OpSelect
2862 TEST_P(ValidateIdWithMessage
, OpLoadVarPtrOpSelectGood
) {
2863 std::string result_strategy
= R
"(
2864 %isneg = OpSLessThan %bool %i %zero
2865 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
2866 %result = OpLoad %f32 %varptr
2869 std::ostringstream spirv
;
2870 createVariablePointerSpirvProgram(&spirv
, result_strategy
,
2871 true /* Add VariablePointers Capability? */,
2872 false /* Use Helper Function? */);
2873 CompileSuccessfully(spirv
.str());
2874 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2877 // Without the VariablePointers Capability, OpLoad will not allow loading
2878 // through a variable pointer.
2879 // Disabled since using OpSelect with pointers without VariablePointers will
2880 // fail LogicalsPass.
2881 TEST_P(ValidateIdWithMessage
, DISABLED_OpLoadVarPtrOpSelectBad
) {
2882 std::string result_strategy
= R
"(
2883 %isneg = OpSLessThan %bool %i %zero
2884 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
2885 %result = OpLoad %f32 %varptr
2888 std::ostringstream spirv
;
2889 createVariablePointerSpirvProgram(&spirv
, result_strategy
,
2890 false /* Add VariablePointers Capability?*/,
2891 false /* Use Helper Function? */);
2892 CompileSuccessfully(spirv
.str());
2893 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2894 EXPECT_THAT(getDiagnosticString(),
2895 HasSubstr(make_message("is not a logical pointer.")));
2898 // With the VariablePointer Capability, OpLoad should allow loading a
2899 // VaiablePointer. In this test the variable pointer is obtained by an OpPhi
2900 TEST_P(ValidateIdWithMessage
, OpLoadVarPtrOpPhiGood
) {
2901 std::string result_strategy
= R
"(
2902 %is_neg = OpSLessThan %bool %i %zero
2903 OpSelectionMerge %end_label None
2904 OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2
2905 %take_ptr_1 = OpLabel
2907 %take_ptr_2 = OpLabel
2909 %end_label = OpLabel
2910 %varptr = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2
2911 %result = OpLoad %f32 %varptr
2914 std::ostringstream spirv
;
2915 createVariablePointerSpirvProgram(&spirv
, result_strategy
,
2916 true /* Add VariablePointers Capability?*/,
2917 false /* Use Helper Function? */);
2918 CompileSuccessfully(spirv
.str());
2919 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2922 // Without the VariablePointers Capability, OpPhi can have a pointer result
2924 TEST_P(ValidateIdWithMessage
, OpPhiBad
) {
2925 std::string result_strategy
= R
"(
2926 %is_neg = OpSLessThan %bool %i %zero
2927 OpSelectionMerge %end_label None
2928 OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2
2929 %take_ptr_1 = OpLabel
2931 %take_ptr_2 = OpLabel
2933 %end_label = OpLabel
2934 %varptr = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2
2935 %result = OpLoad %f32 %varptr
2938 std::ostringstream spirv
;
2939 createVariablePointerSpirvProgram(&spirv
, result_strategy
,
2940 false /* Add VariablePointers Capability?*/,
2941 false /* Use Helper Function? */);
2942 CompileSuccessfully(spirv
.str());
2943 EXPECT_EQ(SPV_ERROR_INVALID_DATA
, ValidateInstructions());
2944 EXPECT_THAT(getDiagnosticString(),
2945 HasSubstr(make_message(
2946 "Using pointers with OpPhi requires capability "
2947 "VariablePointers or VariablePointersStorageBuffer")));
2950 // With the VariablePointer Capability, OpLoad should allow loading through a
2951 // VaiablePointer. In this test the variable pointer is obtained from an
2952 // OpFunctionCall (return value from a function)
2953 TEST_P(ValidateIdWithMessage
, OpLoadVarPtrOpFunctionCallGood
) {
2954 std::ostringstream spirv
;
2955 std::string result_strategy
= R
"(
2956 %isneg = OpSLessThan %bool %i %zero
2957 %varptr = OpFunctionCall %f32ptr %choose_input_func %isneg %ptr1 %ptr2
2958 %result = OpLoad %f32 %varptr
2961 createVariablePointerSpirvProgram(&spirv
, result_strategy
,
2962 true /* Add VariablePointers Capability?*/,
2963 true /* Use Helper Function? */);
2964 CompileSuccessfully(spirv
.str());
2965 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
2968 TEST_P(ValidateIdWithMessage
, OpLoadResultTypeBad
) {
2969 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2972 %3 = OpTypePointer UniformConstant %2
2973 %4 = OpTypeFunction %1
2974 %5 = OpVariable %3 UniformConstant
2975 %6 = OpFunction %1 None %4
2981 CompileSuccessfully(spirv
.c_str());
2982 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
2984 getDiagnosticString(),
2985 HasSubstr(make_message("OpLoad Result Type <id> "
2986 "'3[%_ptr_UniformConstant_uint]' does not match "
2987 "Pointer <id> '5[%5]'s type.")));
2990 TEST_P(ValidateIdWithMessage
, OpLoadPointerBad
) {
2991 std::string spirv
= kGLSL450MemoryModel
+ R
"(
2994 %3 = OpTypePointer UniformConstant %2
2995 %4 = OpTypeFunction %1
2996 %5 = OpFunction %1 None %4
3002 CompileSuccessfully(spirv
.c_str());
3003 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3004 // Prove that SSA checks trigger for a bad Id value.
3005 // The next test case show the not-a-logical-pointer case.
3006 EXPECT_THAT(getDiagnosticString(),
3007 HasSubstr(make_message("ID '8[%8]' has not been "
3011 // Disabled as bitcasting type to object is now not valid.
3012 TEST_P(ValidateIdWithMessage
, DISABLED_OpLoadLogicalPointerBad
) {
3013 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3017 %4 = OpTypePointer UniformConstant %2
3018 %5 = OpTypePointer UniformConstant %3
3019 %6 = OpTypeFunction %1
3020 %7 = OpFunction %1 None %6
3022 %9 = OpBitcast %5 %4 ; Not valid in logical addressing
3023 %10 = OpLoad %3 %9 ; Should trigger message
3027 CompileSuccessfully(spirv
.c_str());
3028 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3029 // Once we start checking bitcasts, we might catch that
3030 // as the error first, instead of catching it here.
3031 // I don't know if it's possible to generate a bad case
3032 // if/when the validator is complete.
3033 EXPECT_THAT(getDiagnosticString(),
3034 HasSubstr(make_message(
3035 "OpLoad Pointer <id> '9' is not a logical pointer.")));
3038 TEST_P(ValidateIdWithMessage
, OpStoreGood
) {
3039 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3042 %3 = OpTypePointer Uniform %2
3043 %4 = OpTypeFunction %1
3044 %5 = OpConstant %2 42
3045 %6 = OpVariable %3 Uniform
3046 %7 = OpFunction %1 None %4
3051 CompileSuccessfully(spirv
.c_str());
3052 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3054 TEST_P(ValidateIdWithMessage
, OpStorePointerBad
) {
3055 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3058 %3 = OpTypePointer UniformConstant %2
3059 %4 = OpTypeFunction %1
3060 %5 = OpConstant %2 42
3061 %6 = OpVariable %3 UniformConstant
3062 %7 = OpConstant %2 0
3063 %8 = OpFunction %1 None %4
3068 CompileSuccessfully(spirv
.c_str());
3069 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3070 EXPECT_THAT(getDiagnosticString(),
3071 HasSubstr(make_message(
3072 "OpStore Pointer <id> '7[%uint_0]' is not a logical "
3076 // Disabled as bitcasting type to object is now not valid.
3077 TEST_P(ValidateIdWithMessage
, DISABLED_OpStoreLogicalPointerBad
) {
3078 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3082 %4 = OpTypePointer UniformConstant %2
3083 %5 = OpTypePointer UniformConstant %3
3084 %6 = OpTypeFunction %1
3085 %7 = OpConstantNull %5
3086 %8 = OpFunction %1 None %6
3088 %10 = OpBitcast %5 %4 ; Not valid in logical addressing
3089 %11 = OpStore %10 %7 ; Should trigger message
3093 CompileSuccessfully(spirv
.c_str());
3094 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3095 EXPECT_THAT(getDiagnosticString(),
3096 HasSubstr(make_message(
3097 "OpStore Pointer <id> '10' is not a logical pointer.")));
3100 // Without the VariablePointer Capability, OpStore should may not store
3101 // through a variable pointer.
3102 // Disabled since using OpSelect with pointers without VariablePointers will
3103 // fail LogicalsPass.
3104 TEST_P(ValidateIdWithMessage
, DISABLED_OpStoreVarPtrBad
) {
3105 std::string result_strategy
= R
"(
3106 %isneg = OpSLessThan %bool %i %zero
3107 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
3108 OpStore %varptr %float_1
3111 std::ostringstream spirv
;
3112 createVariablePointerSpirvProgram(
3113 &spirv
, result_strategy
, false /* Add VariablePointers Capability? */,
3114 false /* Use Helper Function? */);
3115 CompileSuccessfully(spirv
.str());
3116 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3117 EXPECT_THAT(getDiagnosticString(),
3118 HasSubstr(make_message("is not a logical pointer.")));
3121 // With the VariablePointer Capability, OpStore should allow storing through a
3122 // variable pointer.
3123 TEST_P(ValidateIdWithMessage
, OpStoreVarPtrGood
) {
3124 std::string result_strategy
= R
"(
3125 %isneg = OpSLessThan %bool %i %zero
3126 %varptr = OpSelect %f32ptr %isneg %ptr1 %ptr2
3127 OpStore %varptr %float_1
3130 std::ostringstream spirv
;
3131 createVariablePointerSpirvProgram(&spirv
, result_strategy
,
3132 true /* Add VariablePointers Capability? */,
3133 false /* Use Helper Function? */);
3134 CompileSuccessfully(spirv
.str());
3135 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3138 TEST_P(ValidateIdWithMessage
, OpStoreObjectGood
) {
3139 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3142 %3 = OpTypePointer Uniform %2
3143 %4 = OpTypeFunction %1
3144 %5 = OpConstant %2 42
3145 %6 = OpVariable %3 Uniform
3146 %7 = OpFunction %1 None %4
3148 %9 = OpFunctionCall %1 %10
3152 %10 = OpFunction %1 None %4
3156 CompileSuccessfully(spirv
.c_str());
3157 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3159 getDiagnosticString(),
3160 HasSubstr(make_message("OpStore Object <id> '9[%9]'s type is void.")));
3162 TEST_P(ValidateIdWithMessage
, OpStoreTypeBad
) {
3163 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3167 %3 = OpTypePointer Uniform %2
3168 %4 = OpTypeFunction %1
3169 %5 = OpConstant %9 3.14
3170 %6 = OpVariable %3 Uniform
3171 %7 = OpFunction %1 None %4
3176 CompileSuccessfully(spirv
.c_str());
3177 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3178 EXPECT_THAT(getDiagnosticString(),
3179 HasSubstr(make_message(
3180 "OpStore Pointer <id> '7[%7]'s type does not match "
3181 "Object <id> '6[%float_3_1400001]'s type.")));
3184 // The next series of test check test a relaxation of the rules for stores to
3185 // structs. The first test checks that we get a failure when the option is not
3186 // set to relax the rule.
3187 // TODO: Add tests for layout compatible arrays and matricies when the validator
3188 // relaxes the rules for them as well. Also need test to check for layout
3189 // decorations specific to those types.
3190 TEST_P(ValidateIdWithMessage
, OpStoreTypeBadStruct
) {
3191 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3192 OpMemberDecorate %1 0 Offset 0
3193 OpMemberDecorate %1 1 Offset 4
3194 OpMemberDecorate %2 0 Offset 0
3195 OpMemberDecorate %2 1 Offset 4
3198 %1 = OpTypeStruct %4 %4
3199 %5 = OpTypePointer Uniform %1
3200 %2 = OpTypeStruct %4 %4
3201 %6 = OpTypeFunction %3
3202 %7 = OpConstant %4 3.14
3203 %8 = OpVariable %5 Uniform
3204 %9 = OpFunction %3 None %6
3206 %11 = OpCompositeConstruct %2 %7 %7
3210 CompileSuccessfully(spirv
.c_str());
3211 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3212 EXPECT_THAT(getDiagnosticString(),
3213 HasSubstr(make_message(
3214 "OpStore Pointer <id> '8[%8]'s type does not match "
3215 "Object <id> '11[%11]'s type.")));
3218 // Same code as the last test. The difference is that we relax the rule.
3219 // Because the structs %3 and %5 are defined the same way.
3220 TEST_P(ValidateIdWithMessage
, OpStoreTypeRelaxedStruct
) {
3221 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3222 OpMemberDecorate %1 0 Offset 0
3223 OpMemberDecorate %1 1 Offset 4
3224 OpMemberDecorate %2 0 Offset 0
3225 OpMemberDecorate %2 1 Offset 4
3228 %1 = OpTypeStruct %4 %4
3229 %5 = OpTypePointer Uniform %1
3230 %2 = OpTypeStruct %4 %4
3231 %6 = OpTypeFunction %3
3232 %7 = OpConstant %4 3.14
3233 %8 = OpVariable %5 Uniform
3234 %9 = OpFunction %3 None %6
3236 %11 = OpCompositeConstruct %2 %7 %7
3240 spvValidatorOptionsSetRelaxStoreStruct(options_
, true);
3241 CompileSuccessfully(spirv
.c_str());
3242 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3245 // Same code as the last test except for an extra decoration on one of the
3246 // members. With the relaxed rules, the code is still valid.
3247 TEST_P(ValidateIdWithMessage
, OpStoreTypeRelaxedStructWithExtraDecoration
) {
3248 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3249 OpMemberDecorate %1 0 Offset 0
3250 OpMemberDecorate %1 1 Offset 4
3251 OpMemberDecorate %1 0 RelaxedPrecision
3252 OpMemberDecorate %2 0 Offset 0
3253 OpMemberDecorate %2 1 Offset 4
3256 %1 = OpTypeStruct %4 %4
3257 %5 = OpTypePointer Uniform %1
3258 %2 = OpTypeStruct %4 %4
3259 %6 = OpTypeFunction %3
3260 %7 = OpConstant %4 3.14
3261 %8 = OpVariable %5 Uniform
3262 %9 = OpFunction %3 None %6
3264 %11 = OpCompositeConstruct %2 %7 %7
3268 spvValidatorOptionsSetRelaxStoreStruct(options_
, true);
3269 CompileSuccessfully(spirv
.c_str());
3270 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3273 // This test check that we recursively traverse the struct to check if they are
3275 TEST_P(ValidateIdWithMessage
, OpStoreTypeRelaxedNestedStruct
) {
3276 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3277 OpMemberDecorate %1 0 Offset 0
3278 OpMemberDecorate %1 1 Offset 4
3279 OpMemberDecorate %2 0 Offset 0
3280 OpMemberDecorate %2 1 Offset 8
3281 OpMemberDecorate %3 0 Offset 0
3282 OpMemberDecorate %3 1 Offset 4
3283 OpMemberDecorate %4 0 Offset 0
3284 OpMemberDecorate %4 1 Offset 8
3288 %1 = OpTypeStruct %7 %6
3289 %2 = OpTypeStruct %1 %1
3290 %8 = OpTypePointer Uniform %2
3291 %3 = OpTypeStruct %7 %6
3292 %4 = OpTypeStruct %3 %3
3293 %9 = OpTypeFunction %5
3294 %10 = OpConstant %6 7
3295 %11 = OpConstant %7 3.14
3296 %12 = OpConstantComposite %3 %11 %10
3297 %13 = OpVariable %8 Uniform
3298 %14 = OpFunction %5 None %9
3300 %16 = OpCompositeConstruct %4 %12 %12
3304 spvValidatorOptionsSetRelaxStoreStruct(options_
, true);
3305 CompileSuccessfully(spirv
.c_str());
3306 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3309 // This test check that the even with the relaxed rules an error is identified
3310 // if the members of the struct are in a different order.
3311 TEST_P(ValidateIdWithMessage
, OpStoreTypeBadRelaxedStruct1
) {
3312 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3313 OpMemberDecorate %1 0 Offset 0
3314 OpMemberDecorate %1 1 Offset 4
3315 OpMemberDecorate %2 0 Offset 0
3316 OpMemberDecorate %2 1 Offset 8
3317 OpMemberDecorate %3 0 Offset 0
3318 OpMemberDecorate %3 1 Offset 4
3319 OpMemberDecorate %4 0 Offset 0
3320 OpMemberDecorate %4 1 Offset 8
3324 %1 = OpTypeStruct %6 %7
3325 %2 = OpTypeStruct %1 %1
3326 %8 = OpTypePointer Uniform %2
3327 %3 = OpTypeStruct %7 %6
3328 %4 = OpTypeStruct %3 %3
3329 %9 = OpTypeFunction %5
3330 %10 = OpConstant %6 7
3331 %11 = OpConstant %7 3.14
3332 %12 = OpConstantComposite %3 %11 %10
3333 %13 = OpVariable %8 Uniform
3334 %14 = OpFunction %5 None %9
3336 %16 = OpCompositeConstruct %4 %12 %12
3340 spvValidatorOptionsSetRelaxStoreStruct(options_
, true);
3341 CompileSuccessfully(spirv
.c_str());
3342 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3344 getDiagnosticString(),
3345 HasSubstr(make_message(
3346 "OpStore Pointer <id> '13[%13]'s layout does not match Object "
3347 "<id> '16[%16]'s layout.")));
3350 // This test check that the even with the relaxed rules an error is identified
3351 // if the members of the struct are at different offsets.
3352 TEST_P(ValidateIdWithMessage
, OpStoreTypeBadRelaxedStruct2
) {
3353 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3354 OpMemberDecorate %1 0 Offset 4
3355 OpMemberDecorate %1 1 Offset 0
3356 OpMemberDecorate %2 0 Offset 0
3357 OpMemberDecorate %2 1 Offset 8
3358 OpMemberDecorate %3 0 Offset 0
3359 OpMemberDecorate %3 1 Offset 4
3360 OpMemberDecorate %4 0 Offset 0
3361 OpMemberDecorate %4 1 Offset 8
3365 %1 = OpTypeStruct %7 %6
3366 %2 = OpTypeStruct %1 %1
3367 %8 = OpTypePointer Uniform %2
3368 %3 = OpTypeStruct %7 %6
3369 %4 = OpTypeStruct %3 %3
3370 %9 = OpTypeFunction %5
3371 %10 = OpConstant %6 7
3372 %11 = OpConstant %7 3.14
3373 %12 = OpConstantComposite %3 %11 %10
3374 %13 = OpVariable %8 Uniform
3375 %14 = OpFunction %5 None %9
3377 %16 = OpCompositeConstruct %4 %12 %12
3381 spvValidatorOptionsSetRelaxStoreStruct(options_
, true);
3382 CompileSuccessfully(spirv
.c_str());
3383 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3385 getDiagnosticString(),
3386 HasSubstr(make_message(
3387 "OpStore Pointer <id> '13[%13]'s layout does not match Object "
3388 "<id> '16[%16]'s layout.")));
3391 TEST_P(ValidateIdWithMessage
, OpStoreTypeRelaxedLogicalPointerReturnPointer
) {
3392 const std::string spirv
= R
"(
3394 OpCapability Linkage
3395 OpMemoryModel Logical GLSL450
3397 %2 = OpTypePointer Function %1
3398 %3 = OpTypeFunction %2 %2
3399 %4 = OpFunction %2 None %3
3400 %5 = OpFunctionParameter %2
3405 spvValidatorOptionsSetRelaxLogicalPointer(options_
, true);
3406 CompileSuccessfully(spirv
.c_str());
3407 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3410 TEST_P(ValidateIdWithMessage
, OpStoreTypeRelaxedLogicalPointerAllocPointer
) {
3411 const std::string spirv
= R
"(
3413 OpCapability Linkage
3414 OpMemoryModel Logical GLSL450
3417 %3 = OpTypeFunction %1 ; void(void)
3418 %4 = OpTypePointer Uniform %2 ; int*
3419 %5 = OpTypePointer Private %4 ; int** (Private)
3420 %6 = OpTypePointer Function %4 ; int** (Function)
3421 %7 = OpVariable %5 Private
3422 %8 = OpFunction %1 None %3
3424 %10 = OpVariable %6 Function
3428 spvValidatorOptionsSetRelaxLogicalPointer(options_
, true);
3429 CompileSuccessfully(spirv
.c_str());
3430 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3433 TEST_P(ValidateIdWithMessage
, OpStoreVoid
) {
3434 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3437 %3 = OpTypePointer Uniform %2
3438 %4 = OpTypeFunction %1
3439 %6 = OpVariable %3 Uniform
3440 %7 = OpFunction %1 None %4
3442 %9 = OpFunctionCall %1 %7
3446 CompileSuccessfully(spirv
.c_str());
3447 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3449 getDiagnosticString(),
3450 HasSubstr(make_message("OpStore Object <id> '8[%8]'s type is void.")));
3453 TEST_P(ValidateIdWithMessage
, OpStoreLabel
) {
3454 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3457 %3 = OpTypePointer Uniform %2
3458 %4 = OpTypeFunction %1
3459 %6 = OpVariable %3 Uniform
3460 %7 = OpFunction %1 None %4
3465 CompileSuccessfully(spirv
.c_str());
3466 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3467 EXPECT_THAT(getDiagnosticString(),
3468 HasSubstr(make_message("Operand '7[%7]' requires a type")));
3471 // TODO: enable when this bug is fixed:
3472 // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
3473 TEST_P(ValidateIdWithMessage
, DISABLED_OpStoreFunction
) {
3474 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3476 %3 = OpTypePointer UniformConstant %2
3477 %4 = OpTypeFunction %2
3478 %5 = OpConstant %2 123
3479 %6 = OpVariable %3 UniformConstant
3480 %7 = OpFunction %2 None %4
3485 CompileSuccessfully(spirv
.c_str());
3486 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3489 TEST_P(ValidateIdWithMessage
, OpStoreBuiltin
) {
3490 std::string spirv
= R
"(
3492 %1 = OpExtInstImport "GLSL
.std
.450"
3493 OpMemoryModel Logical GLSL450
3494 OpEntryPoint GLCompute %main "main
" %gl_GlobalInvocationID
3495 OpExecutionMode %main LocalSize 1 1 1
3499 OpName %gl_GlobalInvocationID "gl_GlobalInvocationID
"
3500 OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
3502 %int = OpTypeInt 32 1
3503 %uint = OpTypeInt 32 0
3504 %v3uint = OpTypeVector %uint 3
3505 %_ptr_Input_v3uint = OpTypePointer Input %v3uint
3506 %gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
3508 %zero = OpConstant %uint 0
3509 %v3uint_000 = OpConstantComposite %v3uint %zero %zero %zero
3512 %voidfunc = OpTypeFunction %void
3513 %main = OpFunction %void None %voidfunc
3516 OpStore %gl_GlobalInvocationID %v3uint_000
3522 CompileSuccessfully(spirv
.c_str());
3523 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3524 EXPECT_THAT(getDiagnosticString(),
3525 HasSubstr(make_message("storage class is read-only")));
3528 TEST_P(ValidateIdWithMessage
, OpCopyMemoryGood
) {
3529 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3532 %3 = OpTypePointer UniformConstant %2
3533 %4 = OpConstant %2 42
3534 %5 = OpVariable %3 UniformConstant %4
3535 %6 = OpTypePointer Function %2
3536 %7 = OpTypeFunction %1
3537 %8 = OpFunction %1 None %7
3539 %10 = OpVariable %6 Function
3540 OpCopyMemory %10 %5 None
3544 CompileSuccessfully(spirv
.c_str());
3545 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3548 TEST_P(ValidateIdWithMessage
, OpCopyMemoryNonPointerTarget
) {
3549 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3552 %3 = OpTypePointer Uniform %2
3553 %4 = OpTypeFunction %1 %2 %3
3554 %5 = OpFunction %1 None %4
3555 %6 = OpFunctionParameter %2
3556 %7 = OpFunctionParameter %3
3563 CompileSuccessfully(spirv
);
3564 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3566 getDiagnosticString(),
3567 HasSubstr(make_message("Target operand <id> '6[%6]' is not a pointer.")));
3570 TEST_P(ValidateIdWithMessage
, OpCopyMemoryNonPointerSource
) {
3571 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3574 %3 = OpTypePointer Uniform %2
3575 %4 = OpTypeFunction %1 %2 %3
3576 %5 = OpFunction %1 None %4
3577 %6 = OpFunctionParameter %2
3578 %7 = OpFunctionParameter %3
3585 CompileSuccessfully(spirv
);
3586 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3588 getDiagnosticString(),
3589 HasSubstr(make_message("Source operand <id> '6[%6]' is not a pointer.")));
3592 TEST_P(ValidateIdWithMessage
, OpCopyMemoryBad
) {
3593 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3596 %3 = OpTypePointer UniformConstant %2
3597 %4 = OpConstant %2 42
3598 %5 = OpVariable %3 UniformConstant %4
3599 %11 = OpTypeFloat 32
3600 %6 = OpTypePointer Function %11
3601 %7 = OpTypeFunction %1
3602 %8 = OpFunction %1 None %7
3604 %10 = OpVariable %6 Function
3605 OpCopyMemory %10 %5 None
3609 CompileSuccessfully(spirv
.c_str());
3610 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3611 EXPECT_THAT(getDiagnosticString(),
3612 HasSubstr(make_message("Target <id> '5[%5]'s type does not match "
3613 "Source <id> '2[%uint]'s type.")));
3616 TEST_P(ValidateIdWithMessage
, OpCopyMemoryVoidTarget
) {
3617 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3620 %3 = OpTypePointer Uniform %1
3621 %4 = OpTypePointer Uniform %2
3622 %5 = OpTypeFunction %1 %3 %4
3623 %6 = OpFunction %1 None %5
3624 %7 = OpFunctionParameter %3
3625 %8 = OpFunctionParameter %4
3632 CompileSuccessfully(spirv
);
3633 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3635 getDiagnosticString(),
3636 HasSubstr(make_message("Target operand <id> '7[%7]' cannot be a void "
3640 TEST_P(ValidateIdWithMessage
, OpCopyMemoryVoidSource
) {
3641 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3644 %3 = OpTypePointer Uniform %1
3645 %4 = OpTypePointer Uniform %2
3646 %5 = OpTypeFunction %1 %3 %4
3647 %6 = OpFunction %1 None %5
3648 %7 = OpFunctionParameter %3
3649 %8 = OpFunctionParameter %4
3656 CompileSuccessfully(spirv
);
3657 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3659 getDiagnosticString(),
3660 HasSubstr(make_message("Source operand <id> '7[%7]' cannot be a void "
3664 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedGood
) {
3665 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3668 %3 = OpTypePointer UniformConstant %2
3669 %4 = OpTypePointer Function %2
3670 %5 = OpConstant %2 4
3671 %6 = OpVariable %3 UniformConstant %5
3672 %7 = OpTypeFunction %1
3673 %8 = OpFunction %1 None %7
3675 %10 = OpVariable %4 Function
3676 OpCopyMemorySized %10 %6 %5 None
3679 CompileSuccessfully(spirv
.c_str());
3680 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3682 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedTargetBad
) {
3683 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3686 %3 = OpTypePointer UniformConstant %2
3687 %4 = OpTypePointer Function %2
3688 %5 = OpConstant %2 4
3689 %6 = OpVariable %3 UniformConstant %5
3690 %7 = OpTypeFunction %1
3691 %8 = OpFunction %1 None %7
3693 OpCopyMemorySized %5 %5 %5 None
3696 CompileSuccessfully(spirv
.c_str());
3697 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3698 EXPECT_THAT(getDiagnosticString(),
3699 HasSubstr(make_message(
3700 "Target operand <id> '5[%uint_4]' is not a pointer.")));
3702 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSourceBad
) {
3703 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3706 %3 = OpTypePointer UniformConstant %2
3707 %4 = OpTypePointer Function %2
3708 %5 = OpConstant %2 4
3709 %6 = OpTypeFunction %1
3710 %7 = OpFunction %1 None %6
3712 %9 = OpVariable %4 Function
3713 OpCopyMemorySized %9 %5 %5 None
3716 CompileSuccessfully(spirv
.c_str());
3717 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3718 EXPECT_THAT(getDiagnosticString(),
3719 HasSubstr(make_message(
3720 "Source operand <id> '5[%uint_4]' is not a pointer.")));
3722 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeBad
) {
3723 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3726 %3 = OpTypePointer UniformConstant %2
3727 %4 = OpTypePointer Function %2
3728 %5 = OpConstant %2 4
3729 %6 = OpVariable %3 UniformConstant %5
3730 %7 = OpTypeFunction %1
3731 %8 = OpFunction %1 None %7
3733 %10 = OpVariable %4 Function
3734 OpCopyMemorySized %10 %6 %6 None
3737 CompileSuccessfully(spirv
.c_str());
3738 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3739 EXPECT_THAT(getDiagnosticString(),
3740 HasSubstr(make_message(
3741 "Size operand <id> '6[%6]' must be a scalar integer type.")));
3743 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeTypeBad
) {
3744 std::string spirv
= kGLSL450MemoryModel
+ R
"(
3747 %3 = OpTypePointer UniformConstant %2
3748 %4 = OpTypePointer Function %2
3749 %5 = OpConstant %2 4
3750 %6 = OpVariable %3 UniformConstant %5
3751 %7 = OpTypeFunction %1
3752 %11 = OpTypeFloat 32
3753 %12 = OpConstant %11 1.0
3754 %8 = OpFunction %1 None %7
3756 %10 = OpVariable %4 Function
3757 OpCopyMemorySized %10 %6 %12 None
3760 CompileSuccessfully(spirv
.c_str());
3761 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3762 EXPECT_THAT(getDiagnosticString(),
3763 HasSubstr(make_message(
3764 "Size operand <id> '9[%float_1]' must be a scalar integer "
3768 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeConstantNull
) {
3769 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3772 %3 = OpConstantNull %2
3773 %4 = OpTypePointer Uniform %2
3775 %6 = OpTypePointer UniformConstant %5
3776 %7 = OpTypeFunction %1 %4 %6
3777 %8 = OpFunction %1 None %7
3778 %9 = OpFunctionParameter %4
3779 %10 = OpFunctionParameter %6
3781 OpCopyMemorySized %9 %10 %3
3786 CompileSuccessfully(spirv
);
3787 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3789 getDiagnosticString(),
3790 HasSubstr(make_message("Size operand <id> '3[%3]' cannot be a constant "
3794 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeConstantZero
) {
3795 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3798 %3 = OpConstant %2 0
3799 %4 = OpTypePointer Uniform %2
3801 %6 = OpTypePointer UniformConstant %5
3802 %7 = OpTypeFunction %1 %4 %6
3803 %8 = OpFunction %1 None %7
3804 %9 = OpFunctionParameter %4
3805 %10 = OpFunctionParameter %6
3807 OpCopyMemorySized %9 %10 %3
3812 CompileSuccessfully(spirv
);
3813 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3814 EXPECT_THAT(getDiagnosticString(),
3815 HasSubstr(make_message(
3816 "Size operand <id> '3[%uint_0]' cannot be a constant "
3820 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeConstantZero64
) {
3821 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3824 %3 = OpConstant %2 0
3825 %4 = OpTypePointer Uniform %2
3827 %6 = OpTypePointer UniformConstant %5
3828 %7 = OpTypeFunction %1 %4 %6
3829 %8 = OpFunction %1 None %7
3830 %9 = OpFunctionParameter %4
3831 %10 = OpFunctionParameter %6
3833 OpCopyMemorySized %9 %10 %3
3838 CompileSuccessfully(spirv
);
3839 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3840 EXPECT_THAT(getDiagnosticString(),
3841 HasSubstr(make_message(
3842 "Size operand <id> '3[%ulong_0]' cannot be a constant "
3846 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeConstantNegative
) {
3847 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
3850 %3 = OpConstant %2 -1
3851 %4 = OpTypePointer Uniform %2
3853 %6 = OpTypePointer UniformConstant %5
3854 %7 = OpTypeFunction %1 %4 %6
3855 %8 = OpFunction %1 None %7
3856 %9 = OpFunctionParameter %4
3857 %10 = OpFunctionParameter %6
3859 OpCopyMemorySized %9 %10 %3
3864 CompileSuccessfully(spirv
);
3865 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3866 EXPECT_THAT(getDiagnosticString(),
3867 HasSubstr(make_message(
3868 "Size operand <id> '3[%int_n1]' cannot have the sign bit set "
3872 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeConstantNegative64
) {
3873 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
3876 %3 = OpConstant %2 -1
3877 %4 = OpTypePointer Uniform %2
3879 %6 = OpTypePointer UniformConstant %5
3880 %7 = OpTypeFunction %1 %4 %6
3881 %8 = OpFunction %1 None %7
3882 %9 = OpFunctionParameter %4
3883 %10 = OpFunctionParameter %6
3885 OpCopyMemorySized %9 %10 %3
3890 CompileSuccessfully(spirv
);
3891 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
3893 getDiagnosticString(),
3894 HasSubstr(make_message(
3895 "Size operand <id> '3[%long_n1]' cannot have the sign bit set "
3899 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeUnsignedNegative
) {
3900 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3903 %3 = OpConstant %2 2147483648
3904 %4 = OpTypePointer Uniform %2
3906 %6 = OpTypePointer UniformConstant %5
3907 %7 = OpTypeFunction %1 %4 %6
3908 %8 = OpFunction %1 None %7
3909 %9 = OpFunctionParameter %4
3910 %10 = OpFunctionParameter %6
3912 OpCopyMemorySized %9 %10 %3
3917 CompileSuccessfully(spirv
);
3918 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3921 TEST_P(ValidateIdWithMessage
, OpCopyMemorySizedSizeUnsignedNegative64
) {
3922 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
3925 %3 = OpConstant %2 9223372036854775808
3926 %4 = OpTypePointer Uniform %2
3928 %6 = OpTypePointer UniformConstant %5
3929 %7 = OpTypeFunction %1 %4 %6
3930 %8 = OpFunction %1 None %7
3931 %9 = OpFunctionParameter %4
3932 %10 = OpFunctionParameter %6
3934 OpCopyMemorySized %9 %10 %3
3939 CompileSuccessfully(spirv
);
3940 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
3943 const char kDeeplyNestedStructureSetup
[] = R
"(
3945 %void_f = OpTypeFunction %void
3946 %int = OpTypeInt 32 0
3947 %float = OpTypeFloat 32
3948 %v3float = OpTypeVector %float 3
3949 %mat4x3 = OpTypeMatrix %v3float 4
3950 %_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
3951 %_ptr_Private_float = OpTypePointer Private %float
3952 %my_matrix = OpVariable %_ptr_Private_mat4x3 Private
3953 %my_float_var = OpVariable %_ptr_Private_float Private
3954 %_ptr_Function_float = OpTypePointer Function %float
3955 %int_0 = OpConstant %int 0
3956 %int_1 = OpConstant %int 1
3957 %int_2 = OpConstant %int 2
3958 %int_3 = OpConstant %int 3
3959 %int_5 = OpConstant %int 5
3961 ; Making the following nested structures.
3969 ; uniform blockName {
3975 %f32arr = OpTypeRuntimeArray %float
3976 %v4float = OpTypeVector %float 4
3977 %array5_mat4x3 = OpTypeArray %mat4x3 %int_5
3978 %array5_vec4 = OpTypeArray %v4float %int_5
3979 %_ptr_Uniform_float = OpTypePointer Uniform %float
3980 %_ptr_Function_vec4 = OpTypePointer Function %v4float
3981 %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
3982 %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
3983 %struct_blockName = OpTypeStruct %struct_s %int %f32arr
3984 %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
3985 %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
3986 %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
3987 %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
3988 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
3989 %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
3990 %spec_int = OpSpecConstant %int 2
3991 %float_0 = OpConstant %float 0
3992 %func = OpFunction %void None %void_f
3996 // In what follows, Access Chain Instruction refers to one of the following:
3997 // OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain, and
3998 // OpInBoundsPtrAccessChain
3999 using AccessChainInstructionTest
= spvtest::ValidateBase
<std::string
>;
4001 // Determines whether the access chain instruction requires the 'element id'
4003 bool AccessChainRequiresElemId(const std::string
& instr
) {
4004 return (instr
== "OpPtrAccessChain" || instr
== "OpInBoundsPtrAccessChain");
4007 // Valid: Access a float in a matrix using an access chain instruction.
4008 TEST_P(AccessChainInstructionTest
, AccessChainGood
) {
4009 const std::string instr
= GetParam();
4010 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4011 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+
4012 "%float_entry = " + instr
+
4013 R
"( %_ptr_Private_float %my_matrix )" + elem
+
4018 CompileSuccessfully(spirv
);
4019 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4022 // Invalid. The result type of an access chain instruction must be a pointer.
4023 TEST_P(AccessChainInstructionTest
, AccessChainResultTypeBad
) {
4024 const std::string instr
= GetParam();
4025 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4026 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4029 R
"( %float %my_matrix )" + elem
+
4035 const std::string expected_err
= "The Result Type of " + instr
+
4036 " <id> '36[%36]' must be "
4037 "OpTypePointer. Found OpTypeFloat.";
4038 CompileSuccessfully(spirv
);
4039 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4040 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4043 // Invalid. The base type of an access chain instruction must be a pointer.
4044 TEST_P(AccessChainInstructionTest
, AccessChainBaseTypeVoidBad
) {
4045 const std::string instr
= GetParam();
4046 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4047 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4049 instr
+ " %_ptr_Private_float %void " + elem
+
4054 CompileSuccessfully(spirv
);
4055 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4056 EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '1[%void]' cannot be a "
4060 // Invalid. The base type of an access chain instruction must be a pointer.
4061 TEST_P(AccessChainInstructionTest
, AccessChainBaseTypeNonPtrVariableBad
) {
4062 const std::string instr
= GetParam();
4063 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4064 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4066 instr
+ R
"( %_ptr_Private_float %_ptr_Private_float )" +
4072 CompileSuccessfully(spirv
);
4073 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4074 EXPECT_THAT(getDiagnosticString(),
4075 HasSubstr("Operand '8[%_ptr_Private_float]' cannot be a type"));
4078 // Invalid: The storage class of Base and Result do not match.
4079 TEST_P(AccessChainInstructionTest
,
4080 AccessChainResultAndBaseStorageClassDoesntMatchBad
) {
4081 const std::string instr
= GetParam();
4082 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4083 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4085 instr
+ R
"( %_ptr_Function_float %my_matrix )" + elem
+
4090 const std::string expected_err
=
4091 "The result pointer storage class and base pointer storage class in " +
4092 instr
+ " do not match.";
4093 CompileSuccessfully(spirv
);
4094 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4095 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4098 // Invalid. The base type of an access chain instruction must point to a
4099 // composite object.
4100 TEST_P(AccessChainInstructionTest
,
4101 AccessChainBasePtrNotPointingToCompositeBad
) {
4102 const std::string instr
= GetParam();
4103 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4104 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4106 instr
+ R
"( %_ptr_Private_float %my_float_var )" + elem
+
4111 const std::string expected_err
= instr
+
4112 " reached non-composite type while "
4113 "indexes still remain to be traversed.";
4114 CompileSuccessfully(spirv
);
4115 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4116 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4119 // Valid. No Indexes were passed to the access chain instruction. The Result
4120 // Type is the same as the Base type.
4121 TEST_P(AccessChainInstructionTest
, AccessChainNoIndexesGood
) {
4122 const std::string instr
= GetParam();
4123 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4124 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4126 instr
+ R
"( %_ptr_Private_float %my_float_var )" + elem
+
4131 CompileSuccessfully(spirv
);
4132 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4135 // Invalid. No Indexes were passed to the access chain instruction, but the
4136 // Result Type is different from the Base type.
4137 TEST_P(AccessChainInstructionTest
, AccessChainNoIndexesBad
) {
4138 const std::string instr
= GetParam();
4139 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4140 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4142 instr
+ R
"( %_ptr_Private_mat4x3 %my_float_var )" + elem
+
4147 CompileSuccessfully(spirv
);
4148 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4150 getDiagnosticString(),
4151 HasSubstr("result type (OpTypeMatrix) does not match the type that "
4152 "results from indexing into the base <id> (OpTypeFloat)."));
4155 // Valid: 255 indexes passed to the access chain instruction. Limit is 255.
4156 TEST_P(AccessChainInstructionTest
, AccessChainTooManyIndexesGood
) {
4157 const std::string instr
= GetParam();
4158 const std::string elem
= AccessChainRequiresElemId(instr
) ? " %int_0 " : "";
4159 const std::string arrayStride
=
4160 " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
4162 std::string header
=
4163 kGLSL450MemoryModel
+ arrayStride
+ kDeeplyNestedStructureSetup
;
4164 header
.erase(header
.find("%func"));
4165 std::ostringstream spirv
;
4166 spirv
<< header
<< "\n";
4168 // Build nested structures. Struct 'i' contains struct 'i-1'
4169 spirv
<< "%s_depth_1 = OpTypeStruct %float\n";
4170 for (int i
= 2; i
<= depth
; ++i
) {
4171 spirv
<< "%s_depth_" << i
<< " = OpTypeStruct %s_depth_" << i
- 1 << "\n";
4174 // Define Pointer and Variable to use for the AccessChain instruction.
4175 spirv
<< "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
4177 spirv
<< "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
4181 %func = OpFunction %void None %void_f
4185 // AccessChain with 'n' indexes (n = depth)
4186 spirv
<< "%entry = " << instr
<< " %_ptr_Uniform_float %deep_var" << elem
;
4187 for (int i
= 0; i
< depth
; ++i
) {
4196 CompileSuccessfully(spirv
.str());
4197 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4200 // Invalid: 256 indexes passed to the access chain instruction. Limit is 255.
4201 TEST_P(AccessChainInstructionTest
, AccessChainTooManyIndexesBad
) {
4202 const std::string instr
= GetParam();
4203 const std::string elem
= AccessChainRequiresElemId(instr
) ? " %int_0 " : "";
4204 std::ostringstream spirv
;
4205 spirv
<< kGLSL450MemoryModel
<< kDeeplyNestedStructureSetup
;
4206 spirv
<< "%entry = " << instr
<< " %_ptr_Private_float %my_matrix" << elem
;
4207 for (int i
= 0; i
< 256; ++i
) {
4214 const std::string expected_err
= "The number of indexes in " + instr
+
4215 " may not exceed 255. Found 256 indexes.";
4216 CompileSuccessfully(spirv
.str());
4217 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4218 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4221 // Valid: 10 indexes passed to the access chain instruction. (Custom limit: 10)
4222 TEST_P(AccessChainInstructionTest
, CustomizedAccessChainTooManyIndexesGood
) {
4223 const std::string instr
= GetParam();
4224 const std::string elem
= AccessChainRequiresElemId(instr
) ? " %int_0 " : "";
4225 const std::string arrayStride
=
4226 " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
4228 std::string header
=
4229 kGLSL450MemoryModel
+ arrayStride
+ kDeeplyNestedStructureSetup
;
4230 header
.erase(header
.find("%func"));
4231 std::ostringstream spirv
;
4232 spirv
<< header
<< "\n";
4234 // Build nested structures. Struct 'i' contains struct 'i-1'
4235 spirv
<< "%s_depth_1 = OpTypeStruct %float\n";
4236 for (int i
= 2; i
<= depth
; ++i
) {
4237 spirv
<< "%s_depth_" << i
<< " = OpTypeStruct %s_depth_" << i
- 1 << "\n";
4240 // Define Pointer and Variable to use for the AccessChain instruction.
4241 spirv
<< "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
4243 spirv
<< "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
4247 %func = OpFunction %void None %void_f
4251 // AccessChain with 'n' indexes (n = depth)
4252 spirv
<< "%entry = " << instr
<< " %_ptr_Uniform_float %deep_var" << elem
;
4253 for (int i
= 0; i
< depth
; ++i
) {
4263 spvValidatorOptionsSetUniversalLimit(
4264 options_
, spv_validator_limit_max_access_chain_indexes
, 10u);
4265 CompileSuccessfully(spirv
.str());
4266 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4269 // Invalid: 11 indexes passed to the access chain instruction. Custom Limit:10
4270 TEST_P(AccessChainInstructionTest
, CustomizedAccessChainTooManyIndexesBad
) {
4271 const std::string instr
= GetParam();
4272 const std::string elem
= AccessChainRequiresElemId(instr
) ? " %int_0 " : "";
4273 std::ostringstream spirv
;
4274 spirv
<< kGLSL450MemoryModel
<< kDeeplyNestedStructureSetup
;
4275 spirv
<< "%entry = " << instr
<< " %_ptr_Private_float %my_matrix" << elem
;
4276 for (int i
= 0; i
< 11; ++i
) {
4283 const std::string expected_err
= "The number of indexes in " + instr
+
4284 " may not exceed 10. Found 11 indexes.";
4285 spvValidatorOptionsSetUniversalLimit(
4286 options_
, spv_validator_limit_max_access_chain_indexes
, 10u);
4287 CompileSuccessfully(spirv
.str());
4288 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4289 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4292 // Invalid: Index passed to the access chain instruction is float (must be
4294 TEST_P(AccessChainInstructionTest
, AccessChainUndefinedIndexBad
) {
4295 const std::string instr
= GetParam();
4296 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4297 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4299 instr
+ R
"( %_ptr_Private_float %my_matrix )" + elem
+
4304 const std::string expected_err
=
4305 "Indexes passed to " + instr
+ " must be of type integer.";
4306 CompileSuccessfully(spirv
);
4307 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4308 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4311 // Invalid: The index argument that indexes into a struct must be of type
4313 TEST_P(AccessChainInstructionTest
, AccessChainStructIndexNotConstantBad
) {
4314 const std::string instr
= GetParam();
4315 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4316 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4318 instr
+ R
"( %_ptr_Uniform_float %blockName_var )" + elem
+
4319 R
"(%int_0 %spec_int %int_2
4323 CompileSuccessfully(spirv
);
4324 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4325 EXPECT_THAT(getDiagnosticString(), HasSubstr("The <id> passed to " + instr
));
4326 EXPECT_THAT(getDiagnosticString(),
4327 HasSubstr("into a structure must be an OpConstant"));
4330 // Invalid: Indexing up to a vec4 granularity, but result type expected float.
4331 TEST_P(AccessChainInstructionTest
,
4332 AccessChainStructResultTypeDoesntMatchIndexedTypeBad
) {
4333 const std::string instr
= GetParam();
4334 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4335 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4337 instr
+ R
"( %_ptr_Uniform_float %blockName_var )" + elem
+
4338 R
"(%int_0 %int_1 %int_2
4342 const std::string expected_err
= instr
+
4343 " result type (OpTypeFloat) does not match "
4344 "the type that results from indexing into "
4345 "the base <id> (OpTypeVector).";
4346 CompileSuccessfully(spirv
);
4347 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4348 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4351 // Invalid: Reach non-composite type (bool) when unused indexes remain.
4352 TEST_P(AccessChainInstructionTest
, AccessChainStructTooManyIndexesBad
) {
4353 const std::string instr
= GetParam();
4354 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4355 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4357 instr
+ R
"( %_ptr_Uniform_float %blockName_var )" + elem
+
4358 R
"(%int_0 %int_2 %int_2
4362 const std::string expected_err
= instr
+
4363 " reached non-composite type while "
4364 "indexes still remain to be traversed.";
4365 CompileSuccessfully(spirv
);
4366 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4367 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4370 // Invalid: Trying to find index 3 of the struct that has only 3 members.
4371 TEST_P(AccessChainInstructionTest
, AccessChainStructIndexOutOfBoundBad
) {
4372 const std::string instr
= GetParam();
4373 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4374 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4376 instr
+ R
"( %_ptr_Uniform_float %blockName_var )" + elem
+
4377 R
"(%int_3 %int_2 %int_2
4381 const std::string expected_err
= "is out of bounds: " + instr
+
4382 " cannot find index 3 into the structure "
4383 "<id> '25[%_struct_25]'. This structure "
4384 "has 3 members. Largest valid index is 2.";
4385 CompileSuccessfully(spirv
);
4386 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4387 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4390 // Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
4391 TEST_P(AccessChainInstructionTest
, AccessChainIndexIntoAllTypesGood
) {
4392 // indexes that we are passing are: 0, 3, 1, 2, 0
4393 // 0 will select the struct_s within the base struct (blockName)
4394 // 3 will select the Array that contains 5 matrices
4395 // 1 will select the Matrix that is at index 1 of the array
4396 // 2 will select the column (which is a vector) within the matrix at index 2
4397 // 0 will select the element at the index 0 of the vector. (which is a float).
4398 const std::string instr
= GetParam();
4399 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4400 const std::string arrayStride
=
4401 " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
4402 std::ostringstream spirv
;
4403 spirv
<< kGLSL450MemoryModel
<< arrayStride
<< kDeeplyNestedStructureSetup
4405 spirv
<< "%ss = " << instr
<< " %_ptr_Uniform_struct_s %blockName_var "
4406 << elem
<< "%int_0" << std::endl
;
4407 spirv
<< "%sa = " << instr
<< " %_ptr_Uniform_array5_mat4x3 %blockName_var "
4408 << elem
<< "%int_0 %int_3" << std::endl
;
4409 spirv
<< "%sm = " << instr
<< " %_ptr_Uniform_mat4x3 %blockName_var " << elem
4410 << "%int_0 %int_3 %int_1" << std::endl
;
4411 spirv
<< "%sc = " << instr
<< " %_ptr_Uniform_v3float %blockName_var " << elem
4412 << "%int_0 %int_3 %int_1 %int_2" << std::endl
;
4413 spirv
<< "%entry = " << instr
<< " %_ptr_Uniform_float %blockName_var "
4414 << elem
<< "%int_0 %int_3 %int_1 %int_2 %int_0" << std::endl
;
4419 CompileSuccessfully(spirv
.str());
4420 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4423 // Valid: Access an element of OpTypeRuntimeArray.
4424 TEST_P(AccessChainInstructionTest
, AccessChainIndexIntoRuntimeArrayGood
) {
4425 const std::string instr
= GetParam();
4426 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4427 const std::string arrayStride
=
4428 " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
4429 std::string spirv
= kGLSL450MemoryModel
+ arrayStride
+
4430 kDeeplyNestedStructureSetup
+ R
"(
4431 %runtime_arr_entry = )" + instr
+
4432 R
"( %_ptr_Uniform_float %blockName_var )" + elem
+
4437 CompileSuccessfully(spirv
);
4438 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4441 // Invalid: Unused index when accessing OpTypeRuntimeArray.
4442 TEST_P(AccessChainInstructionTest
, AccessChainIndexIntoRuntimeArrayBad
) {
4443 const std::string instr
= GetParam();
4444 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4445 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4446 %runtime_arr_entry = )" +
4447 instr
+ R
"( %_ptr_Uniform_float %blockName_var )" + elem
+
4448 R
"(%int_2 %int_0 %int_1
4452 const std::string expected_err
=
4454 " reached non-composite type while indexes still remain to be traversed.";
4455 CompileSuccessfully(spirv
);
4456 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4457 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4460 // Invalid: Reached scalar type before arguments to the access chain instruction
4462 TEST_P(AccessChainInstructionTest
, AccessChainMatrixMoreArgsThanNeededBad
) {
4463 const std::string instr
= GetParam();
4464 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4465 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4467 instr
+ R
"( %_ptr_Private_float %my_matrix )" + elem
+
4468 R
"(%int_0 %int_1 %int_0
4472 const std::string expected_err
= instr
+
4473 " reached non-composite type while "
4474 "indexes still remain to be traversed.";
4475 CompileSuccessfully(spirv
);
4476 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4477 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4480 // Invalid: The result type and the type indexed into do not match.
4481 TEST_P(AccessChainInstructionTest
,
4482 AccessChainResultTypeDoesntMatchIndexedTypeBad
) {
4483 const std::string instr
= GetParam();
4484 const std::string elem
= AccessChainRequiresElemId(instr
) ? "%int_0 " : "";
4485 std::string spirv
= kGLSL450MemoryModel
+ kDeeplyNestedStructureSetup
+ R
"(
4487 instr
+ R
"( %_ptr_Private_mat4x3 %my_matrix )" + elem
+
4492 const std::string expected_err
= instr
+
4493 " result type (OpTypeMatrix) does not match "
4494 "the type that results from indexing into "
4495 "the base <id> (OpTypeFloat).";
4496 CompileSuccessfully(spirv
);
4497 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4498 EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err
));
4501 // Run tests for Access Chain Instructions.
4502 INSTANTIATE_TEST_SUITE_P(
4503 CheckAccessChainInstructions
, AccessChainInstructionTest
,
4504 ::testing::Values("OpAccessChain", "OpInBoundsAccessChain",
4505 "OpPtrAccessChain", "OpInBoundsPtrAccessChain"));
4507 // TODO: OpArrayLength
4508 // TODO: OpImagePointer
4509 // TODO: OpGenericPtrMemSemantics
4511 TEST_P(ValidateIdWithMessage
, OpFunctionGood
) {
4512 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4515 %3 = OpTypeFunction %1 %2 %2
4516 %4 = OpFunction %1 None %3
4520 CompileSuccessfully(spirv
.c_str());
4521 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4523 TEST_P(ValidateIdWithMessage
, OpFunctionResultTypeBad
) {
4524 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4527 %3 = OpConstant %2 42
4528 %4 = OpTypeFunction %1 %2 %2
4529 %5 = OpFunction %2 None %4
4533 CompileSuccessfully(spirv
.c_str());
4534 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4536 getDiagnosticString(),
4537 HasSubstr(make_message("OpFunction Result Type <id> '2[%uint]' does not "
4538 "match the Function Type's return type <id> "
4541 TEST_P(ValidateIdWithMessage
, OpReturnValueTypeBad
) {
4542 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4545 %3 = OpConstant %2 0
4546 %4 = OpTypeFunction %1
4547 %5 = OpFunction %1 None %4
4551 CompileSuccessfully(spirv
.c_str());
4552 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4553 EXPECT_THAT(getDiagnosticString(),
4554 HasSubstr(make_message(
4555 "OpReturnValue Value <id> '3[%float_0]'s type does "
4556 "not match OpFunction's return type.")));
4558 TEST_P(ValidateIdWithMessage
, OpFunctionFunctionTypeBad
) {
4559 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4562 %4 = OpFunction %1 None %2
4566 CompileSuccessfully(spirv
.c_str());
4567 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4568 EXPECT_THAT(getDiagnosticString(),
4569 HasSubstr(make_message(
4570 "OpFunction Function Type <id> '2[%uint]' is not a function "
4574 TEST_P(ValidateIdWithMessage
, OpFunctionUseBad
) {
4575 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
4577 %2 = OpTypeFunction %1
4578 %3 = OpFunction %1 None %2
4584 CompileSuccessfully(spirv
);
4585 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4587 getDiagnosticString(),
4588 HasSubstr(make_message("Invalid use of function result id '3[%3]'.")));
4591 TEST_P(ValidateIdWithMessage
, OpFunctionParameterGood
) {
4592 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4595 %3 = OpTypeFunction %1 %2
4596 %4 = OpFunction %1 None %3
4597 %5 = OpFunctionParameter %2
4601 CompileSuccessfully(spirv
.c_str());
4602 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4604 TEST_P(ValidateIdWithMessage
, OpFunctionParameterMultipleGood
) {
4605 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4608 %3 = OpTypeFunction %1 %2 %2
4609 %4 = OpFunction %1 None %3
4610 %5 = OpFunctionParameter %2
4611 %6 = OpFunctionParameter %2
4615 CompileSuccessfully(spirv
.c_str());
4616 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4618 TEST_P(ValidateIdWithMessage
, OpFunctionParameterResultTypeBad
) {
4619 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4622 %3 = OpTypeFunction %1 %2
4623 %4 = OpFunction %1 None %3
4624 %5 = OpFunctionParameter %1
4628 CompileSuccessfully(spirv
.c_str());
4629 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4631 getDiagnosticString(),
4632 HasSubstr(make_message(
4633 "OpFunctionParameter Result Type <id> '1[%void]' does not "
4634 "match the OpTypeFunction parameter type of the same index.")));
4637 TEST_P(ValidateIdWithMessage
, OpFunctionCallGood
) {
4638 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4641 %3 = OpTypeFunction %2 %2
4642 %4 = OpTypeFunction %1
4643 %5 = OpConstant %2 42 ;21
4645 %6 = OpFunction %2 None %3
4646 %7 = OpFunctionParameter %2
4651 %10 = OpFunction %1 None %4
4653 %12 = OpFunctionCall %2 %6 %5
4656 CompileSuccessfully(spirv
.c_str());
4657 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4659 TEST_P(ValidateIdWithMessage
, OpFunctionCallResultTypeBad
) {
4660 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4663 %3 = OpTypeFunction %2 %2
4664 %4 = OpTypeFunction %1
4665 %5 = OpConstant %2 42 ;21
4667 %6 = OpFunction %2 None %3
4668 %7 = OpFunctionParameter %2
4670 %9 = OpIAdd %2 %7 %7
4674 %10 = OpFunction %1 None %4
4676 %12 = OpFunctionCall %1 %6 %5
4679 CompileSuccessfully(spirv
.c_str());
4680 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4682 getDiagnosticString(),
4683 HasSubstr(make_message("OpFunctionCall Result Type <id> '1[%void]'s type "
4684 "does not match Function <id> '2[%uint]'s return "
4687 TEST_P(ValidateIdWithMessage
, OpFunctionCallFunctionBad
) {
4688 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4691 %3 = OpTypeFunction %2 %2
4692 %4 = OpTypeFunction %1
4693 %5 = OpConstant %2 42 ;21
4695 %10 = OpFunction %1 None %4
4697 %12 = OpFunctionCall %2 %5 %5
4700 CompileSuccessfully(spirv
.c_str());
4701 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4702 EXPECT_THAT(getDiagnosticString(),
4703 HasSubstr(make_message(
4704 "OpFunctionCall Function <id> '5[%uint_42]' is not a "
4707 TEST_P(ValidateIdWithMessage
, OpFunctionCallArgumentTypeBad
) {
4708 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4711 %3 = OpTypeFunction %2 %2
4712 %4 = OpTypeFunction %1
4713 %5 = OpConstant %2 42
4715 %13 = OpTypeFloat 32
4716 %14 = OpConstant %13 3.14
4718 %6 = OpFunction %2 None %3
4719 %7 = OpFunctionParameter %2
4721 %9 = OpIAdd %2 %7 %7
4725 %10 = OpFunction %1 None %4
4727 %12 = OpFunctionCall %2 %6 %14
4730 CompileSuccessfully(spirv
.c_str());
4731 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4732 EXPECT_THAT(getDiagnosticString(),
4733 HasSubstr(make_message(
4734 "OpFunctionCall Argument <id> '7[%float_3_1400001]'s "
4735 "type does not match Function <id> '2[%uint]'s "
4736 "parameter type.")));
4739 // Valid: OpSampledImage result <id> is used in the same block by
4740 // OpImageSampleImplictLod
4741 TEST_P(ValidateIdWithMessage
, OpSampledImageGood
) {
4742 std::string spirv
= kGLSL450MemoryModel
+ sampledImageSetup
+ R
"(
4743 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4744 %si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
4747 CompileSuccessfully(spirv
.c_str());
4748 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4751 // Invalid: OpSampledImage result <id> is defined in one block and used in a
4753 TEST_P(ValidateIdWithMessage
, OpSampledImageUsedInDifferentBlockBad
) {
4754 std::string spirv
= kGLSL450MemoryModel
+ sampledImageSetup
+ R
"(
4755 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4758 %si_lod = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
4761 CompileSuccessfully(spirv
.c_str());
4762 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4764 getDiagnosticString(),
4765 HasSubstr(make_message(
4766 "All OpSampledImage instructions must be in the same block in "
4767 "which their Result <id> are consumed. OpSampledImage Result "
4768 "Type <id> '23[%23]' has a consumer in a different basic "
4769 "block. The consumer instruction <id> is '25[%25]'.")));
4772 // Invalid: OpSampledImage result <id> is used by OpSelect
4773 // Note: According to the Spec, OpSelect parameters must be either a scalar or a
4774 // vector. Therefore, OpTypeSampledImage is an illegal parameter for OpSelect.
4775 // However, the OpSelect validation does not catch this today. Therefore, it is
4776 // caught by the OpSampledImage validation. If the OpSelect validation code is
4777 // updated, the error message for this test may change.
4779 // Disabled since OpSelect catches this now.
4780 TEST_P(ValidateIdWithMessage
, DISABLED_OpSampledImageUsedInOpSelectBad
) {
4781 std::string spirv
= kGLSL450MemoryModel
+ sampledImageSetup
+ R
"(
4782 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4783 %select_img = OpSelect %sampled_image_type %spec_true %smpld_img %smpld_img
4786 CompileSuccessfully(spirv
.c_str());
4787 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4788 EXPECT_THAT(getDiagnosticString(),
4789 HasSubstr(make_message(
4790 "Result <id> from OpSampledImage instruction must not "
4791 "appear as operands of OpSelect. Found result <id> "
4792 "'23' as an operand of <id> '24'.")));
4795 TEST_P(ValidateIdWithMessage
, OpCopyObjectSampledImageGood
) {
4796 std::string spirv
= kGLSL450MemoryModel
+ sampledImageSetup
+ R
"(
4797 %smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4798 %smpld_img2 = OpCopyObject %sampled_image_type %smpld_img
4799 %image_inst2 = OpCopyObject %image_type %image_inst
4802 CompileSuccessfully(spirv
.c_str());
4803 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4806 // Valid: Get a float in a matrix using CompositeExtract.
4807 // Valid: Insert float into a matrix using CompositeInsert.
4808 TEST_P(ValidateIdWithMessage
, CompositeExtractInsertGood
) {
4809 std::ostringstream spirv
;
4810 spirv
<< kGLSL450MemoryModel
<< kDeeplyNestedStructureSetup
<< std::endl
;
4811 spirv
<< "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl
;
4812 spirv
<< "%float_entry = OpCompositeExtract %float %matrix 0 1" << std::endl
;
4814 // To test CompositeInsert, insert the object back in after extraction.
4815 spirv
<< "%new_composite = OpCompositeInsert %mat4x3 %float_entry %matrix 0 1"
4817 spirv
<< R
"(OpReturn
4819 CompileSuccessfully(spirv
.str());
4820 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4824 TEST_P(ValidateIdWithMessage
, OpFunctionCallArgumentCountBar
) {
4825 const char *spirv
= R
"(
4828 %3 = OpTypeFunction %2 %2
4829 %4 = OpTypeFunction %1
4830 %5 = OpConstant %2 42 ;21
4832 %6 = OpFunction %2 None %3
4833 %7 = OpFunctionParameter %2
4839 %10 = OpFunction %1 None %4
4842 %12 = OpFunctionCall %2 %6 %5
4844 CHECK(spirv
, SPV_ERROR_INVALID_ID
);
4848 // TODO: The many things that changed with how images are used.
4849 // TODO: OpTextureSample
4850 // TODO: OpTextureSampleDref
4851 // TODO: OpTextureSampleLod
4852 // TODO: OpTextureSampleProj
4853 // TODO: OpTextureSampleGrad
4854 // TODO: OpTextureSampleOffset
4855 // TODO: OpTextureSampleProjLod
4856 // TODO: OpTextureSampleProjGrad
4857 // TODO: OpTextureSampleLodOffset
4858 // TODO: OpTextureSampleProjOffset
4859 // TODO: OpTextureSampleGradOffset
4860 // TODO: OpTextureSampleProjLodOffset
4861 // TODO: OpTextureSampleProjGradOffset
4862 // TODO: OpTextureFetchTexelLod
4863 // TODO: OpTextureFetchTexelOffset
4864 // TODO: OpTextureFetchSample
4865 // TODO: OpTextureFetchTexel
4866 // TODO: OpTextureGather
4867 // TODO: OpTextureGatherOffset
4868 // TODO: OpTextureGatherOffsets
4869 // TODO: OpTextureQuerySizeLod
4870 // TODO: OpTextureQuerySize
4871 // TODO: OpTextureQueryLevels
4872 // TODO: OpTextureQuerySamples
4873 // TODO: OpConvertUToF
4874 // TODO: OpConvertFToS
4875 // TODO: OpConvertSToF
4876 // TODO: OpConvertUToF
4880 // TODO: OpConvertPtrToU
4881 // TODO: OpConvertUToPtr
4882 // TODO: OpPtrCastToGeneric
4883 // TODO: OpGenericCastToPtr
4885 // TODO: OpGenericCastToPtrExplicit
4886 // TODO: OpSatConvertSToU
4887 // TODO: OpSatConvertUToS
4888 // TODO: OpVectorExtractDynamic
4889 // TODO: OpVectorInsertDynamic
4891 TEST_P(ValidateIdWithMessage
, OpVectorShuffleIntGood
) {
4892 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4893 %int = OpTypeInt 32 0
4894 %ivec3 = OpTypeVector %int 3
4895 %ivec4 = OpTypeVector %int 4
4896 %ptr_ivec3 = OpTypePointer Function %ivec3
4897 %undef = OpUndef %ivec4
4898 %int_42 = OpConstant %int 42
4899 %int_0 = OpConstant %int 0
4900 %int_2 = OpConstant %int 2
4901 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4902 %2 = OpTypeFunction %ivec3
4903 %3 = OpFunction %ivec3 None %2
4905 %var = OpVariable %ptr_ivec3 Function %1
4906 %5 = OpLoad %ivec3 %var
4907 %6 = OpVectorShuffle %ivec3 %5 %undef 2 1 0
4910 CompileSuccessfully(spirv
.c_str());
4911 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4914 TEST_P(ValidateIdWithMessage
, OpVectorShuffleFloatGood
) {
4915 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4916 %float = OpTypeFloat 32
4917 %vec2 = OpTypeVector %float 2
4918 %vec3 = OpTypeVector %float 3
4919 %vec4 = OpTypeVector %float 4
4920 %ptr_vec2 = OpTypePointer Function %vec2
4921 %ptr_vec3 = OpTypePointer Function %vec3
4922 %float_1 = OpConstant %float 1
4923 %float_2 = OpConstant %float 2
4924 %1 = OpConstantComposite %vec2 %float_2 %float_1
4925 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
4926 %3 = OpTypeFunction %vec4
4927 %4 = OpFunction %vec4 None %3
4929 %var = OpVariable %ptr_vec2 Function %1
4930 %var2 = OpVariable %ptr_vec3 Function %2
4931 %6 = OpLoad %vec2 %var
4932 %7 = OpLoad %vec3 %var2
4933 %8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0xffffffff
4936 CompileSuccessfully(spirv
.c_str());
4937 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
4940 TEST_P(ValidateIdWithMessage
, OpVectorShuffleScalarResultType
) {
4941 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4942 %float = OpTypeFloat 32
4943 %vec2 = OpTypeVector %float 2
4944 %ptr_vec2 = OpTypePointer Function %vec2
4945 %float_1 = OpConstant %float 1
4946 %float_2 = OpConstant %float 2
4947 %1 = OpConstantComposite %vec2 %float_2 %float_1
4948 %2 = OpTypeFunction %float
4949 %3 = OpFunction %float None %2
4951 %var = OpVariable %ptr_vec2 Function %1
4952 %5 = OpLoad %vec2 %var
4953 %6 = OpVectorShuffle %float %5 %5 0
4956 CompileSuccessfully(spirv
.c_str());
4957 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4958 EXPECT_THAT(getDiagnosticString(),
4959 HasSubstr(make_message(
4960 "Result Type of OpVectorShuffle must be OpTypeVector.")));
4963 TEST_P(ValidateIdWithMessage
, OpVectorShuffleComponentCount
) {
4964 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4965 %int = OpTypeInt 32 0
4966 %ivec3 = OpTypeVector %int 3
4967 %ptr_ivec3 = OpTypePointer Function %ivec3
4968 %int_42 = OpConstant %int 42
4969 %int_0 = OpConstant %int 0
4970 %int_2 = OpConstant %int 2
4971 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4972 %2 = OpTypeFunction %ivec3
4973 %3 = OpFunction %ivec3 None %2
4975 %var = OpVariable %ptr_ivec3 Function %1
4976 %5 = OpLoad %ivec3 %var
4977 %6 = OpVectorShuffle %ivec3 %5 %5 0 1
4980 CompileSuccessfully(spirv
.c_str());
4981 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
4982 EXPECT_THAT(getDiagnosticString(),
4983 HasSubstr(make_message(
4984 "OpVectorShuffle component literals count does not match "
4985 "Result Type <id> '2[%v3uint]'s vector component count.")));
4988 TEST_P(ValidateIdWithMessage
, OpVectorShuffleVector1Type
) {
4989 std::string spirv
= kGLSL450MemoryModel
+ R
"(
4990 %int = OpTypeInt 32 0
4991 %ivec2 = OpTypeVector %int 2
4992 %ptr_int = OpTypePointer Function %int
4993 %undef = OpUndef %ivec2
4994 %int_42 = OpConstant %int 42
4995 %2 = OpTypeFunction %ivec2
4996 %3 = OpFunction %ivec2 None %2
4998 %var = OpVariable %ptr_int Function %int_42
4999 %5 = OpLoad %int %var
5000 %6 = OpVectorShuffle %ivec2 %5 %undef 0 0
5003 CompileSuccessfully(spirv
.c_str());
5004 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5006 getDiagnosticString(),
5007 HasSubstr(make_message("The type of Vector 1 must be OpTypeVector.")));
5010 TEST_P(ValidateIdWithMessage
, OpVectorShuffleVector2Type
) {
5011 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5012 %int = OpTypeInt 32 0
5013 %ivec2 = OpTypeVector %int 2
5014 %ptr_ivec2 = OpTypePointer Function %ivec2
5015 %undef = OpUndef %int
5016 %int_42 = OpConstant %int 42
5017 %1 = OpConstantComposite %ivec2 %int_42 %int_42
5018 %2 = OpTypeFunction %ivec2
5019 %3 = OpFunction %ivec2 None %2
5021 %var = OpVariable %ptr_ivec2 Function %1
5022 %5 = OpLoad %ivec2 %var
5023 %6 = OpVectorShuffle %ivec2 %5 %undef 0 1
5026 CompileSuccessfully(spirv
.c_str());
5027 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5029 getDiagnosticString(),
5030 HasSubstr(make_message("The type of Vector 2 must be OpTypeVector.")));
5033 TEST_P(ValidateIdWithMessage
, OpVectorShuffleVector1ComponentType
) {
5034 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5035 %int = OpTypeInt 32 0
5036 %ivec3 = OpTypeVector %int 3
5037 %ptr_ivec3 = OpTypePointer Function %ivec3
5038 %int_42 = OpConstant %int 42
5039 %int_0 = OpConstant %int 0
5040 %int_2 = OpConstant %int 2
5041 %float = OpTypeFloat 32
5042 %vec3 = OpTypeVector %float 3
5043 %vec4 = OpTypeVector %float 4
5044 %ptr_vec3 = OpTypePointer Function %vec3
5045 %float_1 = OpConstant %float 1
5046 %float_2 = OpConstant %float 2
5047 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
5048 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
5049 %3 = OpTypeFunction %vec4
5050 %4 = OpFunction %vec4 None %3
5052 %var = OpVariable %ptr_ivec3 Function %1
5053 %var2 = OpVariable %ptr_vec3 Function %2
5054 %6 = OpLoad %ivec3 %var
5055 %7 = OpLoad %vec3 %var2
5056 %8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0
5059 CompileSuccessfully(spirv
.c_str());
5060 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5061 EXPECT_THAT(getDiagnosticString(),
5062 HasSubstr(make_message(
5063 "The Component Type of Vector 1 must be the same as "
5067 TEST_P(ValidateIdWithMessage
, OpVectorShuffleVector2ComponentType
) {
5068 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5069 %int = OpTypeInt 32 0
5070 %ivec3 = OpTypeVector %int 3
5071 %ptr_ivec3 = OpTypePointer Function %ivec3
5072 %int_42 = OpConstant %int 42
5073 %int_0 = OpConstant %int 0
5074 %int_2 = OpConstant %int 2
5075 %float = OpTypeFloat 32
5076 %vec3 = OpTypeVector %float 3
5077 %vec4 = OpTypeVector %float 4
5078 %ptr_vec3 = OpTypePointer Function %vec3
5079 %float_1 = OpConstant %float 1
5080 %float_2 = OpConstant %float 2
5081 %1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
5082 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
5083 %3 = OpTypeFunction %vec4
5084 %4 = OpFunction %vec4 None %3
5086 %var = OpVariable %ptr_ivec3 Function %1
5087 %var2 = OpVariable %ptr_vec3 Function %2
5088 %6 = OpLoad %vec3 %var2
5089 %7 = OpLoad %ivec3 %var
5090 %8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0
5093 CompileSuccessfully(spirv
.c_str());
5094 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5095 EXPECT_THAT(getDiagnosticString(),
5096 HasSubstr(make_message(
5097 "The Component Type of Vector 2 must be the same as "
5101 TEST_P(ValidateIdWithMessage
, OpVectorShuffleLiterals
) {
5102 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5103 %float = OpTypeFloat 32
5104 %vec2 = OpTypeVector %float 2
5105 %vec3 = OpTypeVector %float 3
5106 %vec4 = OpTypeVector %float 4
5107 %ptr_vec2 = OpTypePointer Function %vec2
5108 %ptr_vec3 = OpTypePointer Function %vec3
5109 %float_1 = OpConstant %float 1
5110 %float_2 = OpConstant %float 2
5111 %1 = OpConstantComposite %vec2 %float_2 %float_1
5112 %2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
5113 %3 = OpTypeFunction %vec4
5114 %4 = OpFunction %vec4 None %3
5116 %var = OpVariable %ptr_vec2 Function %1
5117 %var2 = OpVariable %ptr_vec3 Function %2
5118 %6 = OpLoad %vec2 %var
5119 %7 = OpLoad %vec3 %var2
5120 %8 = OpVectorShuffle %vec4 %6 %7 0 8 2 6
5123 CompileSuccessfully(spirv
.c_str());
5124 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5126 getDiagnosticString(),
5127 HasSubstr(make_message(
5128 "Component index 8 is out of bounds for combined (Vector1 + Vector2) "
5132 // TODO: OpCompositeConstruct
5133 // TODO: OpCompositeExtract
5134 // TODO: OpCompositeInsert
5135 // TODO: OpCopyObject
5136 // TODO: OpTranspose
5154 // TODO: OpVectorTimesScalar
5155 // TODO: OpMatrixTimesScalar
5156 // TODO: OpVectorTimesMatrix
5157 // TODO: OpMatrixTimesVector
5158 // TODO: OpMatrixTimesMatrix
5159 // TODO: OpOuterProduct
5161 // TODO: OpShiftRightLogical
5162 // TODO: OpShiftRightArithmetic
5163 // TODO: OpShiftLeftLogical
5164 // TODO: OpBitwiseOr
5165 // TODO: OpBitwiseXor
5166 // TODO: OpBitwiseAnd
5173 // TODO: OpSignBitSet
5174 // TODO: OpLessOrGreater
5176 // TODO: OpUnordered
5177 // TODO: OpLogicalOr
5178 // TODO: OpLogicalXor
5179 // TODO: OpLogicalAnd
5182 // TODO: OpFOrdEqual
5183 // TODO: OpFUnordEqual
5184 // TODO: OpINotEqual
5185 // TODO: OpFOrdNotEqual
5186 // TODO: OpFUnordNotEqual
5187 // TODO: OpULessThan
5188 // TODO: OpSLessThan
5189 // TODO: OpFOrdLessThan
5190 // TODO: OpFUnordLessThan
5191 // TODO: OpUGreaterThan
5192 // TODO: OpSGreaterThan
5193 // TODO: OpFOrdGreaterThan
5194 // TODO: OpFUnordGreaterThan
5195 // TODO: OpULessThanEqual
5196 // TODO: OpSLessThanEqual
5197 // TODO: OpFOrdLessThanEqual
5198 // TODO: OpFUnordLessThanEqual
5199 // TODO: OpUGreaterThanEqual
5200 // TODO: OpSGreaterThanEqual
5201 // TODO: OpFOrdGreaterThanEqual
5202 // TODO: OpFUnordGreaterThanEqual
5208 // TODO: OpFwidthFine
5209 // TODO: OpDPdxCoarse
5210 // TODO: OpDPdyCoarse
5211 // TODO: OpFwidthCoarse
5212 // TODO: OpLoopMerge
5213 // TODO: OpSelectionMerge
5216 TEST_P(ValidateIdWithMessage
, OpPhiNotAType
) {
5217 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5219 %3 = OpConstantTrue %2
5221 %5 = OpTypeFunction %4
5222 %6 = OpFunction %4 None %5
5231 CompileSuccessfully(spirv
.c_str());
5232 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5233 EXPECT_THAT(getDiagnosticString(),
5234 HasSubstr(make_message("ID '3[%true]' is not a type "
5238 TEST_P(ValidateIdWithMessage
, OpPhiSamePredecessor
) {
5239 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5241 %3 = OpConstantTrue %2
5243 %5 = OpTypeFunction %4
5244 %6 = OpFunction %4 None %5
5246 OpBranchConditional %3 %8 %8
5253 CompileSuccessfully(spirv
.c_str());
5254 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5257 TEST_P(ValidateIdWithMessage
, OpPhiOddArgumentNumber
) {
5258 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5260 %3 = OpConstantTrue %2
5262 %5 = OpTypeFunction %4
5263 %6 = OpFunction %4 None %5
5272 CompileSuccessfully(spirv
.c_str());
5273 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5275 getDiagnosticString(),
5276 HasSubstr(make_message("OpPhi does not have an equal number of incoming "
5277 "values and basic blocks.")));
5280 TEST_P(ValidateIdWithMessage
, OpPhiTooFewPredecessors
) {
5281 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5283 %3 = OpConstantTrue %2
5285 %5 = OpTypeFunction %4
5286 %6 = OpFunction %4 None %5
5295 CompileSuccessfully(spirv
.c_str());
5296 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5297 EXPECT_THAT(getDiagnosticString(),
5298 HasSubstr(make_message(
5299 "OpPhi's number of incoming blocks (0) does not match "
5300 "block's predecessor count (1).")));
5303 TEST_P(ValidateIdWithMessage
, OpPhiTooManyPredecessors
) {
5304 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5306 %3 = OpConstantTrue %2
5308 %5 = OpTypeFunction %4
5309 %6 = OpFunction %4 None %5
5315 %10 = OpPhi %2 %3 %7 %3 %9
5320 CompileSuccessfully(spirv
.c_str());
5321 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5322 EXPECT_THAT(getDiagnosticString(),
5323 HasSubstr(make_message(
5324 "OpPhi's number of incoming blocks (2) does not match "
5325 "block's predecessor count (1).")));
5328 TEST_P(ValidateIdWithMessage
, OpPhiMismatchedTypes
) {
5329 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5331 %3 = OpConstantTrue %2
5334 %6 = OpConstant %5 0
5335 %7 = OpTypeFunction %4
5336 %8 = OpFunction %4 None %7
5338 OpBranchConditional %3 %10 %11
5342 %12 = OpPhi %2 %3 %9 %6 %11
5347 CompileSuccessfully(spirv
.c_str());
5348 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5349 EXPECT_THAT(getDiagnosticString(),
5350 HasSubstr(make_message(
5351 "OpPhi's result type <id> '2[%bool]' does not match "
5352 "incoming value <id> '6[%uint_0]' type <id> "
5356 TEST_P(ValidateIdWithMessage
, OpPhiPredecessorNotABlock
) {
5357 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5359 %3 = OpConstantTrue %2
5361 %5 = OpTypeFunction %4
5362 %6 = OpFunction %4 None %5
5364 OpBranchConditional %3 %8 %9
5370 %10 = OpPhi %2 %3 %7 %3 %3
5375 CompileSuccessfully(spirv
.c_str());
5376 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5377 EXPECT_THAT(getDiagnosticString(),
5378 HasSubstr(make_message(
5379 "OpPhi's incoming basic block <id> '3[%true]' is not an "
5383 TEST_P(ValidateIdWithMessage
, OpPhiNotAPredecessor
) {
5384 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5386 %3 = OpConstantTrue %2
5388 %5 = OpTypeFunction %4
5389 %6 = OpFunction %4 None %5
5391 OpBranchConditional %3 %8 %9
5397 %10 = OpPhi %2 %3 %7 %3 %9
5402 CompileSuccessfully(spirv
.c_str());
5403 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5404 EXPECT_THAT(getDiagnosticString(),
5405 HasSubstr(make_message(
5406 "OpPhi's incoming basic block <id> '9[%9]' is not a "
5407 "predecessor of <id> '8[%8]'.")));
5410 TEST_P(ValidateIdWithMessage
, OpBranchConditionalGood
) {
5411 std::string spirv
= BranchConditionalSetup
+ R
"(
5412 %branch_cond = OpINotEqual %bool %i0 %i1
5413 OpSelectionMerge %end None
5414 OpBranchConditional %branch_cond %target_t %target_f
5415 )" + BranchConditionalTail
;
5417 CompileSuccessfully(spirv
.c_str());
5418 EXPECT_EQ(SPV_SUCCESS
, ValidateAndRetrieveValidationState());
5421 TEST_P(ValidateIdWithMessage
, OpBranchConditionalWithWeightsGood
) {
5422 std::string spirv
= BranchConditionalSetup
+ R
"(
5423 %branch_cond = OpINotEqual %bool %i0 %i1
5424 OpSelectionMerge %end None
5425 OpBranchConditional %branch_cond %target_t %target_f 1 1
5426 )" + BranchConditionalTail
;
5428 CompileSuccessfully(spirv
.c_str());
5429 EXPECT_EQ(SPV_SUCCESS
, ValidateAndRetrieveValidationState());
5432 TEST_P(ValidateIdWithMessage
, OpBranchConditional_CondIsScalarInt
) {
5433 std::string spirv
= BranchConditionalSetup
+ R
"(
5434 OpSelectionMerge %end None
5435 OpBranchConditional %i0 %target_t %target_f
5436 )" + BranchConditionalTail
;
5438 CompileSuccessfully(spirv
.c_str());
5439 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5441 getDiagnosticString(),
5442 HasSubstr(make_message("Condition operand for OpBranchConditional must "
5443 "be of boolean type")));
5446 TEST_P(ValidateIdWithMessage
, OpBranchConditional_TrueTargetIsNotLabel
) {
5447 std::string spirv
= BranchConditionalSetup
+ R
"(
5448 OpSelectionMerge %end None
5449 OpBranchConditional %true %i0 %target_f
5450 )" + BranchConditionalTail
;
5452 CompileSuccessfully(spirv
.c_str());
5453 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5454 EXPECT_THAT(getDiagnosticString(),
5455 HasSubstr(make_message(
5456 "The 'True Label' operand for OpBranchConditional must "
5457 "be the ID of an OpLabel instruction")));
5460 TEST_P(ValidateIdWithMessage
, OpBranchConditional_FalseTargetIsNotLabel
) {
5461 std::string spirv
= BranchConditionalSetup
+ R
"(
5462 OpSelectionMerge %end None
5463 OpBranchConditional %true %target_t %i0
5464 )" + BranchConditionalTail
;
5466 CompileSuccessfully(spirv
.c_str());
5467 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5468 EXPECT_THAT(getDiagnosticString(),
5469 HasSubstr(make_message(
5470 "The 'False Label' operand for OpBranchConditional "
5471 "must be the ID of an OpLabel instruction")));
5474 TEST_P(ValidateIdWithMessage
, OpBranchConditional_NotEnoughWeights
) {
5475 std::string spirv
= BranchConditionalSetup
+ R
"(
5476 %branch_cond = OpINotEqual %bool %i0 %i1
5477 OpSelectionMerge %end None
5478 OpBranchConditional %branch_cond %target_t %target_f 1
5479 )" + BranchConditionalTail
;
5481 CompileSuccessfully(spirv
.c_str());
5482 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5483 EXPECT_THAT(getDiagnosticString(),
5484 HasSubstr(make_message(
5485 "OpBranchConditional requires either 3 or 5 parameters")));
5488 TEST_P(ValidateIdWithMessage
, OpBranchConditional_TooManyWeights
) {
5489 std::string spirv
= BranchConditionalSetup
+ R
"(
5490 %branch_cond = OpINotEqual %bool %i0 %i1
5491 OpSelectionMerge %end None
5492 OpBranchConditional %branch_cond %target_t %target_f 1 2 3
5493 )" + BranchConditionalTail
;
5495 CompileSuccessfully(spirv
.c_str());
5496 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5497 EXPECT_THAT(getDiagnosticString(),
5498 HasSubstr(make_message(
5499 "OpBranchConditional requires either 3 or 5 parameters")));
5502 TEST_P(ValidateIdWithMessage
, OpBranchConditional_ConditionIsAType
) {
5503 std::string spirv
= BranchConditionalSetup
+ R
"(
5504 OpBranchConditional %bool %target_t %target_f
5505 )" + BranchConditionalTail
;
5507 CompileSuccessfully(spirv
.c_str());
5508 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5509 EXPECT_THAT(getDiagnosticString(),
5510 HasSubstr(make_message("Operand '3[%bool]' cannot be a "
5516 TEST_P(ValidateIdWithMessage
, OpReturnValueConstantGood
) {
5517 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5520 %3 = OpTypeFunction %2
5521 %4 = OpConstant %2 42
5522 %5 = OpFunction %2 None %3
5526 CompileSuccessfully(spirv
.c_str());
5527 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5530 TEST_P(ValidateIdWithMessage
, OpReturnValueVariableGood
) {
5531 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5533 %2 = OpTypeInt 32 0 ;10
5534 %3 = OpTypeFunction %2
5535 %8 = OpTypePointer Function %2 ;18
5536 %4 = OpConstant %2 42 ;22
5537 %5 = OpFunction %2 None %3 ;27
5539 %7 = OpVariable %8 Function %4 ;34
5541 OpReturnValue %9 ;36
5543 CompileSuccessfully(spirv
.c_str());
5544 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5547 TEST_P(ValidateIdWithMessage
, OpReturnValueExpressionGood
) {
5548 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5551 %3 = OpTypeFunction %2
5552 %4 = OpConstant %2 42
5553 %5 = OpFunction %2 None %3
5555 %7 = OpIAdd %2 %4 %4
5558 CompileSuccessfully(spirv
.c_str());
5559 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5562 TEST_P(ValidateIdWithMessage
, OpReturnValueIsType
) {
5563 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5566 %3 = OpTypeFunction %2
5567 %5 = OpFunction %2 None %3
5571 CompileSuccessfully(spirv
.c_str());
5572 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5573 EXPECT_THAT(getDiagnosticString(),
5574 HasSubstr(make_message("Operand '1[%void]' cannot be a "
5578 TEST_P(ValidateIdWithMessage
, OpReturnValueIsLabel
) {
5579 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5582 %3 = OpTypeFunction %2
5583 %5 = OpFunction %2 None %3
5587 CompileSuccessfully(spirv
.c_str());
5588 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5589 EXPECT_THAT(getDiagnosticString(),
5590 HasSubstr(make_message("Operand '5[%5]' requires a type")));
5593 TEST_P(ValidateIdWithMessage
, OpReturnValueIsVoid
) {
5594 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5597 %3 = OpTypeFunction %1
5598 %5 = OpFunction %1 None %3
5600 %7 = OpFunctionCall %1 %5
5603 CompileSuccessfully(spirv
.c_str());
5604 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5605 EXPECT_THAT(getDiagnosticString(),
5606 HasSubstr(make_message(
5607 "OpReturnValue value's type <id> '1[%void]' is missing or "
5611 TEST_P(ValidateIdWithMessage
, OpReturnValueIsVariableInPhysical
) {
5612 // It's valid to return a pointer in a physical addressing model.
5613 std::string spirv
= kOpCapabilitySetup
+ R
"(
5614 OpMemoryModel Physical32 OpenCL
5617 %3 = OpTypePointer Function %2
5618 %4 = OpTypeFunction %3
5619 %5 = OpFunction %3 None %4
5621 %7 = OpVariable %3 Function
5624 CompileSuccessfully(spirv
.c_str());
5625 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5628 TEST_P(ValidateIdWithMessage
, OpReturnValueIsVariableInLogical
) {
5629 // It's invalid to return a pointer in a physical addressing model.
5630 std::string spirv
= kOpCapabilitySetup
+ R
"(
5631 OpMemoryModel Logical GLSL450
5634 %3 = OpTypePointer Function %2
5635 %4 = OpTypeFunction %3
5636 %5 = OpFunction %3 None %4
5638 %7 = OpVariable %3 Function
5641 CompileSuccessfully(spirv
.c_str());
5642 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5644 getDiagnosticString(),
5645 HasSubstr(make_message("OpReturnValue value's type <id> "
5646 "'3[%_ptr_Function_uint]' is a pointer, which is "
5647 "invalid in the Logical addressing model.")));
5650 // With the VariablePointer Capability, the return value of a function is
5651 // allowed to be a pointer.
5652 TEST_P(ValidateIdWithMessage
, OpReturnValueVarPtrGood
) {
5653 std::ostringstream spirv
;
5654 createVariablePointerSpirvProgram(&spirv
,
5655 "" /* Instructions to add to "main" */,
5656 true /* Add VariablePointers Capability?*/,
5657 true /* Use Helper Function? */);
5658 CompileSuccessfully(spirv
.str());
5659 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5662 // Without the VariablePointer Capability, the return value of a function is
5663 // *not* allowed to be a pointer.
5664 // Disabled since using OpSelect with pointers without VariablePointers will
5665 // fail LogicalsPass.
5666 TEST_P(ValidateIdWithMessage
, DISABLED_OpReturnValueVarPtrBad
) {
5667 std::ostringstream spirv
;
5668 createVariablePointerSpirvProgram(&spirv
,
5669 "" /* Instructions to add to "main" */,
5670 false /* Add VariablePointers Capability?*/,
5671 true /* Use Helper Function? */);
5672 CompileSuccessfully(spirv
.str());
5673 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5674 EXPECT_THAT(getDiagnosticString(),
5675 HasSubstr(make_message(
5676 "OpReturnValue value's type <id> '7' is a pointer, "
5677 "which is invalid in the Logical addressing model.")));
5680 // TODO: enable when this bug is fixed:
5681 // https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
5682 TEST_P(ValidateIdWithMessage
, DISABLED_OpReturnValueIsFunction
) {
5683 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5686 %3 = OpTypeFunction %2
5687 %5 = OpFunction %2 None %3
5691 CompileSuccessfully(spirv
.c_str());
5692 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5695 TEST_P(ValidateIdWithMessage
, UndefinedTypeId
) {
5696 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5697 %s = OpTypeStruct %i32
5699 CompileSuccessfully(spirv
.c_str());
5700 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5701 EXPECT_THAT(getDiagnosticString(),
5702 HasSubstr(make_message(
5703 "Operand '2[%2]' requires a previous definition")));
5706 TEST_P(ValidateIdWithMessage
, UndefinedIdScope
) {
5707 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5708 %u32 = OpTypeInt 32 0
5709 %memsem = OpConstant %u32 0
5711 %void_f = OpTypeFunction %void
5712 %f = OpFunction %void None %void_f
5714 OpMemoryBarrier %undef %memsem
5718 CompileSuccessfully(spirv
.c_str());
5719 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5720 EXPECT_THAT(getDiagnosticString(),
5721 HasSubstr(make_message("ID '7[%7]' has not been "
5725 TEST_P(ValidateIdWithMessage
, UndefinedIdMemSem
) {
5726 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5727 %u32 = OpTypeInt 32 0
5728 %scope = OpConstant %u32 0
5730 %void_f = OpTypeFunction %void
5731 %f = OpFunction %void None %void_f
5733 OpMemoryBarrier %scope %undef
5737 CompileSuccessfully(spirv
.c_str());
5738 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5739 EXPECT_THAT(getDiagnosticString(),
5740 HasSubstr(make_message("ID '7[%7]' has not been "
5744 TEST_P(ValidateIdWithMessage
,
5745 KernelOpEntryPointAndOpInBoundsPtrAccessChainGood
) {
5746 std::string spirv
= kOpenCLMemoryModel32
+ R
"(
5747 OpEntryPoint Kernel %2 "simple_kernel
"
5748 OpSource OpenCL_C 200000
5749 OpDecorate %3 BuiltIn GlobalInvocationId
5750 OpDecorate %3 Constant
5751 OpDecorate %4 FuncParamAttr NoCapture
5752 OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId
" Import
5754 %6 = OpTypeVector %5 3
5755 %7 = OpTypePointer UniformConstant %6
5756 %3 = OpVariable %7 UniformConstant
5758 %9 = OpTypeStruct %5
5759 %10 = OpTypePointer CrossWorkgroup %9
5760 %11 = OpTypeFunction %8 %10
5761 %12 = OpConstant %5 0
5762 %13 = OpTypePointer CrossWorkgroup %5
5763 %14 = OpConstant %5 42
5764 %2 = OpFunction %8 None %11
5765 %4 = OpFunctionParameter %10
5767 %16 = OpLoad %6 %3 Aligned 0
5768 %17 = OpCompositeExtract %5 %16 0
5769 %18 = OpInBoundsPtrAccessChain %13 %4 %17 %12
5770 OpStore %18 %14 Aligned 4
5773 CompileSuccessfully(spirv
.c_str());
5774 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5777 TEST_P(ValidateIdWithMessage
, OpPtrAccessChainGood
) {
5778 std::string spirv
= kOpenCLMemoryModel64
+ R
"(
5779 OpEntryPoint Kernel %2 "another_kernel
"
5780 OpSource OpenCL_C 200000
5781 OpDecorate %3 BuiltIn GlobalInvocationId
5782 OpDecorate %3 Constant
5783 OpDecorate %4 FuncParamAttr NoCapture
5784 OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId
" Import
5786 %6 = OpTypeVector %5 3
5787 %7 = OpTypePointer UniformConstant %6
5788 %3 = OpVariable %7 UniformConstant
5791 %10 = OpTypeStruct %9
5792 %11 = OpTypePointer CrossWorkgroup %10
5793 %12 = OpTypeFunction %8 %11
5794 %13 = OpConstant %5 4294967295
5795 %14 = OpConstant %9 0
5796 %15 = OpTypePointer CrossWorkgroup %9
5797 %16 = OpConstant %9 42
5798 %2 = OpFunction %8 None %12
5799 %4 = OpFunctionParameter %11
5801 %18 = OpLoad %6 %3 Aligned 0
5802 %19 = OpCompositeExtract %5 %18 0
5803 %20 = OpBitwiseAnd %5 %19 %13
5804 %21 = OpPtrAccessChain %15 %4 %20 %14
5805 OpStore %21 %16 Aligned 4
5808 CompileSuccessfully(spirv
.c_str());
5809 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5812 TEST_P(ValidateIdWithMessage
, StgBufOpPtrAccessChainGood
) {
5813 std::string spirv
= R
"(
5815 OpCapability Linkage
5816 OpCapability VariablePointersStorageBuffer
5817 OpExtension "SPV_KHR_variable_pointers
"
5818 OpMemoryModel Logical GLSL450
5819 OpEntryPoint GLCompute %3 ""
5820 OpDecorate %ptr ArrayStride 8
5821 %int = OpTypeInt 32 0
5822 %int_2 = OpConstant %int 2
5823 %int_4 = OpConstant %int 4
5824 %struct = OpTypeStruct %int
5825 %array = OpTypeArray %struct %int_4
5826 %ptr = OpTypePointer StorageBuffer %array
5827 %var = OpVariable %ptr StorageBuffer
5829 %2 = OpTypeFunction %1
5830 %3 = OpFunction %1 None %2
5832 %5 = OpPtrAccessChain %ptr %var %int_2
5836 CompileSuccessfully(spirv
.c_str());
5837 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5840 TEST_P(ValidateIdWithMessage
, OpLoadBitcastPointerGood
) {
5841 std::string spirv
= kOpenCLMemoryModel64
+ R
"(
5845 %5 = OpTypePointer UniformConstant %3
5846 %6 = OpTypePointer UniformConstant %4
5847 %7 = OpVariable %5 UniformConstant
5848 %8 = OpTypeFunction %2
5849 %9 = OpFunction %2 None %8
5851 %11 = OpBitcast %6 %7
5855 CompileSuccessfully(spirv
.c_str());
5856 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5858 TEST_P(ValidateIdWithMessage
, OpLoadBitcastNonPointerBad
) {
5859 std::string spirv
= kOpenCLMemoryModel64
+ R
"(
5863 %5 = OpTypePointer UniformConstant %3
5864 %6 = OpTypeFunction %2
5865 %7 = OpVariable %5 UniformConstant
5866 %8 = OpFunction %2 None %6
5869 %11 = OpBitcast %4 %10
5873 CompileSuccessfully(spirv
.c_str());
5874 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5875 EXPECT_THAT(getDiagnosticString(),
5876 HasSubstr(make_message(
5877 "OpLoad type for pointer <id> '11[%11]' is not a pointer "
5880 TEST_P(ValidateIdWithMessage
, OpStoreBitcastPointerGood
) {
5881 std::string spirv
= kOpenCLMemoryModel64
+ R
"(
5885 %5 = OpTypePointer Function %3
5886 %6 = OpTypePointer Function %4
5887 %7 = OpTypeFunction %2
5888 %8 = OpConstant %3 42
5889 %9 = OpFunction %2 None %7
5891 %11 = OpVariable %6 Function
5892 %12 = OpBitcast %5 %11
5896 CompileSuccessfully(spirv
.c_str());
5897 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions());
5899 TEST_P(ValidateIdWithMessage
, OpStoreBitcastNonPointerBad
) {
5900 std::string spirv
= kOpenCLMemoryModel64
+ R
"(
5904 %5 = OpTypePointer Function %4
5905 %6 = OpTypeFunction %2
5906 %7 = OpConstant %4 42
5907 %8 = OpFunction %2 None %6
5909 %10 = OpVariable %5 Function
5910 %11 = OpBitcast %3 %7
5914 CompileSuccessfully(spirv
.c_str());
5915 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5916 EXPECT_THAT(getDiagnosticString(),
5917 HasSubstr(make_message(
5918 "OpStore type for pointer <id> '11[%11]' is not a pointer "
5922 // Result <id> resulting from an instruction within a function may not be used
5923 // outside that function.
5924 TEST_P(ValidateIdWithMessage
, ResultIdUsedOutsideOfFunctionBad
) {
5925 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5927 %2 = OpTypeFunction %1
5929 %4 = OpTypePointer Function %3
5930 %5 = OpFunction %1 None %2
5932 %7 = OpVariable %4 Function
5935 %8 = OpFunction %1 None %2
5941 CompileSuccessfully(spirv
.c_str());
5942 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5943 EXPECT_THAT(getDiagnosticString(),
5944 HasSubstr(make_message("ID '7[%7]' defined in block '6[%6]' does "
5945 "not dominate its use in block "
5949 TEST_P(ValidateIdWithMessage
, SpecIdTargetNotSpecializationConstant
) {
5950 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5951 OpDecorate %1 SpecId 200
5953 %2 = OpTypeFunction %void
5954 %int = OpTypeInt 32 0
5955 %1 = OpConstant %int 3
5956 %main = OpFunction %void None %2
5961 CompileSuccessfully(spirv
.c_str());
5962 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5964 getDiagnosticString(),
5965 HasSubstr(make_message("SpecId decoration on target <id> "
5966 "'1[%uint_3]' must be a scalar specialization "
5970 TEST_P(ValidateIdWithMessage
, SpecIdTargetOpSpecConstantOpBad
) {
5971 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5972 OpDecorate %1 SpecId 200
5974 %2 = OpTypeFunction %void
5975 %int = OpTypeInt 32 0
5976 %3 = OpConstant %int 1
5977 %4 = OpConstant %int 2
5978 %1 = OpSpecConstantOp %int IAdd %3 %4
5979 %main = OpFunction %void None %2
5984 CompileSuccessfully(spirv
.c_str());
5985 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
5987 getDiagnosticString(),
5988 HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
5989 "must be a scalar specialization constant")));
5992 TEST_P(ValidateIdWithMessage
, SpecIdTargetOpSpecConstantCompositeBad
) {
5993 std::string spirv
= kGLSL450MemoryModel
+ R
"(
5994 OpDecorate %1 SpecId 200
5996 %2 = OpTypeFunction %void
5997 %int = OpTypeInt 32 0
5998 %3 = OpConstant %int 1
5999 %1 = OpSpecConstantComposite %int
6000 %main = OpFunction %void None %2
6005 CompileSuccessfully(spirv
.c_str());
6006 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
6008 getDiagnosticString(),
6009 HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
6010 "must be a scalar specialization constant")));
6013 TEST_P(ValidateIdWithMessage
, SpecIdTargetGood
) {
6014 std::string spirv
= kGLSL450MemoryModel
+ R
"(
6015 OpDecorate %3 SpecId 200
6016 OpDecorate %4 SpecId 201
6017 OpDecorate %5 SpecId 202
6019 %2 = OpTypeFunction %1
6020 %int = OpTypeInt 32 0
6022 %3 = OpSpecConstant %int 3
6023 %4 = OpSpecConstantTrue %bool
6024 %5 = OpSpecConstantFalse %bool
6025 %main = OpFunction %1 None %2
6030 CompileSuccessfully(spirv
.c_str());
6031 EXPECT_EQ(SPV_SUCCESS
, ValidateAndRetrieveValidationState());
6034 TEST_P(ValidateIdWithMessage
, CorrectErrorForShuffle
) {
6035 std::string spirv
= kGLSL450MemoryModel
+ R
"(
6036 %uint = OpTypeInt 32 0
6037 %float = OpTypeFloat 32
6038 %v4float = OpTypeVector %float 4
6039 %v2float = OpTypeVector %float 2
6041 %548 = OpTypeFunction %void
6042 %CS = OpFunction %void None %548
6044 %6275 = OpUndef %v2float
6045 %6280 = OpUndef %v2float
6046 %6282 = OpVectorShuffle %v4float %6275 %6280 0 1 4 5
6051 CompileSuccessfully(spirv
.c_str());
6052 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
6054 getDiagnosticString(),
6055 HasSubstr(make_message(
6056 "Component index 4 is out of bounds for combined (Vector1 + Vector2) "
6058 EXPECT_EQ(25, getErrorPosition().index
);
6061 TEST_P(ValidateIdWithMessage
, VoidStructMember
) {
6062 const std::string spirv
= kGLSL450MemoryModel
+ R
"(
6064 %struct = OpTypeStruct %void
6067 CompileSuccessfully(spirv
);
6068 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
6070 getDiagnosticString(),
6071 HasSubstr(make_message("Structures cannot contain a void type.")));
6074 TEST_P(ValidateIdWithMessage
, TypeFunctionBadUse
) {
6075 std::string spirv
= kGLSL450MemoryModel
+ R
"(
6077 %2 = OpTypeFunction %1
6078 %3 = OpTypePointer Function %2
6079 %4 = OpFunction %1 None %2
6084 CompileSuccessfully(spirv
);
6085 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
6086 EXPECT_THAT(getDiagnosticString(),
6087 HasSubstr(make_message(
6088 "Invalid use of function type result id '2[%2]'.")));
6091 TEST_P(ValidateIdWithMessage
, BadTypeId
) {
6092 std::string spirv
= kGLSL450MemoryModel
+ R
"(
6094 %2 = OpTypeFunction %1
6096 %4 = OpConstant %3 0
6097 %5 = OpFunction %1 None %2
6104 CompileSuccessfully(spirv
);
6105 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
6106 EXPECT_THAT(getDiagnosticString(),
6107 HasSubstr(make_message("ID '4[%float_0]' is not a type "
6111 TEST_P(ValidateIdWithMessage
, VulkanMemoryModelLoadMakePointerVisibleGood
) {
6112 std::string spirv
= R
"(
6114 OpCapability VulkanMemoryModelKHR
6115 OpCapability Linkage
6116 OpExtension "SPV_KHR_vulkan_memory_model
"
6117 OpMemoryModel Logical VulkanKHR
6120 %3 = OpTypePointer Workgroup %2
6121 %4 = OpVariable %3 Workgroup
6122 %5 = OpTypeFunction %1
6123 %6 = OpConstant %2 2
6124 %7 = OpFunction %1 None %5
6126 %9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerVisibleKHR %6
6131 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6132 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6135 TEST_P(ValidateIdWithMessage
,
6136 VulkanMemoryModelLoadMakePointerVisibleMissingNonPrivatePointer
) {
6137 std::string spirv
= R
"(
6139 OpCapability VulkanMemoryModelKHR
6140 OpCapability Linkage
6141 OpExtension "SPV_KHR_vulkan_memory_model
"
6142 OpMemoryModel Logical VulkanKHR
6145 %3 = OpTypePointer Workgroup %2
6146 %4 = OpVariable %3 Workgroup
6147 %5 = OpTypeFunction %1
6148 %6 = OpConstant %2 2
6149 %7 = OpFunction %1 None %5
6151 %9 = OpLoad %2 %4 MakePointerVisibleKHR %6
6156 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6157 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6159 getDiagnosticString(),
6160 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6161 "MakePointerVisibleKHR is specified.")));
6164 TEST_P(ValidateIdWithMessage
,
6165 VulkanMemoryModelLoadNonPrivatePointerBadStorageClass
) {
6166 std::string spirv
= R
"(
6168 OpCapability VulkanMemoryModelKHR
6169 OpCapability Linkage
6170 OpExtension "SPV_KHR_vulkan_memory_model
"
6171 OpMemoryModel Logical VulkanKHR
6174 %3 = OpTypePointer Private %2
6175 %4 = OpVariable %3 Private
6176 %5 = OpTypeFunction %1
6177 %6 = OpConstant %2 2
6178 %7 = OpFunction %1 None %5
6180 %9 = OpLoad %2 %4 NonPrivatePointerKHR
6185 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6186 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6187 EXPECT_THAT(getDiagnosticString(),
6188 HasSubstr(make_message(
6189 "NonPrivatePointerKHR requires a pointer in Uniform, "
6190 "Workgroup, CrossWorkgroup, Generic, Image or "
6191 "StorageBuffer storage classes.")));
6194 TEST_P(ValidateIdWithMessage
,
6195 VulkanMemoryModelLoadMakePointerAvailableCannotBeUsed
) {
6196 std::string spirv
= R
"(
6198 OpCapability VulkanMemoryModelKHR
6199 OpCapability Linkage
6200 OpExtension "SPV_KHR_vulkan_memory_model
"
6201 OpMemoryModel Logical VulkanKHR
6204 %3 = OpTypePointer Workgroup %2
6205 %4 = OpVariable %3 Workgroup
6206 %5 = OpTypeFunction %1
6207 %6 = OpConstant %2 2
6208 %7 = OpFunction %1 None %5
6210 %9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerAvailableKHR %6
6215 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6216 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6217 EXPECT_THAT(getDiagnosticString(),
6218 HasSubstr(make_message(
6219 "MakePointerAvailableKHR cannot be used with OpLoad")));
6222 TEST_P(ValidateIdWithMessage
, VulkanMemoryModelStoreMakePointerAvailableGood
) {
6223 std::string spirv
= R
"(
6225 OpCapability VulkanMemoryModelKHR
6226 OpCapability Linkage
6227 OpExtension "SPV_KHR_vulkan_memory_model
"
6228 OpMemoryModel Logical VulkanKHR
6231 %3 = OpTypePointer Uniform %2
6232 %4 = OpVariable %3 Uniform
6233 %5 = OpTypeFunction %1
6234 %6 = OpConstant %2 5
6235 %7 = OpFunction %1 None %5
6237 OpStore %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %6
6242 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6243 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6246 TEST_P(ValidateIdWithMessage
,
6247 VulkanMemoryModelStoreMakePointerAvailableMissingNonPrivatePointer
) {
6248 std::string spirv
= R
"(
6250 OpCapability VulkanMemoryModelKHR
6251 OpCapability Linkage
6252 OpExtension "SPV_KHR_vulkan_memory_model
"
6253 OpMemoryModel Logical VulkanKHR
6256 %3 = OpTypePointer Uniform %2
6257 %4 = OpVariable %3 Uniform
6258 %5 = OpTypeFunction %1
6259 %6 = OpConstant %2 5
6260 %7 = OpFunction %1 None %5
6262 OpStore %4 %6 MakePointerAvailableKHR %6
6267 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6268 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6270 getDiagnosticString(),
6271 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6272 "MakePointerAvailableKHR is specified.")));
6275 TEST_P(ValidateIdWithMessage
,
6276 VulkanMemoryModelStoreNonPrivatePointerBadStorageClass
) {
6277 std::string spirv
= R
"(
6279 OpCapability VulkanMemoryModelKHR
6280 OpCapability Linkage
6281 OpExtension "SPV_KHR_vulkan_memory_model
"
6282 OpMemoryModel Logical VulkanKHR
6285 %3 = OpTypePointer Output %2
6286 %4 = OpVariable %3 Output
6287 %5 = OpTypeFunction %1
6288 %6 = OpConstant %2 5
6289 %7 = OpFunction %1 None %5
6291 OpStore %4 %6 NonPrivatePointerKHR
6296 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6297 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6298 EXPECT_THAT(getDiagnosticString(),
6299 HasSubstr(make_message(
6300 "NonPrivatePointerKHR requires a pointer in Uniform, "
6301 "Workgroup, CrossWorkgroup, Generic, Image or "
6302 "StorageBuffer storage classes.")));
6305 TEST_P(ValidateIdWithMessage
,
6306 VulkanMemoryModelStoreMakePointerVisibleCannotBeUsed
) {
6307 std::string spirv
= R
"(
6309 OpCapability VulkanMemoryModelKHR
6310 OpCapability Linkage
6311 OpExtension "SPV_KHR_vulkan_memory_model
"
6312 OpMemoryModel Logical VulkanKHR
6315 %3 = OpTypePointer Uniform %2
6316 %4 = OpVariable %3 Uniform
6317 %5 = OpTypeFunction %1
6318 %6 = OpConstant %2 5
6319 %7 = OpFunction %1 None %5
6321 OpStore %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %6
6326 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6327 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6328 EXPECT_THAT(getDiagnosticString(),
6329 HasSubstr(make_message(
6330 "MakePointerVisibleKHR cannot be used with OpStore.")));
6333 TEST_P(ValidateIdWithMessage
, VulkanMemoryModelCopyMemoryAvailable
) {
6334 std::string spirv
= R
"(
6336 OpCapability Linkage
6337 OpCapability VulkanMemoryModelKHR
6338 OpExtension "SPV_KHR_vulkan_memory_model
"
6339 OpMemoryModel Logical VulkanKHR
6342 %3 = OpTypePointer Workgroup %2
6343 %4 = OpVariable %3 Workgroup
6344 %5 = OpTypePointer Uniform %2
6345 %6 = OpVariable %5 Uniform
6346 %7 = OpConstant %2 2
6347 %8 = OpConstant %2 5
6348 %9 = OpTypeFunction %1
6349 %10 = OpFunction %1 None %9
6351 OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %7
6356 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6357 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6360 TEST_P(ValidateIdWithMessage
, VulkanMemoryModelCopyMemoryVisible
) {
6361 std::string spirv
= R
"(
6363 OpCapability Linkage
6364 OpCapability VulkanMemoryModelKHR
6365 OpExtension "SPV_KHR_vulkan_memory_model
"
6366 OpMemoryModel Logical VulkanKHR
6369 %3 = OpTypePointer Workgroup %2
6370 %4 = OpVariable %3 Workgroup
6371 %5 = OpTypePointer Uniform %2
6372 %6 = OpVariable %5 Uniform
6373 %7 = OpConstant %2 2
6374 %8 = OpConstant %2 5
6375 %9 = OpTypeFunction %1
6376 %10 = OpFunction %1 None %9
6378 OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %8
6383 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6384 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6387 TEST_P(ValidateIdWithMessage
, VulkanMemoryModelCopyMemoryAvailableAndVisible
) {
6388 std::string spirv
= R
"(
6390 OpCapability Linkage
6391 OpCapability VulkanMemoryModelKHR
6392 OpExtension "SPV_KHR_vulkan_memory_model
"
6393 OpMemoryModel Logical VulkanKHR
6396 %3 = OpTypePointer Workgroup %2
6397 %4 = OpVariable %3 Workgroup
6398 %5 = OpTypePointer Uniform %2
6399 %6 = OpVariable %5 Uniform
6400 %7 = OpConstant %2 2
6401 %8 = OpConstant %2 5
6402 %9 = OpTypeFunction %1
6403 %10 = OpFunction %1 None %9
6405 OpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8
6410 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6411 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6414 TEST_P(ValidateIdWithMessage
,
6415 VulkanMemoryModelCopyMemoryAvailableMissingNonPrivatePointer
) {
6416 std::string spirv
= R
"(
6418 OpCapability Linkage
6419 OpCapability VulkanMemoryModelKHR
6420 OpExtension "SPV_KHR_vulkan_memory_model
"
6421 OpMemoryModel Logical VulkanKHR
6424 %3 = OpTypePointer Workgroup %2
6425 %4 = OpVariable %3 Workgroup
6426 %5 = OpTypePointer Uniform %2
6427 %6 = OpVariable %5 Uniform
6428 %7 = OpConstant %2 2
6429 %8 = OpConstant %2 5
6430 %9 = OpTypeFunction %1
6431 %10 = OpFunction %1 None %9
6433 OpCopyMemory %4 %6 MakePointerAvailableKHR %7
6438 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6439 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6441 getDiagnosticString(),
6442 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6443 "MakePointerAvailableKHR is specified.")));
6446 TEST_P(ValidateIdWithMessage
,
6447 VulkanMemoryModelCopyMemoryVisibleMissingNonPrivatePointer
) {
6448 std::string spirv
= R
"(
6450 OpCapability Linkage
6451 OpCapability VulkanMemoryModelKHR
6452 OpExtension "SPV_KHR_vulkan_memory_model
"
6453 OpMemoryModel Logical VulkanKHR
6456 %3 = OpTypePointer Workgroup %2
6457 %4 = OpVariable %3 Workgroup
6458 %5 = OpTypePointer Uniform %2
6459 %6 = OpVariable %5 Uniform
6460 %7 = OpConstant %2 2
6461 %8 = OpConstant %2 5
6462 %9 = OpTypeFunction %1
6463 %10 = OpFunction %1 None %9
6465 OpCopyMemory %4 %6 MakePointerVisibleKHR %8
6470 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6471 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6473 getDiagnosticString(),
6474 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6475 "MakePointerVisibleKHR is specified.")));
6478 TEST_P(ValidateIdWithMessage
,
6479 VulkanMemoryModelCopyMemoryAvailableBadStorageClass
) {
6480 std::string spirv
= R
"(
6482 OpCapability Linkage
6483 OpCapability VulkanMemoryModelKHR
6484 OpExtension "SPV_KHR_vulkan_memory_model
"
6485 OpMemoryModel Logical VulkanKHR
6488 %3 = OpTypePointer Output %2
6489 %4 = OpVariable %3 Output
6490 %5 = OpTypePointer Uniform %2
6491 %6 = OpVariable %5 Uniform
6492 %7 = OpConstant %2 2
6493 %8 = OpConstant %2 5
6494 %9 = OpTypeFunction %1
6495 %10 = OpFunction %1 None %9
6497 OpCopyMemory %4 %6 NonPrivatePointerKHR
6502 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6503 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6504 EXPECT_THAT(getDiagnosticString(),
6505 HasSubstr(make_message(
6506 "NonPrivatePointerKHR requires a pointer in Uniform, "
6507 "Workgroup, CrossWorkgroup, Generic, Image or "
6508 "StorageBuffer storage classes.")));
6511 TEST_P(ValidateIdWithMessage
,
6512 VulkanMemoryModelCopyMemoryVisibleBadStorageClass
) {
6513 std::string spirv
= R
"(
6515 OpCapability Linkage
6516 OpCapability VulkanMemoryModelKHR
6517 OpExtension "SPV_KHR_vulkan_memory_model
"
6518 OpMemoryModel Logical VulkanKHR
6521 %3 = OpTypePointer Workgroup %2
6522 %4 = OpVariable %3 Workgroup
6523 %5 = OpTypePointer Input %2
6524 %6 = OpVariable %5 Input
6525 %7 = OpConstant %2 2
6526 %8 = OpConstant %2 5
6527 %9 = OpTypeFunction %1
6528 %10 = OpFunction %1 None %9
6530 OpCopyMemory %4 %6 NonPrivatePointerKHR
6535 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6536 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6537 EXPECT_THAT(getDiagnosticString(),
6538 HasSubstr(make_message(
6539 "NonPrivatePointerKHR requires a pointer in Uniform, "
6540 "Workgroup, CrossWorkgroup, Generic, Image or "
6541 "StorageBuffer storage classes.")));
6544 TEST_P(ValidateIdWithMessage
, VulkanMemoryModelCopyMemorySizedAvailable
) {
6545 std::string spirv
= R
"(
6547 OpCapability Linkage
6548 OpCapability Addresses
6549 OpCapability VulkanMemoryModelKHR
6550 OpExtension "SPV_KHR_vulkan_memory_model
"
6551 OpMemoryModel Logical VulkanKHR
6554 %3 = OpTypePointer Workgroup %2
6555 %4 = OpVariable %3 Workgroup
6556 %5 = OpTypePointer Uniform %2
6557 %6 = OpVariable %5 Uniform
6558 %7 = OpConstant %2 2
6559 %8 = OpConstant %2 5
6560 %9 = OpTypeFunction %1
6561 %12 = OpConstant %2 4
6562 %10 = OpFunction %1 None %9
6564 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR|MakePointerAvailableKHR %7
6569 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6570 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6573 TEST_P(ValidateIdWithMessage
, VulkanMemoryModelCopyMemorySizedVisible
) {
6574 std::string spirv
= R
"(
6576 OpCapability Linkage
6577 OpCapability Addresses
6578 OpCapability VulkanMemoryModelKHR
6579 OpExtension "SPV_KHR_vulkan_memory_model
"
6580 OpMemoryModel Logical VulkanKHR
6583 %3 = OpTypePointer Workgroup %2
6584 %4 = OpVariable %3 Workgroup
6585 %5 = OpTypePointer Uniform %2
6586 %6 = OpVariable %5 Uniform
6587 %7 = OpConstant %2 2
6588 %8 = OpConstant %2 5
6589 %12 = OpConstant %2 4
6590 %9 = OpTypeFunction %1
6591 %10 = OpFunction %1 None %9
6593 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR|MakePointerVisibleKHR %8
6598 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6599 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6602 TEST_P(ValidateIdWithMessage
,
6603 VulkanMemoryModelCopyMemorySizedAvailableAndVisible
) {
6604 std::string spirv
= R
"(
6606 OpCapability Linkage
6607 OpCapability Addresses
6608 OpCapability VulkanMemoryModelKHR
6609 OpExtension "SPV_KHR_vulkan_memory_model
"
6610 OpMemoryModel Logical VulkanKHR
6613 %3 = OpTypePointer Workgroup %2
6614 %4 = OpVariable %3 Workgroup
6615 %5 = OpTypePointer Uniform %2
6616 %6 = OpVariable %5 Uniform
6617 %7 = OpConstant %2 2
6618 %8 = OpConstant %2 5
6619 %12 = OpConstant %2 4
6620 %9 = OpTypeFunction %1
6621 %10 = OpFunction %1 None %9
6623 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8
6628 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6629 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6632 TEST_P(ValidateIdWithMessage
,
6633 VulkanMemoryModelCopyMemorySizedAvailableMissingNonPrivatePointer
) {
6634 std::string spirv
= R
"(
6636 OpCapability Linkage
6637 OpCapability Addresses
6638 OpCapability VulkanMemoryModelKHR
6639 OpExtension "SPV_KHR_vulkan_memory_model
"
6640 OpMemoryModel Logical VulkanKHR
6643 %3 = OpTypePointer Workgroup %2
6644 %4 = OpVariable %3 Workgroup
6645 %5 = OpTypePointer Uniform %2
6646 %6 = OpVariable %5 Uniform
6647 %7 = OpConstant %2 2
6648 %8 = OpConstant %2 5
6649 %12 = OpConstant %2 4
6650 %9 = OpTypeFunction %1
6651 %10 = OpFunction %1 None %9
6653 OpCopyMemorySized %4 %6 %12 MakePointerAvailableKHR %7
6658 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6659 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6661 getDiagnosticString(),
6662 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6663 "MakePointerAvailableKHR is specified.")));
6666 TEST_P(ValidateIdWithMessage
,
6667 VulkanMemoryModelCopyMemorySizedVisibleMissingNonPrivatePointer
) {
6668 std::string spirv
= R
"(
6670 OpCapability Linkage
6671 OpCapability Addresses
6672 OpCapability VulkanMemoryModelKHR
6673 OpExtension "SPV_KHR_vulkan_memory_model
"
6674 OpMemoryModel Logical VulkanKHR
6677 %3 = OpTypePointer Workgroup %2
6678 %4 = OpVariable %3 Workgroup
6679 %5 = OpTypePointer Uniform %2
6680 %6 = OpVariable %5 Uniform
6681 %7 = OpConstant %2 2
6682 %8 = OpConstant %2 5
6683 %12 = OpConstant %2 4
6684 %9 = OpTypeFunction %1
6685 %10 = OpFunction %1 None %9
6687 OpCopyMemorySized %4 %6 %12 MakePointerVisibleKHR %8
6692 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6693 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6695 getDiagnosticString(),
6696 HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6697 "MakePointerVisibleKHR is specified.")));
6700 TEST_P(ValidateIdWithMessage
,
6701 VulkanMemoryModelCopyMemorySizedAvailableBadStorageClass
) {
6702 std::string spirv
= R
"(
6704 OpCapability Linkage
6705 OpCapability Addresses
6706 OpCapability VulkanMemoryModelKHR
6707 OpExtension "SPV_KHR_vulkan_memory_model
"
6708 OpMemoryModel Logical VulkanKHR
6711 %3 = OpTypePointer Output %2
6712 %4 = OpVariable %3 Output
6713 %5 = OpTypePointer Uniform %2
6714 %6 = OpVariable %5 Uniform
6715 %7 = OpConstant %2 2
6716 %8 = OpConstant %2 5
6717 %12 = OpConstant %2 4
6718 %9 = OpTypeFunction %1
6719 %10 = OpFunction %1 None %9
6721 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR
6726 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6727 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6728 EXPECT_THAT(getDiagnosticString(),
6729 HasSubstr(make_message(
6730 "NonPrivatePointerKHR requires a pointer in Uniform, "
6731 "Workgroup, CrossWorkgroup, Generic, Image or "
6732 "StorageBuffer storage classes.")));
6735 TEST_P(ValidateIdWithMessage
,
6736 VulkanMemoryModelCopyMemorySizedVisibleBadStorageClass
) {
6737 std::string spirv
= R
"(
6739 OpCapability Linkage
6740 OpCapability Addresses
6741 OpCapability VulkanMemoryModelKHR
6742 OpExtension "SPV_KHR_vulkan_memory_model
"
6743 OpMemoryModel Logical VulkanKHR
6746 %3 = OpTypePointer Workgroup %2
6747 %4 = OpVariable %3 Workgroup
6748 %5 = OpTypePointer Input %2
6749 %6 = OpVariable %5 Input
6750 %7 = OpConstant %2 2
6751 %8 = OpConstant %2 5
6752 %12 = OpConstant %2 4
6753 %9 = OpTypeFunction %1
6754 %10 = OpFunction %1 None %9
6756 OpCopyMemorySized %4 %6 %12 NonPrivatePointerKHR
6761 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6762 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6763 EXPECT_THAT(getDiagnosticString(),
6764 HasSubstr(make_message(
6765 "NonPrivatePointerKHR requires a pointer in Uniform, "
6766 "Workgroup, CrossWorkgroup, Generic, Image or "
6767 "StorageBuffer storage classes.")));
6770 TEST_P(ValidateIdWithMessage
, IdDefInUnreachableBlock1
) {
6771 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6773 %2 = OpTypeFunction %1
6775 %4 = OpTypeFunction %3
6776 %5 = OpFunction %1 None %2
6780 %8 = OpFunctionCall %3 %9
6783 %9 = OpFunction %3 None %4
6789 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6790 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6791 EXPECT_THAT(getDiagnosticString(),
6792 HasSubstr(make_message(
6793 "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6794 "use in block '10[%10]'\n %10 = OpLabel")));
6797 TEST_P(ValidateIdWithMessage
, IdDefInUnreachableBlock2
) {
6798 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6800 %2 = OpTypeFunction %1
6802 %4 = OpTypeFunction %3
6803 %5 = OpFunction %1 None %2
6807 %8 = OpFunctionCall %3 %9
6810 %9 = OpFunction %3 None %4
6816 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6817 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6818 EXPECT_THAT(getDiagnosticString(),
6819 HasSubstr(make_message(
6820 "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6821 "use in block '10[%10]'\n %10 = OpLabel")));
6824 TEST_P(ValidateIdWithMessage
, IdDefInUnreachableBlock3
) {
6825 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6827 %2 = OpTypeFunction %1
6829 %4 = OpTypeFunction %3
6830 %5 = OpFunction %1 None %2
6834 %8 = OpFunctionCall %3 %9
6837 %9 = OpFunction %3 None %4
6843 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6844 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6845 EXPECT_THAT(getDiagnosticString(),
6846 HasSubstr(make_message(
6847 "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6848 "use in block '10[%10]'\n %10 = OpLabel")));
6851 TEST_P(ValidateIdWithMessage
, IdDefInUnreachableBlock4
) {
6852 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6854 %2 = OpTypeFunction %1
6856 %4 = OpTypeFunction %3
6857 %5 = OpFunction %1 None %2
6862 %9 = OpCopyObject %3 %8
6867 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6868 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6871 TEST_P(ValidateIdWithMessage
, IdDefInUnreachableBlock5
) {
6872 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6874 %2 = OpTypeFunction %1
6876 %4 = OpTypeFunction %3
6877 %5 = OpFunction %1 None %2
6884 %10 = OpCopyObject %3 %8
6889 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6890 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6893 TEST_P(ValidateIdWithMessage
, IdDefInUnreachableBlock6
) {
6894 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6896 %2 = OpTypeFunction %1
6898 %4 = OpTypeFunction %3
6899 %5 = OpFunction %1 None %2
6906 %10 = OpCopyObject %3 %9
6911 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6912 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6913 EXPECT_THAT(getDiagnosticString(),
6914 HasSubstr(make_message(
6915 "ID '9[%9]' defined in block '8[%8]' does not dominate its "
6916 "use in block '7[%7]'\n %7 = OpLabel")));
6919 TEST_P(ValidateIdWithMessage
, ReachableDefUnreachableUse
) {
6920 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6922 %2 = OpTypeFunction %1
6924 %4 = OpTypeFunction %3
6925 %5 = OpFunction %1 None %2
6930 %9 = OpCopyObject %3 %7
6935 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6936 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6939 TEST_P(ValidateIdWithMessage
, UnreachableDefUsedInPhi
) {
6940 const std::string spirv
= kNoKernelGLSL450MemoryModel
+ R
"(
6942 %3 = OpTypeFunction %void
6943 %float = OpTypeFloat 32
6945 %6 = OpTypeFunction %float
6946 %1 = OpFunction %void None %3
6949 OpSelectionMerge %9 None
6950 OpBranchConditional %8 %10 %9
6952 %11 = OpUndef %float
6955 %13 = OpUndef %float
6958 %14 = OpPhi %float %11 %10 %13 %7
6963 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6964 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6966 getDiagnosticString(),
6967 HasSubstr(make_message(
6968 "In OpPhi instruction '14[%14]', ID '13[%13]' definition does not "
6969 "dominate its parent '7[%7]'\n %14 = OpPhi %float %11 %10 %13 "
6973 TEST_P(ValidateIdWithMessage
, OpTypeForwardPointerNotAPointerType
) {
6974 std::string spirv
= R
"(
6975 OpCapability GenericPointer
6976 OpCapability VariablePointersStorageBuffer
6977 OpMemoryModel Logical GLSL450
6978 OpEntryPoint Fragment %1 "main
"
6979 OpExecutionMode %1 OriginLowerLeft
6980 OpTypeForwardPointer %2 CrossWorkgroup
6982 %3 = OpTypeFunction %2
6983 %1 = OpFunction %2 DontInline %3
6989 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
6990 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
6991 EXPECT_THAT(getDiagnosticString(),
6992 HasSubstr(make_message(
6993 "Pointer type in OpTypeForwardPointer is not a pointer "
6994 "type.\n OpTypeForwardPointer %void CrossWorkgroup")));
6997 TEST_P(ValidateIdWithMessage
, OpTypeForwardPointerWrongStorageClass
) {
6998 std::string spirv
= R
"(
6999 OpCapability GenericPointer
7000 OpCapability VariablePointersStorageBuffer
7001 OpMemoryModel Logical GLSL450
7002 OpEntryPoint Fragment %1 "main
"
7003 OpExecutionMode %1 OriginLowerLeft
7004 OpTypeForwardPointer %2 CrossWorkgroup
7005 %int = OpTypeInt 32 1
7006 %2 = OpTypePointer Function %int
7008 %3 = OpTypeFunction %void
7009 %1 = OpFunction %void None %3
7015 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
7016 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
7017 EXPECT_THAT(getDiagnosticString(),
7018 HasSubstr(make_message(
7019 "Storage class in OpTypeForwardPointer does not match the "
7020 "pointer definition.\n OpTypeForwardPointer "
7021 "%_ptr_Function_int CrossWorkgroup")));
7024 TEST_P(ValidateIdWithMessage
, MissingForwardPointer
) {
7025 const std::string spirv
= R
"(
7026 OpCapability Linkage
7028 OpMemoryModel Logical Simple
7029 %float = OpTypeFloat 32
7030 %_struct_9 = OpTypeStruct %float %_ptr_Uniform__struct_9
7031 %_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
7032 %1278 = OpVariable %_ptr_Uniform__struct_9 Uniform
7035 CompileSuccessfully(spirv
);
7036 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions());
7037 EXPECT_THAT(getDiagnosticString(),
7038 HasSubstr(make_message("Operand '3[%_ptr_Uniform__struct_2]' "
7039 "requires a previous definition")));
7042 TEST_P(ValidateIdWithMessage
, NVBindlessSamplerInStruct
) {
7043 std::string spirv
= R
"(
7045 OpCapability BindlessTextureNV
7046 OpExtension "SPV_NV_bindless_texture
"
7047 OpMemoryModel Logical GLSL450
7048 OpSamplerImageAddressingModeNV 64
7049 OpEntryPoint Fragment %main "main
"
7050 OpExecutionMode %main OriginUpperLeft
7052 %3 = OpTypeFunction %void
7053 %float = OpTypeFloat 32
7054 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
7055 %8 = OpTypeSampledImage %7
7056 %9 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
7058 %UBO = OpTypeStruct %8 %9 %10
7059 %_ptr_Uniform_UBO = OpTypePointer Uniform %UBO
7060 %_ = OpVariable %_ptr_Uniform_UBO Uniform
7061 %main = OpFunction %void None %3
7067 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_3
);
7068 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3
));
7071 TEST_P(ValidateIdWithMessage
,
7072 OpExtInstWithForwardRefsKHRDisallowedNoForwardRef
) {
7073 std::string spirv
= R
"(
7075 OpExtension "SPV_KHR_non_semantic_info
"
7076 OpExtension "SPV_KHR_relaxed_extended_instruction
"
7077 %1 = OpExtInstImport "NonSemantic
.Shader
.DebugInfo
.100"
7078 OpMemoryModel Logical GLSL450
7079 OpEntryPoint GLCompute %main "main
"
7080 OpExecutionMode %main LocalSize 1 1 1
7082 %main_type = OpTypeFunction %void
7083 %4 = OpExtInstWithForwardRefsKHR %void %1 DebugInfoNone
7084 %main = OpFunction %void None %main_type
7090 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_6
);
7091 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6
));
7093 getDiagnosticString(),
7094 HasSubstr(make_message("Opcode OpExtInstWithForwardRefsKHR must have at "
7095 "least one forward declared ID.")));
7098 TEST_P(ValidateIdWithMessage
, OpExtInstNoForwardRef
) {
7099 std::string spirv
= R
"(
7101 OpExtension "SPV_KHR_non_semantic_info
"
7102 OpExtension "SPV_KHR_relaxed_extended_instruction
"
7103 %1 = OpExtInstImport "NonSemantic
.Shader
.DebugInfo
.100"
7104 OpMemoryModel Logical GLSL450
7105 OpEntryPoint GLCompute %main "main
"
7106 OpExecutionMode %main LocalSize 1 1 1
7108 %main_type = OpTypeFunction %void
7109 %4 = OpExtInst %void %1 DebugInfoNone
7110 %main = OpFunction %void None %main_type
7116 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_6
);
7117 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6
));
7120 TEST_P(ValidateIdWithMessage
,
7121 OpExtInstWithForwardRefsKHRAllowedForwardReferenceInNonSemantic
) {
7122 std::string spirv
= R
"(
7124 OpExtension "SPV_KHR_non_semantic_info
"
7125 OpExtension "SPV_KHR_relaxed_extended_instruction
"
7126 %1 = OpExtInstImport "NonSemantic
.Shader
.DebugInfo
.100"
7127 OpMemoryModel Logical GLSL450
7128 OpEntryPoint GLCompute %2 "main
"
7129 OpExecutionMode %2 LocalSize 1 1 1
7130 %3 = OpString "sample
"
7132 %uint = OpTypeInt 32 0
7133 %uint_0 = OpConstant %uint 0
7134 %7 = OpTypeFunction %void
7135 %8 = OpExtInst %void %1 DebugSource %3 %3
7136 %9 = OpExtInst %void %1 DebugCompilationUnit %uint_0 %uint_0 %8 %uint_0
7137 %10 = OpExtInstWithForwardRefsKHR %void %1 DebugTypeFunction %uint_0 %11
7138 %12 = OpExtInstWithForwardRefsKHR %void %1 DebugFunction %3 %10 %8 %uint_0 %uint_0 %11 %3 %uint_0 %uint_0
7139 %11 = OpExtInst %void %1 DebugTypeComposite %3 %uint_0 %8 %uint_0 %uint_0 %9 %3 %uint_0 %uint_0 %12
7140 %2 = OpFunction %void None %7
7146 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_6
);
7147 EXPECT_EQ(SPV_SUCCESS
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6
));
7150 TEST_P(ValidateIdWithMessage
, OpExtInstNoForwardDeclAllowed
) {
7151 std::string spirv
= R
"(
7153 %1 = OpExtInstImport "NonSemantic
.Shader
.DebugInfo
.100"
7154 OpMemoryModel Logical GLSL450
7155 OpEntryPoint GLCompute %2 "main
"
7156 OpExecutionMode %2 LocalSize 1 1 1
7157 %3 = OpString "sample
"
7159 %uint = OpTypeInt 32 0
7160 %uint_0 = OpConstant %uint 0
7161 %7 = OpTypeFunction %void
7162 %8 = OpExtInst %void %1 DebugSource %3 %3
7163 %9 = OpExtInst %void %1 DebugCompilationUnit %uint_0 %uint_0 %8 %uint_0
7164 %10 = OpExtInst %void %1 DebugTypeFunction %uint_0 %11
7165 %12 = OpExtInst %void %1 DebugFunction %3 %10 %8 %uint_0 %uint_0 %11 %3 %uint_0 %uint_0
7166 %11 = OpExtInst %void %1 DebugTypeComposite %3 %uint_0 %8 %uint_0 %uint_0 %9 %3 %uint_0 %uint_0 %12
7167 %2 = OpFunction %void None %7
7173 CompileSuccessfully(spirv
, SPV_ENV_UNIVERSAL_1_6
);
7174 EXPECT_EQ(SPV_ERROR_INVALID_ID
, ValidateInstructions(SPV_ENV_UNIVERSAL_1_6
));
7175 EXPECT_THAT(getDiagnosticString(),
7176 HasSubstr(make_message("ID '11[%11]' has not been defined")));
7179 INSTANTIATE_TEST_SUITE_P(, ValidateIdWithMessage
, ::testing::Bool());
7183 } // namespace spvtools