1 // Copyright (c) 2018 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Validation tests for memory/storage
16 
17 #include <string>
18 #include <vector>
19 
20 #include "gmock/gmock.h"
21 #include "test/unit_spirv.h"
22 #include "test/val/val_code_generator.h"
23 #include "test/val/val_fixtures.h"
24 
25 // For pretty-printing tuples with spv_target_env.
operator <<(std::ostream & stream,spv_target_env target)26 std::ostream& operator<<(std::ostream& stream, spv_target_env target) {
27   switch (target) {
28     case SPV_ENV_UNIVERSAL_1_3:
29       return stream << "SPV_ENV_UNIVERSAL_1_3";
30     case SPV_ENV_UNIVERSAL_1_4:
31       return stream << "SPV_ENV_UNIVERSAL_1_4";
32     default:
33       return stream << (unsigned)target;
34   }
35 }
36 
37 namespace spvtools {
38 namespace val {
39 namespace {
40 
41 using ::testing::Combine;
42 using ::testing::Eq;
43 using ::testing::HasSubstr;
44 using ::testing::Values;
45 
46 using ValidateMemory = spvtest::ValidateBase<bool>;
47 
TEST_F(ValidateMemory,VulkanUniformConstantOnNonOpaqueResourceBad)48 TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceBad) {
49   std::string spirv = R"(
50 OpCapability Shader
51 OpMemoryModel Logical GLSL450
52 OpEntryPoint Fragment %func "func"
53 OpExecutionMode %func OriginUpperLeft
54 %float = OpTypeFloat 32
55 %float_ptr = OpTypePointer UniformConstant %float
56 %2 = OpVariable %float_ptr UniformConstant
57 %void = OpTypeVoid
58 %functy = OpTypeFunction %void
59 %func = OpFunction %void None %functy
60 %1 = OpLabel
61 OpReturn
62 OpFunctionEnd
63 )";
64   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
65   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
66   EXPECT_THAT(getDiagnosticString(),
67               AnyVUID("VUID-StandaloneSpirv-UniformConstant-04655"));
68   EXPECT_THAT(
69       getDiagnosticString(),
70       HasSubstr("Variables identified with the UniformConstant storage class "
71                 "are used only as handles to refer to opaque resources. Such "
72                 "variables must be typed as OpTypeImage, OpTypeSampler, "
73                 "OpTypeSampledImage, OpTypeAccelerationStructureKHR, "
74                 "or an array of one of these types."));
75 }
76 
TEST_F(ValidateMemory,VulkanUniformConstantOnOpaqueResourceGood)77 TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceGood) {
78   std::string spirv = R"(
79 OpCapability Shader
80 OpMemoryModel Logical GLSL450
81 OpEntryPoint Fragment %func "func"
82 OpExecutionMode %func OriginUpperLeft
83 OpDecorate %2 DescriptorSet 0
84 OpDecorate %2 Binding 0
85 %sampler = OpTypeSampler
86 %sampler_ptr = OpTypePointer UniformConstant %sampler
87 %2 = OpVariable %sampler_ptr UniformConstant
88 %void = OpTypeVoid
89 %functy = OpTypeFunction %void
90 %func = OpFunction %void None %functy
91 %1 = OpLabel
92 OpReturn
93 OpFunctionEnd
94 )";
95   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
96   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
97 }
98 
TEST_F(ValidateMemory,VulkanUniformConstantOnNonOpaqueResourceArrayBad)99 TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceArrayBad) {
100   std::string spirv = R"(
101 OpCapability Shader
102 OpMemoryModel Logical GLSL450
103 OpEntryPoint Fragment %func "func"
104 OpExecutionMode %func OriginUpperLeft
105 %float = OpTypeFloat 32
106 %uint = OpTypeInt 32 0
107 %array_size = OpConstant %uint 5
108 %array = OpTypeArray %float %array_size
109 %array_ptr = OpTypePointer UniformConstant %array
110 %2 = OpVariable %array_ptr UniformConstant
111 %void = OpTypeVoid
112 %functy = OpTypeFunction %void
113 %func = OpFunction %void None %functy
114 %1 = OpLabel
115 OpReturn
116 OpFunctionEnd
117 )";
118   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
119   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
120   EXPECT_THAT(getDiagnosticString(),
121               AnyVUID("VUID-StandaloneSpirv-UniformConstant-04655"));
122   EXPECT_THAT(
123       getDiagnosticString(),
124       HasSubstr("Variables identified with the UniformConstant storage class "
125                 "are used only as handles to refer to opaque resources. Such "
126                 "variables must be typed as OpTypeImage, OpTypeSampler, "
127                 "OpTypeSampledImage, OpTypeAccelerationStructureKHR, "
128                 "or an array of one of these types."));
129 }
130 
TEST_F(ValidateMemory,VulkanUniformConstantOnOpaqueResourceArrayGood)131 TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceArrayGood) {
132   std::string spirv = R"(
133 OpCapability Shader
134 OpMemoryModel Logical GLSL450
135 OpEntryPoint Fragment %func "func"
136 OpExecutionMode %func OriginUpperLeft
137 OpDecorate %2 DescriptorSet 0
138 OpDecorate %2 Binding 0
139 %sampler = OpTypeSampler
140 %uint = OpTypeInt 32 0
141 %array_size = OpConstant %uint 5
142 %array = OpTypeArray %sampler %array_size
143 %array_ptr = OpTypePointer UniformConstant %array
144 %2 = OpVariable %array_ptr UniformConstant
145 %void = OpTypeVoid
146 %functy = OpTypeFunction %void
147 %func = OpFunction %void None %functy
148 %1 = OpLabel
149 OpReturn
150 OpFunctionEnd
151 )";
152   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
153   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
154 }
155 
TEST_F(ValidateMemory,VulkanUniformConstantOnOpaqueResourceRuntimeArrayGood)156 TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceRuntimeArrayGood) {
157   std::string spirv = R"(
158 OpCapability RuntimeDescriptorArrayEXT
159 OpCapability Shader
160 OpExtension "SPV_EXT_descriptor_indexing"
161 OpMemoryModel Logical GLSL450
162 OpEntryPoint Fragment %func "func"
163 OpExecutionMode %func OriginUpperLeft
164 OpDecorate %2 DescriptorSet 0
165 OpDecorate %2 Binding 0
166 %sampler = OpTypeSampler
167 %uint = OpTypeInt 32 0
168 %array = OpTypeRuntimeArray %sampler
169 %array_ptr = OpTypePointer UniformConstant %array
170 %2 = OpVariable %array_ptr UniformConstant
171 %void = OpTypeVoid
172 %functy = OpTypeFunction %void
173 %func = OpFunction %void None %functy
174 %1 = OpLabel
175 OpReturn
176 OpFunctionEnd
177 )";
178   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
179   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
180 }
181 
TEST_F(ValidateMemory,VulkanUniformOnIntBad)182 TEST_F(ValidateMemory, VulkanUniformOnIntBad) {
183   char src[] = R"(
184             OpCapability Shader
185             OpMemoryModel Logical GLSL450
186             OpEntryPoint GLCompute %kernel "main"
187             OpExecutionMode %kernel LocalSize 1 1 1
188 
189             OpDecorate %var DescriptorSet 0
190             OpDecorate %var Binding 0
191 
192   %voidty = OpTypeVoid
193 %kernelty = OpTypeFunction %voidty
194    %intty = OpTypeInt 32 0
195    %varty = OpTypePointer Uniform %intty
196    %value = OpConstant %intty 42
197 
198      %var = OpVariable %varty Uniform
199 
200   %kernel = OpFunction %voidty None %kernelty
201    %label = OpLabel
202             OpStore %var %value
203             OpReturn
204             OpFunctionEnd
205 )";
206   CompileSuccessfully(src, SPV_ENV_VULKAN_1_1);
207   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
208   EXPECT_THAT(getDiagnosticString(),
209               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
210   EXPECT_THAT(
211       getDiagnosticString(),
212       HasSubstr("From Vulkan spec:\n"
213                 "Variables identified with the Uniform storage class are used "
214                 "to access transparent buffer backed resources. Such variables "
215                 "must be typed as OpTypeStruct, or an array of this type"));
216 }
217 
218 // #version 440
219 // #extension GL_EXT_nonuniform_qualifier : enable
220 // layout(binding = 1) uniform sampler2D s2d[][2];
221 // layout(location = 0) in nonuniformEXT int i;
222 // void main()
223 // {
224 //     vec4 v = texture(s2d[i][i], vec2(0.3));
225 // }
TEST_F(ValidateMemory,VulkanUniformOnRuntimeArrayOfArrayBad)226 TEST_F(ValidateMemory, VulkanUniformOnRuntimeArrayOfArrayBad) {
227   char src[] = R"(
228                OpCapability Shader
229                OpCapability ShaderNonUniformEXT
230                OpCapability RuntimeDescriptorArrayEXT
231                OpCapability SampledImageArrayNonUniformIndexingEXT
232                OpExtension "SPV_EXT_descriptor_indexing"
233           %1 = OpExtInstImport "GLSL.std.450"
234                OpMemoryModel Logical GLSL450
235                OpEntryPoint Vertex %main "main" %i
236                OpSource GLSL 440
237                OpSourceExtension "GL_EXT_nonuniform_qualifier"
238                OpName %main "main"
239                OpName %v "v"
240                OpName %s2d "s2d"
241                OpName %i "i"
242                OpDecorate %s2d DescriptorSet 0
243                OpDecorate %s2d Binding 1
244                OpDecorate %i Location 0
245                OpDecorate %i NonUniformEXT
246                OpDecorate %21 NonUniformEXT
247                OpDecorate %22 NonUniformEXT
248                OpDecorate %25 NonUniformEXT
249        %void = OpTypeVoid
250           %3 = OpTypeFunction %void
251       %float = OpTypeFloat 32
252     %v4float = OpTypeVector %float 4
253 %_ptr_Function_v4float = OpTypePointer Function %v4float
254          %10 = OpTypeImage %float 2D 0 0 0 1 Unknown
255          %11 = OpTypeSampledImage %10
256        %uint = OpTypeInt 32 0
257      %uint_2 = OpConstant %uint 2
258 %_arr_11_uint_2 = OpTypeArray %11 %uint_2
259 %_runtimearr__arr_11_uint_2 = OpTypeRuntimeArray %_arr_11_uint_2
260 %_ptr_Uniform__runtimearr__arr_11_uint_2 = OpTypePointer Uniform %_runtimearr__arr_11_uint_2
261         %s2d = OpVariable %_ptr_Uniform__runtimearr__arr_11_uint_2 Uniform
262         %int = OpTypeInt 32 1
263 %_ptr_Input_int = OpTypePointer Input %int
264           %i = OpVariable %_ptr_Input_int Input
265 %_ptr_Uniform_11 = OpTypePointer Uniform %11
266     %v2float = OpTypeVector %float 2
267 %float_0_300000012 = OpConstant %float 0.300000012
268          %28 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012
269     %float_0 = OpConstant %float 0
270        %main = OpFunction %void None %3
271           %5 = OpLabel
272           %v = OpVariable %_ptr_Function_v4float Function
273          %21 = OpLoad %int %i
274          %22 = OpLoad %int %i
275          %24 = OpAccessChain %_ptr_Uniform_11 %s2d %21 %22
276          %25 = OpLoad %11 %24
277          %30 = OpImageSampleExplicitLod %v4float %25 %28 Lod %float_0
278                OpStore %v %30
279                OpReturn
280                OpFunctionEnd
281 )";
282   CompileSuccessfully(src, SPV_ENV_VULKAN_1_1);
283   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
284   EXPECT_THAT(getDiagnosticString(),
285               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
286   EXPECT_THAT(
287       getDiagnosticString(),
288       HasSubstr("From Vulkan spec:\n"
289                 "Variables identified with the Uniform storage class are used "
290                 "to access transparent buffer backed resources. Such variables "
291                 "must be typed as OpTypeStruct, or an array of this type"));
292 }
293 
294 // #version 440
295 // layout (set=1, binding=1) uniform sampler2D variableName[2][2];
296 // void main() {
297 // }
TEST_F(ValidateMemory,VulkanUniformOnArrayOfArrayBad)298 TEST_F(ValidateMemory, VulkanUniformOnArrayOfArrayBad) {
299   char src[] = R"(
300                OpCapability Shader
301           %1 = OpExtInstImport "GLSL.std.450"
302                OpMemoryModel Logical GLSL450
303                OpEntryPoint Vertex %main "main"
304                OpSource GLSL 440
305                OpName %main "main"
306                OpName %variableName "variableName"
307                OpDecorate %variableName DescriptorSet 1
308                OpDecorate %variableName Binding 1
309        %void = OpTypeVoid
310           %3 = OpTypeFunction %void
311       %float = OpTypeFloat 32
312           %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
313           %8 = OpTypeSampledImage %7
314        %uint = OpTypeInt 32 0
315      %uint_2 = OpConstant %uint 2
316 %_arr_8_uint_2 = OpTypeArray %8 %uint_2
317 %_arr__arr_8_uint_2_uint_2 = OpTypeArray %_arr_8_uint_2 %uint_2
318 %_ptr_Uniform__arr__arr_8_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_8_uint_2_uint_2
319 %variableName = OpVariable %_ptr_Uniform__arr__arr_8_uint_2_uint_2 Uniform
320        %main = OpFunction %void None %3
321           %5 = OpLabel
322                OpReturn
323                OpFunctionEnd
324 )";
325   CompileSuccessfully(src, SPV_ENV_VULKAN_1_1);
326   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
327   EXPECT_THAT(getDiagnosticString(),
328               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
329   EXPECT_THAT(
330       getDiagnosticString(),
331       HasSubstr("From Vulkan spec:\n"
332                 "Variables identified with the Uniform storage class are used "
333                 "to access transparent buffer backed resources. Such variables "
334                 "must be typed as OpTypeStruct, or an array of this type"));
335 }
336 
TEST_F(ValidateMemory,MismatchingStorageClassesBad)337 TEST_F(ValidateMemory, MismatchingStorageClassesBad) {
338   std::string spirv = R"(
339 OpCapability Shader
340 OpMemoryModel Logical GLSL450
341 OpEntryPoint Fragment %func "func"
342 OpExecutionMode %func OriginUpperLeft
343 %float = OpTypeFloat 32
344 %float_ptr = OpTypePointer Uniform %float
345 %void = OpTypeVoid
346 %functy = OpTypeFunction %void
347 %func = OpFunction %void None %functy
348 %1 = OpLabel
349 %2 = OpVariable %float_ptr Function
350 OpReturn
351 OpFunctionEnd
352 )";
353   CompileSuccessfully(spirv.c_str());
354   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
355   EXPECT_THAT(
356       getDiagnosticString(),
357       HasSubstr(
358           "From SPIR-V spec, section 3.32.8 on OpVariable:\n"
359           "Its Storage Class operand must be the same as the Storage Class "
360           "operand of the result type."));
361 }
362 
TEST_F(ValidateMemory,MatchingStorageClassesGood)363 TEST_F(ValidateMemory, MatchingStorageClassesGood) {
364   std::string spirv = R"(
365 OpCapability Shader
366 OpMemoryModel Logical GLSL450
367 OpEntryPoint Fragment %func "func"
368 OpExecutionMode %func OriginUpperLeft
369 %float = OpTypeFloat 32
370 %float_ptr = OpTypePointer Function %float
371 %void = OpTypeVoid
372 %functy = OpTypeFunction %void
373 %func = OpFunction %void None %functy
374 %1 = OpLabel
375 %2 = OpVariable %float_ptr Function
376 OpReturn
377 OpFunctionEnd
378 )";
379   CompileSuccessfully(spirv.c_str());
380   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
381 }
382 
TEST_F(ValidateMemory,VulkanInitializerWithOutputStorageClassesGood)383 TEST_F(ValidateMemory, VulkanInitializerWithOutputStorageClassesGood) {
384   std::string spirv = R"(
385 OpCapability Shader
386 OpMemoryModel Logical GLSL450
387 OpEntryPoint Fragment %func "func"
388 OpExecutionMode %func OriginUpperLeft
389 %float = OpTypeFloat 32
390 %float_ptr = OpTypePointer Output %float
391 %init_val = OpConstant %float 1.0
392 %1 = OpVariable %float_ptr Output %init_val
393 %void = OpTypeVoid
394 %functy = OpTypeFunction %void
395 %func = OpFunction %void None %functy
396 %2 = OpLabel
397 OpReturn
398 OpFunctionEnd
399 )";
400   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
401   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
402 }
403 
TEST_F(ValidateMemory,VulkanInitializerWithFunctionStorageClassesGood)404 TEST_F(ValidateMemory, VulkanInitializerWithFunctionStorageClassesGood) {
405   std::string spirv = R"(
406 OpCapability Shader
407 OpMemoryModel Logical GLSL450
408 OpEntryPoint Fragment %func "func"
409 OpExecutionMode %func OriginUpperLeft
410 %float = OpTypeFloat 32
411 %float_ptr = OpTypePointer Function %float
412 %init_val = OpConstant %float 1.0
413 %void = OpTypeVoid
414 %functy = OpTypeFunction %void
415 %func = OpFunction %void None %functy
416 %1 = OpLabel
417 %2 = OpVariable %float_ptr Function %init_val
418 OpReturn
419 OpFunctionEnd
420 )";
421   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
422   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
423 }
424 
TEST_F(ValidateMemory,VulkanInitializerWithPrivateStorageClassesGood)425 TEST_F(ValidateMemory, VulkanInitializerWithPrivateStorageClassesGood) {
426   std::string spirv = R"(
427 OpCapability Shader
428 OpMemoryModel Logical GLSL450
429 OpEntryPoint Fragment %func "func"
430 OpExecutionMode %func OriginUpperLeft
431 %float = OpTypeFloat 32
432 %float_ptr = OpTypePointer Private %float
433 %init_val = OpConstant %float 1.0
434 %1 = OpVariable %float_ptr Private %init_val
435 %void = OpTypeVoid
436 %functy = OpTypeFunction %void
437 %func = OpFunction %void None %functy
438 %2 = OpLabel
439 OpReturn
440 OpFunctionEnd
441 )";
442   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
443   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
444 }
445 
TEST_F(ValidateMemory,VulkanInitializerWithDisallowedStorageClassesBad)446 TEST_F(ValidateMemory, VulkanInitializerWithDisallowedStorageClassesBad) {
447   std::string spirv = R"(
448 OpCapability Shader
449 OpMemoryModel Logical GLSL450
450 OpEntryPoint Fragment %func "func"
451 OpExecutionMode %func OriginUpperLeft
452 %float = OpTypeFloat 32
453 %float_ptr = OpTypePointer Input %float
454 %init_val = OpConstant %float 1.0
455 %1 = OpVariable %float_ptr Input %init_val
456 %void = OpTypeVoid
457 %functy = OpTypeFunction %void
458 %func = OpFunction %void None %functy
459 %2 = OpLabel
460 OpReturn
461 OpFunctionEnd
462 )";
463   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
464   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
465   EXPECT_THAT(getDiagnosticString(),
466               AnyVUID("VUID-StandaloneSpirv-OpVariable-04651"));
467   EXPECT_THAT(
468       getDiagnosticString(),
469       HasSubstr("OpVariable, <id> '5[%5]', has a disallowed initializer & "
470                 "storage class combination.\nFrom Vulkan spec:\nVariable "
471                 "declarations that include initializers must have one of the "
472                 "following storage classes: Output, Private, Function or "
473                 "Workgroup\n  %5 "
474                 "= OpVariable %_ptr_Input_float Input %float_1\n"));
475 }
476 
TEST_F(ValidateMemory,UniversalInitializerWithDisallowedStorageClassesBad)477 TEST_F(ValidateMemory, UniversalInitializerWithDisallowedStorageClassesBad) {
478   std::string spirv = R"(
479 OpCapability Shader
480 OpMemoryModel Logical GLSL450
481 OpEntryPoint Fragment %func "func"
482 OpExecutionMode %func OriginUpperLeft
483 %float = OpTypeFloat 32
484 %float_ptr = OpTypePointer Input %float
485 %init_val = OpConstant %float 1.0
486 %1 = OpVariable %float_ptr Input %init_val
487 %void = OpTypeVoid
488 %functy = OpTypeFunction %void
489 %func = OpFunction %void None %functy
490 %2 = OpLabel
491 OpReturn
492 OpFunctionEnd
493 )";
494   CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_3);
495   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
496   EXPECT_THAT(
497       getDiagnosticString(),
498       HasSubstr(
499           "OpVariable, <id> '5[%5]', initializer are not allowed for Input"));
500 }
501 
TEST_F(ValidateMemory,InitializerWithTaskPayloadWorkgroupEXT)502 TEST_F(ValidateMemory, InitializerWithTaskPayloadWorkgroupEXT) {
503   std::string spirv = R"(
504                OpCapability MeshShadingEXT
505                OpExtension "SPV_EXT_mesh_shader"
506                OpMemoryModel Logical GLSL450
507                OpEntryPoint TaskEXT %main "main" %payload
508        %void = OpTypeVoid
509        %func = OpTypeFunction %void
510        %uint = OpTypeInt 32 0
511 %_ptr_TaskPayloadWorkgroupEXT = OpTypePointer TaskPayloadWorkgroupEXT %uint
512      %uint_1 = OpConstant %uint 1
513     %payload = OpVariable %_ptr_TaskPayloadWorkgroupEXT TaskPayloadWorkgroupEXT %uint_1
514        %main = OpFunction %void None %func
515       %label = OpLabel
516                OpReturn
517                OpFunctionEnd
518 )";
519   CompileSuccessfully(spirv.c_str(), SPV_ENV_UNIVERSAL_1_5);
520   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
521   EXPECT_THAT(getDiagnosticString(),
522               HasSubstr("OpVariable, <id> '2[%2]', initializer are not allowed "
523                         "for TaskPayloadWorkgroupEXT"));
524 }
525 
TEST_F(ValidateMemory,ArrayLenCorrectResultType)526 TEST_F(ValidateMemory, ArrayLenCorrectResultType) {
527   std::string spirv = R"(
528                OpCapability Shader
529                OpMemoryModel Logical GLSL450
530                OpEntryPoint Fragment %1 "main"
531                OpExecutionMode %1 OriginUpperLeft
532        %void = OpTypeVoid
533           %3 = OpTypeFunction %void
534       %float = OpTypeFloat 32
535      %uint = OpTypeInt 32 0
536 %_runtimearr_float = OpTypeRuntimeArray %float
537   %_struct_7 = OpTypeStruct %_runtimearr_float
538 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
539           %1 = OpFunction %void None %3
540           %9 = OpLabel
541          %10 = OpVariable %_ptr_Function__struct_7 Function
542          %11 = OpArrayLength %uint %10 0
543                OpReturn
544                OpFunctionEnd
545 
546 )";
547 
548   CompileSuccessfully(spirv.c_str());
549   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
550 }
551 
TEST_F(ValidateMemory,ArrayLenIndexCorrectWith2Members)552 TEST_F(ValidateMemory, ArrayLenIndexCorrectWith2Members) {
553   std::string spirv = R"(
554                OpCapability Shader
555                OpMemoryModel Logical GLSL450
556                OpEntryPoint Fragment %1 "main"
557                OpExecutionMode %1 OriginUpperLeft
558        %void = OpTypeVoid
559           %3 = OpTypeFunction %void
560       %float = OpTypeFloat 32
561      %uint = OpTypeInt 32 0
562 %_runtimearr_float = OpTypeRuntimeArray %float
563   %_struct_7 = OpTypeStruct %float %_runtimearr_float
564 %_ptr_Function__struct_7  = OpTypePointer Function %_struct_7
565           %1 = OpFunction %void None %3
566           %9 = OpLabel
567          %10 = OpVariable %_ptr_Function__struct_7  Function
568          %11 = OpArrayLength %uint %10 1
569                OpReturn
570                OpFunctionEnd
571 
572 )";
573 
574   CompileSuccessfully(spirv.c_str());
575   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
576 }
577 
TEST_F(ValidateMemory,ArrayLenResultNotIntType)578 TEST_F(ValidateMemory, ArrayLenResultNotIntType) {
579   std::string spirv = R"(
580                OpCapability Shader
581                OpMemoryModel Logical GLSL450
582                OpEntryPoint Fragment %1 "main"
583                OpExecutionMode %1 OriginUpperLeft
584        %void = OpTypeVoid
585           %3 = OpTypeFunction %void
586       %float = OpTypeFloat 32
587 %_runtimearr_float = OpTypeRuntimeArray %float
588   %_struct_6 = OpTypeStruct %_runtimearr_float
589 %_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
590           %1 = OpFunction %void None %3
591           %8 = OpLabel
592           %9 = OpVariable %_ptr_Function__struct_6 Function
593          %10 = OpArrayLength %float %9 0
594                OpReturn
595                OpFunctionEnd
596 )";
597 
598   CompileSuccessfully(spirv.c_str());
599   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
600   EXPECT_THAT(
601       getDiagnosticString(),
602       HasSubstr(
603           "The Result Type of OpArrayLength <id> '10[%10]' must be OpTypeInt "
604           "with width 32 and signedness 0.\n  %10 = OpArrayLength %float %9 "
605           "0\n"));
606 }
607 
TEST_F(ValidateMemory,ArrayLenResultNot32bits)608 TEST_F(ValidateMemory, ArrayLenResultNot32bits) {
609   std::string spirv = R"(
610                OpCapability Shader
611                OpCapability Int16
612                OpMemoryModel Logical GLSL450
613                OpEntryPoint Fragment %1 "main"
614                OpExecutionMode %1 OriginUpperLeft
615        %void = OpTypeVoid
616           %3 = OpTypeFunction %void
617       %float = OpTypeFloat 32
618      %ushort = OpTypeInt 16 0
619 %_runtimearr_float = OpTypeRuntimeArray %float
620   %_struct_7 = OpTypeStruct %_runtimearr_float
621 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
622           %1 = OpFunction %void None %3
623           %9 = OpLabel
624          %10 = OpVariable %_ptr_Function__struct_7 Function
625          %11 = OpArrayLength %ushort %10 0
626                OpReturn
627                OpFunctionEnd
628 
629 )";
630 
631   CompileSuccessfully(spirv.c_str());
632   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
633   EXPECT_THAT(
634       getDiagnosticString(),
635       HasSubstr(
636           "The Result Type of OpArrayLength <id> '11[%11]' must be OpTypeInt "
637           "with width 32 and signedness 0.\n  %11 = OpArrayLength %ushort %10 "
638           "0\n"));
639 }
640 
TEST_F(ValidateMemory,ArrayLenResultSigned)641 TEST_F(ValidateMemory, ArrayLenResultSigned) {
642   std::string spirv = R"(
643                OpCapability Shader
644                OpMemoryModel Logical GLSL450
645                OpEntryPoint Fragment %1 "main"
646                OpExecutionMode %1 OriginUpperLeft
647        %void = OpTypeVoid
648           %3 = OpTypeFunction %void
649       %float = OpTypeFloat 32
650      %int = OpTypeInt 32 1
651 %_runtimearr_float = OpTypeRuntimeArray %float
652   %_struct_7 = OpTypeStruct %_runtimearr_float
653 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7
654           %1 = OpFunction %void None %3
655           %9 = OpLabel
656          %10 = OpVariable %_ptr_Function__struct_7 Function
657          %11 = OpArrayLength %int %10 0
658                OpReturn
659                OpFunctionEnd
660 
661 )";
662 
663   CompileSuccessfully(spirv.c_str());
664   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
665   EXPECT_THAT(
666       getDiagnosticString(),
667       HasSubstr(
668           "The Result Type of OpArrayLength <id> '11[%11]' must be OpTypeInt "
669           "with width 32 and signedness 0.\n  %11 = OpArrayLength %int %10 "
670           "0\n"));
671 }
672 
TEST_F(ValidateMemory,ArrayLenInputNotStruct)673 TEST_F(ValidateMemory, ArrayLenInputNotStruct) {
674   std::string spirv = R"(
675                OpCapability Shader
676                OpMemoryModel Logical GLSL450
677                OpEntryPoint Fragment %1 "main"
678                OpExecutionMode %1 OriginUpperLeft
679        %void = OpTypeVoid
680           %3 = OpTypeFunction %void
681       %float = OpTypeFloat 32
682      %uint = OpTypeInt 32 0
683 %_runtimearr_float = OpTypeRuntimeArray %float
684   %_struct_7 = OpTypeStruct %_runtimearr_float
685 %_ptr_Function_float = OpTypePointer Function %float
686           %1 = OpFunction %void None %3
687           %9 = OpLabel
688          %10 = OpVariable %_ptr_Function_float Function
689          %11 = OpArrayLength %uint %10 0
690                OpReturn
691                OpFunctionEnd
692 
693 )";
694 
695   CompileSuccessfully(spirv.c_str());
696   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
697   EXPECT_THAT(getDiagnosticString(),
698               HasSubstr("The Structure's type in OpArrayLength <id> '11[%11]' "
699                         "must be a pointer to an OpTypeStruct."));
700 }
701 
TEST_F(ValidateMemory,ArrayLenInputLastMemberNoRTA)702 TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA) {
703   std::string spirv = R"(
704                OpCapability Shader
705                OpMemoryModel Logical GLSL450
706                OpEntryPoint Fragment %1 "main"
707                OpExecutionMode %1 OriginUpperLeft
708        %void = OpTypeVoid
709           %3 = OpTypeFunction %void
710       %float = OpTypeFloat 32
711      %uint = OpTypeInt 32 0
712 %_runtimearr_float = OpTypeRuntimeArray %float
713   %_struct_7 = OpTypeStruct %float
714 %_ptr_Function__struct_7  = OpTypePointer Function %_struct_7
715           %1 = OpFunction %void None %3
716           %9 = OpLabel
717          %10 = OpVariable %_ptr_Function__struct_7  Function
718          %11 = OpArrayLength %uint %10 0
719                OpReturn
720                OpFunctionEnd
721 
722 )";
723 
724   CompileSuccessfully(spirv.c_str());
725   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
726   EXPECT_THAT(
727       getDiagnosticString(),
728       HasSubstr("The Structure's last member in OpArrayLength <id> '11[%11]' "
729                 "must be an OpTypeRuntimeArray.\n  %11 = OpArrayLength %uint "
730                 "%10 0\n"));
731 }
732 
TEST_F(ValidateMemory,ArrayLenInputLastMemberNoRTA2)733 TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA2) {
734   std::string spirv = R"(
735                OpCapability Shader
736                OpMemoryModel Logical GLSL450
737                OpEntryPoint Fragment %1 "main"
738                OpExecutionMode %1 OriginUpperLeft
739        %void = OpTypeVoid
740           %3 = OpTypeFunction %void
741       %float = OpTypeFloat 32
742      %uint = OpTypeInt 32 0
743 %_runtimearr_float = OpTypeRuntimeArray %float
744   %_struct_7 = OpTypeStruct %_runtimearr_float %float
745 %_ptr_Function__struct_7  = OpTypePointer Function %_struct_7
746           %1 = OpFunction %void None %3
747           %9 = OpLabel
748          %10 = OpVariable %_ptr_Function__struct_7  Function
749          %11 = OpArrayLength %uint %10 1
750                OpReturn
751                OpFunctionEnd
752 
753 )";
754 
755   CompileSuccessfully(spirv.c_str());
756   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
757   EXPECT_THAT(
758       getDiagnosticString(),
759       HasSubstr("The Structure's last member in OpArrayLength <id> '11[%11]' "
760                 "must be an OpTypeRuntimeArray.\n  %11 = OpArrayLength %uint "
761                 "%10 1\n"));
762 }
763 
TEST_F(ValidateMemory,ArrayLenIndexNotLastMember)764 TEST_F(ValidateMemory, ArrayLenIndexNotLastMember) {
765   std::string spirv = R"(
766                OpCapability Shader
767                OpMemoryModel Logical GLSL450
768                OpEntryPoint Fragment %1 "main"
769                OpExecutionMode %1 OriginUpperLeft
770        %void = OpTypeVoid
771           %3 = OpTypeFunction %void
772       %float = OpTypeFloat 32
773      %uint = OpTypeInt 32 0
774 %_runtimearr_float = OpTypeRuntimeArray %float
775   %_struct_7 = OpTypeStruct %float %_runtimearr_float
776 %_ptr_Function__struct_7  = OpTypePointer Function %_struct_7
777           %1 = OpFunction %void None %3
778           %9 = OpLabel
779          %10 = OpVariable %_ptr_Function__struct_7  Function
780          %11 = OpArrayLength %uint %10 0
781                OpReturn
782                OpFunctionEnd
783 
784 )";
785 
786   CompileSuccessfully(spirv.c_str());
787   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
788   EXPECT_THAT(
789       getDiagnosticString(),
790       HasSubstr(
791           "The array member in OpArrayLength <id> '11[%11]' must be an the "
792           "last member of the struct.\n  %11 = OpArrayLength %uint %10 0\n"));
793 }
794 
TEST_F(ValidateMemory,ArrayLenIndexNotPointerToStruct)795 TEST_F(ValidateMemory, ArrayLenIndexNotPointerToStruct) {
796   std::string spirv = R"(
797                OpCapability Shader
798                OpMemoryModel Logical GLSL450
799                OpEntryPoint Fragment %1 "main"
800                OpExecutionMode %1 OriginUpperLeft
801        %void = OpTypeVoid
802           %3 = OpTypeFunction %void
803       %float = OpTypeFloat 32
804      %uint = OpTypeInt 32 0
805 %_runtimearr_float = OpTypeRuntimeArray %float
806   %_struct_7 = OpTypeStruct %float
807 %_ptr_Function__struct_7  = OpTypePointer Function %_struct_7
808           %1 = OpFunction %void None %3
809           %9 = OpLabel
810          %10 = OpVariable %_ptr_Function__struct_7  Function
811          %11 = OpLoad %_struct_7 %10
812          %12 = OpArrayLength %uint %11 0
813                OpReturn
814                OpFunctionEnd
815 
816 )";
817 
818   CompileSuccessfully(spirv.c_str());
819   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
820   EXPECT_THAT(
821       getDiagnosticString(),
822       HasSubstr(
823           "The Structure's type in OpArrayLength <id> '12[%12]' must be a "
824           "pointer to an OpTypeStruct.\n  %12 = OpArrayLength %uint %11 0\n"));
825 }
826 
TEST_F(ValidateMemory,ArrayLenPointerIsAType)827 TEST_F(ValidateMemory, ArrayLenPointerIsAType) {
828   std::string spirv = R"(
829                OpCapability Shader
830                OpMemoryModel Logical GLSL450
831                OpEntryPoint Fragment %1 "main"
832                OpExecutionMode %1 OriginUpperLeft
833        %void = OpTypeVoid
834           %3 = OpTypeFunction %void
835       %float = OpTypeFloat 32
836        %uint = OpTypeInt 32 0
837           %1 = OpFunction %void None %3
838           %9 = OpLabel
839          %12 = OpArrayLength %uint %float 0
840                OpReturn
841                OpFunctionEnd
842 
843 )";
844 
845   CompileSuccessfully(spirv.c_str());
846   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
847   EXPECT_THAT(getDiagnosticString(),
848               HasSubstr("Operand '4[%float]' cannot be a "
849                         "type"));
850 }
851 
TEST_F(ValidateMemory,PushConstantNotStructGood)852 TEST_F(ValidateMemory, PushConstantNotStructGood) {
853   std::string spirv = R"(
854             OpCapability Shader
855             OpMemoryModel Logical GLSL450
856             OpEntryPoint Fragment %1 "main"
857             OpExecutionMode %1 OriginUpperLeft
858 
859     %void = OpTypeVoid
860   %voidfn = OpTypeFunction %void
861    %float = OpTypeFloat 32
862      %ptr = OpTypePointer PushConstant %float
863       %pc = OpVariable %ptr PushConstant
864 
865        %1 = OpFunction %void None %voidfn
866    %label = OpLabel
867             OpReturn
868             OpFunctionEnd
869 )";
870   CompileSuccessfully(spirv);
871   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
872 }
873 
TEST_F(ValidateMemory,VulkanPushConstantNotStructBad)874 TEST_F(ValidateMemory, VulkanPushConstantNotStructBad) {
875   std::string spirv = R"(
876             OpCapability Shader
877             OpMemoryModel Logical GLSL450
878             OpEntryPoint Fragment %1 "main"
879             OpExecutionMode %1 OriginUpperLeft
880 
881     %void = OpTypeVoid
882   %voidfn = OpTypeFunction %void
883    %float = OpTypeFloat 32
884      %ptr = OpTypePointer PushConstant %float
885       %pc = OpVariable %ptr PushConstant
886 
887        %1 = OpFunction %void None %voidfn
888    %label = OpLabel
889             OpReturn
890             OpFunctionEnd
891 )";
892   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
893   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
894   EXPECT_THAT(getDiagnosticString(),
895               AnyVUID("VUID-StandaloneSpirv-PushConstant-06808"));
896   EXPECT_THAT(
897       getDiagnosticString(),
898       HasSubstr("PushConstant OpVariable <id> '6[%6]' has illegal "
899                 "type.\nFrom Vulkan spec, Push Constant Interface section:\n"
900                 "Such variables must be typed as OpTypeStruct"));
901 }
902 
TEST_F(ValidateMemory,VulkanPushConstantArrayOfStructBad)903 TEST_F(ValidateMemory, VulkanPushConstantArrayOfStructBad) {
904   std::string spirv = R"(
905             OpCapability Shader
906             OpMemoryModel Logical GLSL450
907             OpEntryPoint Fragment %1 "main"
908             OpExecutionMode %1 OriginUpperLeft
909 
910             OpDecorate %struct Block
911             OpMemberDecorate %struct 0 Offset 0
912 
913     %void = OpTypeVoid
914   %voidfn = OpTypeFunction %void
915    %float = OpTypeFloat 32
916      %int = OpTypeInt 32 0
917    %int_1 = OpConstant %int 1
918   %struct = OpTypeStruct %float
919    %array = OpTypeArray %struct %int_1
920      %ptr = OpTypePointer PushConstant %array
921       %pc = OpVariable %ptr PushConstant
922 
923        %1 = OpFunction %void None %voidfn
924    %label = OpLabel
925             OpReturn
926             OpFunctionEnd
927 )";
928   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
929   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
930   EXPECT_THAT(getDiagnosticString(),
931               AnyVUID("VUID-StandaloneSpirv-PushConstant-06808"));
932   EXPECT_THAT(
933       getDiagnosticString(),
934       HasSubstr("PushConstant OpVariable <id> '10[%10]' has illegal "
935                 "type.\nFrom Vulkan spec, Push Constant Interface section:\n"
936                 "Such variables must be typed as OpTypeStruct"));
937 }
938 
TEST_F(ValidateMemory,VulkanPushConstant)939 TEST_F(ValidateMemory, VulkanPushConstant) {
940   std::string spirv = R"(
941             OpCapability Shader
942             OpMemoryModel Logical GLSL450
943             OpEntryPoint Fragment %1 "main"
944             OpExecutionMode %1 OriginUpperLeft
945 
946             OpDecorate %struct Block
947             OpMemberDecorate %struct 0 Offset 0
948 
949     %void = OpTypeVoid
950   %voidfn = OpTypeFunction %void
951    %float = OpTypeFloat 32
952   %struct = OpTypeStruct %float
953      %ptr = OpTypePointer PushConstant %struct
954       %pc = OpVariable %ptr PushConstant
955 
956        %1 = OpFunction %void None %voidfn
957    %label = OpLabel
958             OpReturn
959             OpFunctionEnd
960 )";
961   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
962   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
963 }
964 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeLoadBad1)965 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad1) {
966   const std::string spirv = R"(
967 OpCapability Shader
968 OpCapability VulkanMemoryModelKHR
969 OpCapability Linkage
970 OpExtension "SPV_KHR_vulkan_memory_model"
971 OpMemoryModel Logical VulkanKHR
972 %void = OpTypeVoid
973 %int = OpTypeInt 32 0
974 %device = OpConstant %int 1
975 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
976 %var = OpVariable %int_ptr_ssbo StorageBuffer
977 %voidfn = OpTypeFunction %void
978 %func = OpFunction %void None %voidfn
979 %entry = OpLabel
980 %load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device
981 OpReturn
982 OpFunctionEnd
983 )";
984 
985   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
986   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
987             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
988   EXPECT_THAT(
989       getDiagnosticString(),
990       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
991                 "VulkanMemoryModelDeviceScopeKHR capability"));
992 }
993 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeLoadBad2)994 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad2) {
995   const std::string spirv = R"(
996 OpCapability Shader
997 OpCapability VulkanMemoryModelKHR
998 OpCapability Linkage
999 OpExtension "SPV_KHR_vulkan_memory_model"
1000 OpMemoryModel Logical VulkanKHR
1001 %void = OpTypeVoid
1002 %int = OpTypeInt 32 0
1003 %device = OpConstant %int 1
1004 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1005 %var = OpVariable %int_ptr_ssbo StorageBuffer
1006 %voidfn = OpTypeFunction %void
1007 %func = OpFunction %void None %voidfn
1008 %entry = OpLabel
1009 %load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device
1010 OpReturn
1011 OpFunctionEnd
1012 )";
1013 
1014   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1015   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1016             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1017   EXPECT_THAT(
1018       getDiagnosticString(),
1019       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1020                 "VulkanMemoryModelDeviceScopeKHR capability"));
1021 }
1022 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeLoadGood1)1023 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood1) {
1024   const std::string spirv = R"(
1025 OpCapability Shader
1026 OpCapability VulkanMemoryModelKHR
1027 OpCapability VulkanMemoryModelDeviceScopeKHR
1028 OpCapability Linkage
1029 OpExtension "SPV_KHR_vulkan_memory_model"
1030 OpMemoryModel Logical VulkanKHR
1031 %void = OpTypeVoid
1032 %int = OpTypeInt 32 0
1033 %device = OpConstant %int 1
1034 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1035 %var = OpVariable %int_ptr_ssbo StorageBuffer
1036 %voidfn = OpTypeFunction %void
1037 %func = OpFunction %void None %voidfn
1038 %entry = OpLabel
1039 %load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device
1040 OpReturn
1041 OpFunctionEnd
1042 )";
1043 
1044   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1045   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1046 }
1047 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeLoadGood2)1048 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood2) {
1049   const std::string spirv = R"(
1050 OpCapability Shader
1051 OpCapability VulkanMemoryModelKHR
1052 OpCapability VulkanMemoryModelDeviceScopeKHR
1053 OpCapability Linkage
1054 OpExtension "SPV_KHR_vulkan_memory_model"
1055 OpMemoryModel Logical VulkanKHR
1056 %void = OpTypeVoid
1057 %int = OpTypeInt 32 0
1058 %device = OpConstant %int 1
1059 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1060 %var = OpVariable %int_ptr_ssbo StorageBuffer
1061 %voidfn = OpTypeFunction %void
1062 %func = OpFunction %void None %voidfn
1063 %entry = OpLabel
1064 %load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device
1065 OpReturn
1066 OpFunctionEnd
1067 )";
1068 
1069   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1070   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1071 }
1072 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeStoreBad1)1073 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad1) {
1074   const std::string spirv = R"(
1075 OpCapability Shader
1076 OpCapability VulkanMemoryModelKHR
1077 OpCapability Linkage
1078 OpExtension "SPV_KHR_vulkan_memory_model"
1079 OpMemoryModel Logical VulkanKHR
1080 %void = OpTypeVoid
1081 %int = OpTypeInt 32 0
1082 %device = OpConstant %int 1
1083 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1084 %var = OpVariable %int_ptr_ssbo StorageBuffer
1085 %voidfn = OpTypeFunction %void
1086 %func = OpFunction %void None %voidfn
1087 %entry = OpLabel
1088 OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device
1089 OpReturn
1090 OpFunctionEnd
1091 )";
1092 
1093   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1094   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1095             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1096   EXPECT_THAT(
1097       getDiagnosticString(),
1098       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1099                 "VulkanMemoryModelDeviceScopeKHR capability"));
1100 }
1101 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeStoreBad2)1102 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad2) {
1103   const std::string spirv = R"(
1104 OpCapability Shader
1105 OpCapability VulkanMemoryModelKHR
1106 OpCapability Linkage
1107 OpExtension "SPV_KHR_vulkan_memory_model"
1108 OpMemoryModel Logical VulkanKHR
1109 %void = OpTypeVoid
1110 %int = OpTypeInt 32 0
1111 %device = OpConstant %int 1
1112 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1113 %var = OpVariable %int_ptr_ssbo StorageBuffer
1114 %voidfn = OpTypeFunction %void
1115 %func = OpFunction %void None %voidfn
1116 %entry = OpLabel
1117 OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device
1118 OpReturn
1119 OpFunctionEnd
1120 )";
1121 
1122   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1123   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1124             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1125   EXPECT_THAT(
1126       getDiagnosticString(),
1127       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1128                 "VulkanMemoryModelDeviceScopeKHR capability"));
1129 }
1130 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeStoreGood1)1131 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood1) {
1132   const std::string spirv = R"(
1133 OpCapability Shader
1134 OpCapability VulkanMemoryModelKHR
1135 OpCapability VulkanMemoryModelDeviceScopeKHR
1136 OpCapability Linkage
1137 OpExtension "SPV_KHR_vulkan_memory_model"
1138 OpMemoryModel Logical VulkanKHR
1139 %void = OpTypeVoid
1140 %int = OpTypeInt 32 0
1141 %device = OpConstant %int 1
1142 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1143 %var = OpVariable %int_ptr_ssbo StorageBuffer
1144 %voidfn = OpTypeFunction %void
1145 %func = OpFunction %void None %voidfn
1146 %entry = OpLabel
1147 OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device
1148 OpReturn
1149 OpFunctionEnd
1150 )";
1151 
1152   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1153   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1154 }
1155 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeStoreGood2)1156 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood2) {
1157   const std::string spirv = R"(
1158 OpCapability Shader
1159 OpCapability VulkanMemoryModelKHR
1160 OpCapability VulkanMemoryModelDeviceScopeKHR
1161 OpCapability Linkage
1162 OpExtension "SPV_KHR_vulkan_memory_model"
1163 OpMemoryModel Logical VulkanKHR
1164 %void = OpTypeVoid
1165 %int = OpTypeInt 32 0
1166 %device = OpConstant %int 1
1167 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1168 %var = OpVariable %int_ptr_ssbo StorageBuffer
1169 %voidfn = OpTypeFunction %void
1170 %func = OpFunction %void None %voidfn
1171 %entry = OpLabel
1172 OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device
1173 OpReturn
1174 OpFunctionEnd
1175 )";
1176 
1177   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1178   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1179 }
1180 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemoryBad1)1181 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad1) {
1182   const std::string spirv = R"(
1183 OpCapability Shader
1184 OpCapability VulkanMemoryModelKHR
1185 OpCapability Linkage
1186 OpExtension "SPV_KHR_vulkan_memory_model"
1187 OpMemoryModel Logical VulkanKHR
1188 %void = OpTypeVoid
1189 %int = OpTypeInt 32 0
1190 %device = OpConstant %int 1
1191 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1192 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1193 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1194 %voidfn = OpTypeFunction %void
1195 %func = OpFunction %void None %voidfn
1196 %entry = OpLabel
1197 OpCopyMemory %var1 %var2 MakePointerAvailableKHR|NonPrivatePointerKHR %device
1198 OpReturn
1199 OpFunctionEnd
1200 )";
1201 
1202   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1203   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1204             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1205   EXPECT_THAT(
1206       getDiagnosticString(),
1207       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1208                 "VulkanMemoryModelDeviceScopeKHR capability"));
1209 }
1210 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemoryBad2)1211 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad2) {
1212   const std::string spirv = R"(
1213 OpCapability Shader
1214 OpCapability VulkanMemoryModelKHR
1215 OpCapability Linkage
1216 OpExtension "SPV_KHR_vulkan_memory_model"
1217 OpMemoryModel Logical VulkanKHR
1218 %void = OpTypeVoid
1219 %int = OpTypeInt 32 0
1220 %device = OpConstant %int 1
1221 %workgroup = OpConstant %int 1
1222 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1223 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1224 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1225 %voidfn = OpTypeFunction %void
1226 %func = OpFunction %void None %voidfn
1227 %entry = OpLabel
1228 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
1229 OpReturn
1230 OpFunctionEnd
1231 )";
1232 
1233   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1234   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1235             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1236   EXPECT_THAT(
1237       getDiagnosticString(),
1238       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1239                 "VulkanMemoryModelDeviceScopeKHR capability"));
1240 }
1241 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemoryBad3)1242 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad3) {
1243   const std::string spirv = R"(
1244 OpCapability Shader
1245 OpCapability VulkanMemoryModelKHR
1246 OpCapability Linkage
1247 OpExtension "SPV_KHR_vulkan_memory_model"
1248 OpMemoryModel Logical VulkanKHR
1249 %void = OpTypeVoid
1250 %int = OpTypeInt 32 0
1251 %device = OpConstant %int 1
1252 %workgroup = OpConstant %int 1
1253 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1254 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1255 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1256 %voidfn = OpTypeFunction %void
1257 %func = OpFunction %void None %voidfn
1258 %entry = OpLabel
1259 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
1260 OpReturn
1261 OpFunctionEnd
1262 )";
1263 
1264   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1265   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1266             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1267   EXPECT_THAT(
1268       getDiagnosticString(),
1269       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1270                 "VulkanMemoryModelDeviceScopeKHR capability"));
1271 }
1272 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemoryGood2)1273 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood2) {
1274   const std::string spirv = R"(
1275 OpCapability Shader
1276 OpCapability VulkanMemoryModelKHR
1277 OpCapability VulkanMemoryModelDeviceScopeKHR
1278 OpCapability Linkage
1279 OpExtension "SPV_KHR_vulkan_memory_model"
1280 OpMemoryModel Logical VulkanKHR
1281 %void = OpTypeVoid
1282 %int = OpTypeInt 32 0
1283 %device = OpConstant %int 1
1284 %workgroup = OpConstant %int 2
1285 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1286 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1287 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1288 %voidfn = OpTypeFunction %void
1289 %func = OpFunction %void None %voidfn
1290 %entry = OpLabel
1291 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
1292 OpReturn
1293 OpFunctionEnd
1294 )";
1295 
1296   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1297   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1298 }
1299 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemoryGood3)1300 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood3) {
1301   const std::string spirv = R"(
1302 OpCapability Shader
1303 OpCapability VulkanMemoryModelKHR
1304 OpCapability VulkanMemoryModelDeviceScopeKHR
1305 OpCapability Linkage
1306 OpExtension "SPV_KHR_vulkan_memory_model"
1307 OpMemoryModel Logical VulkanKHR
1308 %void = OpTypeVoid
1309 %int = OpTypeInt 32 0
1310 %device = OpConstant %int 1
1311 %workgroup = OpConstant %int 2
1312 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1313 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1314 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1315 %voidfn = OpTypeFunction %void
1316 %func = OpFunction %void None %voidfn
1317 %entry = OpLabel
1318 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
1319 OpReturn
1320 OpFunctionEnd
1321 )";
1322 
1323   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1324   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1325 }
1326 
TEST_F(ValidateMemory,VulkanMemoryModelCopyMemoryTwoAccessAvVisBadBinaryV13)1327 TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessAvVisBadBinaryV13) {
1328   const std::string spirv = R"(
1329 OpCapability Shader
1330 OpCapability VulkanMemoryModelKHR
1331 OpCapability VulkanMemoryModelDeviceScopeKHR
1332 OpCapability Linkage
1333 OpExtension "SPV_KHR_vulkan_memory_model"
1334 OpMemoryModel Logical VulkanKHR
1335 %void = OpTypeVoid
1336 %int = OpTypeInt 32 0
1337 %device = OpConstant %int 1
1338 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1339 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1340 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1341 %voidfn = OpTypeFunction %void
1342 %func = OpFunction %void None %voidfn
1343 %entry = OpLabel
1344 OpCopyMemory %var1 %var2
1345   MakePointerAvailableKHR|NonPrivatePointerKHR %device
1346   MakePointerVisibleKHR|NonPrivatePointerKHR %device
1347 OpReturn
1348 OpFunctionEnd
1349 )";
1350 
1351   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1352   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1353             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1354   EXPECT_THAT(
1355       getDiagnosticString(),
1356       HasSubstr(
1357           "with two memory access operands requires SPIR-V 1.4 or later"));
1358 }
1359 
TEST_F(ValidateMemory,VulkanMemoryModelCopyMemoryTwoAccessAvVisGood)1360 TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessAvVisGood) {
1361   const std::string spirv = R"(
1362 OpCapability Shader
1363 OpCapability VulkanMemoryModelKHR
1364 OpCapability VulkanMemoryModelDeviceScopeKHR
1365 OpCapability Linkage
1366 OpExtension "SPV_KHR_vulkan_memory_model"
1367 OpMemoryModel Logical VulkanKHR
1368 %void = OpTypeVoid
1369 %int = OpTypeInt 32 0
1370 %device = OpConstant %int 1
1371 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1372 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1373 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1374 %voidfn = OpTypeFunction %void
1375 %func = OpFunction %void None %voidfn
1376 %entry = OpLabel
1377 OpCopyMemory %var1 %var2
1378   MakePointerAvailableKHR|NonPrivatePointerKHR %device
1379   MakePointerVisibleKHR|NonPrivatePointerKHR %device
1380 OpReturn
1381 OpFunctionEnd
1382 )";
1383 
1384   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1385   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1386   EXPECT_THAT(getDiagnosticString(), Eq(""));
1387 }
1388 
TEST_F(ValidateMemory,VulkanMemoryModelCopyMemoryTwoAccessFirstWithAvBad)1389 TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessFirstWithAvBad) {
1390   const std::string spirv = R"(
1391 OpCapability Shader
1392 OpCapability VulkanMemoryModelKHR
1393 OpCapability VulkanMemoryModelDeviceScopeKHR
1394 OpCapability Linkage
1395 OpExtension "SPV_KHR_vulkan_memory_model"
1396 OpMemoryModel Logical VulkanKHR
1397 %void = OpTypeVoid
1398 %int = OpTypeInt 32 0
1399 %device = OpConstant %int 1
1400 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1401 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1402 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1403 %voidfn = OpTypeFunction %void
1404 %func = OpFunction %void None %voidfn
1405 %entry = OpLabel
1406 OpCopyMemory %var1 %var2
1407   MakePointerAvailableKHR|NonPrivatePointerKHR %device
1408   MakePointerAvailableKHR|NonPrivatePointerKHR %device
1409 OpReturn
1410 OpFunctionEnd
1411 )";
1412 
1413   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1414   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1415             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1416   EXPECT_THAT(
1417       getDiagnosticString(),
1418       HasSubstr(
1419           "Source memory access must not include MakePointerAvailableKHR\n"
1420           "  OpCopyMemory %5 %6 MakePointerAvailable|NonPrivatePointer"
1421           " %uint_1 MakePointerAvailable|NonPrivatePointer %uint_1"));
1422 }
1423 
TEST_F(ValidateMemory,VulkanMemoryModelCopyMemoryTwoAccessSecondWithVisBad)1424 TEST_F(ValidateMemory, VulkanMemoryModelCopyMemoryTwoAccessSecondWithVisBad) {
1425   const std::string spirv = R"(
1426 OpCapability Shader
1427 OpCapability VulkanMemoryModelKHR
1428 OpCapability VulkanMemoryModelDeviceScopeKHR
1429 OpCapability Linkage
1430 OpExtension "SPV_KHR_vulkan_memory_model"
1431 OpMemoryModel Logical VulkanKHR
1432 %void = OpTypeVoid
1433 %int = OpTypeInt 32 0
1434 %device = OpConstant %int 1
1435 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1436 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1437 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1438 %voidfn = OpTypeFunction %void
1439 %func = OpFunction %void None %voidfn
1440 %entry = OpLabel
1441 OpCopyMemory %var1 %var2
1442   MakePointerVisibleKHR|NonPrivatePointerKHR %device
1443   MakePointerVisibleKHR|NonPrivatePointerKHR %device
1444 OpReturn
1445 OpFunctionEnd
1446 )";
1447 
1448   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1449   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1450             ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1451   EXPECT_THAT(
1452       getDiagnosticString(),
1453       HasSubstr("Target memory access must not include MakePointerVisibleKHR\n"
1454                 "  OpCopyMemory %5 %6 MakePointerVisible|NonPrivatePointer"
1455                 " %uint_1 MakePointerVisible|NonPrivatePointer %uint_1"));
1456 }
1457 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemorySizedBad1)1458 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad1) {
1459   const std::string spirv = R"(
1460 OpCapability Shader
1461 OpCapability VulkanMemoryModelKHR
1462 OpCapability Linkage
1463 OpCapability Addresses
1464 OpExtension "SPV_KHR_vulkan_memory_model"
1465 OpMemoryModel Logical VulkanKHR
1466 %void = OpTypeVoid
1467 %int = OpTypeInt 32 0
1468 %device = OpConstant %int 1
1469 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1470 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1471 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1472 %voidfn = OpTypeFunction %void
1473 %func = OpFunction %void None %voidfn
1474 %entry = OpLabel
1475 OpCopyMemorySized %var1 %var2 %device MakePointerAvailableKHR|NonPrivatePointerKHR %device
1476 OpReturn
1477 OpFunctionEnd
1478 )";
1479 
1480   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1481   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1482             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1483   EXPECT_THAT(
1484       getDiagnosticString(),
1485       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1486                 "VulkanMemoryModelDeviceScopeKHR capability"));
1487 }
1488 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemorySizedBad2)1489 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad2) {
1490   const std::string spirv = R"(
1491 OpCapability Shader
1492 OpCapability VulkanMemoryModelKHR
1493 OpCapability Linkage
1494 OpCapability Addresses
1495 OpExtension "SPV_KHR_vulkan_memory_model"
1496 OpMemoryModel Logical VulkanKHR
1497 %void = OpTypeVoid
1498 %int = OpTypeInt 32 0
1499 %device = OpConstant %int 1
1500 %workgroup = OpConstant %int 1
1501 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1502 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1503 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1504 %voidfn = OpTypeFunction %void
1505 %func = OpFunction %void None %voidfn
1506 %entry = OpLabel
1507 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
1508 OpReturn
1509 OpFunctionEnd
1510 )";
1511 
1512   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1513   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1514             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1515   EXPECT_THAT(
1516       getDiagnosticString(),
1517       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1518                 "VulkanMemoryModelDeviceScopeKHR capability"));
1519 }
1520 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemorySizedBad3)1521 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad3) {
1522   const std::string spirv = R"(
1523 OpCapability Shader
1524 OpCapability VulkanMemoryModelKHR
1525 OpCapability Linkage
1526 OpCapability Addresses
1527 OpExtension "SPV_KHR_vulkan_memory_model"
1528 OpMemoryModel Logical VulkanKHR
1529 %void = OpTypeVoid
1530 %int = OpTypeInt 32 0
1531 %device = OpConstant %int 1
1532 %workgroup = OpConstant %int 1
1533 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1534 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1535 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1536 %voidfn = OpTypeFunction %void
1537 %func = OpFunction %void None %voidfn
1538 %entry = OpLabel
1539 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
1540 OpReturn
1541 OpFunctionEnd
1542 )";
1543 
1544   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1545   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1546             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1547   EXPECT_THAT(
1548       getDiagnosticString(),
1549       HasSubstr("Use of device scope with VulkanKHR memory model requires the "
1550                 "VulkanMemoryModelDeviceScopeKHR capability"));
1551 }
1552 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemorySizedGood1)1553 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood1) {
1554   const std::string spirv = R"(
1555 OpCapability Shader
1556 OpCapability VulkanMemoryModelKHR
1557 OpCapability VulkanMemoryModelDeviceScopeKHR
1558 OpCapability Linkage
1559 OpCapability Addresses
1560 OpExtension "SPV_KHR_vulkan_memory_model"
1561 OpMemoryModel Logical VulkanKHR
1562 %void = OpTypeVoid
1563 %int = OpTypeInt 32 0
1564 %device = OpConstant %int 1
1565 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1566 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1567 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1568 %voidfn = OpTypeFunction %void
1569 %func = OpFunction %void None %voidfn
1570 %entry = OpLabel
1571 OpCopyMemorySized %var1 %var2 %device MakePointerAvailableKHR|NonPrivatePointerKHR %device
1572 OpReturn
1573 OpFunctionEnd
1574 )";
1575 
1576   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1577   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1578 }
1579 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemorySizedGood2)1580 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood2) {
1581   const std::string spirv = R"(
1582 OpCapability Shader
1583 OpCapability VulkanMemoryModelKHR
1584 OpCapability VulkanMemoryModelDeviceScopeKHR
1585 OpCapability Linkage
1586 OpCapability Addresses
1587 OpExtension "SPV_KHR_vulkan_memory_model"
1588 OpMemoryModel Logical VulkanKHR
1589 %void = OpTypeVoid
1590 %int = OpTypeInt 32 0
1591 %device = OpConstant %int 1
1592 %workgroup = OpConstant %int 2
1593 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1594 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1595 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1596 %voidfn = OpTypeFunction %void
1597 %func = OpFunction %void None %voidfn
1598 %entry = OpLabel
1599 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup
1600 OpReturn
1601 OpFunctionEnd
1602 )";
1603 
1604   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1605   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1606 }
1607 
TEST_F(ValidateMemory,VulkanMemoryModelDeviceScopeCopyMemorySizedGood3)1608 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood3) {
1609   const std::string spirv = R"(
1610 OpCapability Shader
1611 OpCapability VulkanMemoryModelKHR
1612 OpCapability VulkanMemoryModelDeviceScopeKHR
1613 OpCapability Linkage
1614 OpCapability Addresses
1615 OpExtension "SPV_KHR_vulkan_memory_model"
1616 OpMemoryModel Logical VulkanKHR
1617 %void = OpTypeVoid
1618 %int = OpTypeInt 32 0
1619 %device = OpConstant %int 1
1620 %workgroup = OpConstant %int 2
1621 %int_ptr_ssbo = OpTypePointer StorageBuffer %int
1622 %var1 = OpVariable %int_ptr_ssbo StorageBuffer
1623 %var2 = OpVariable %int_ptr_ssbo StorageBuffer
1624 %voidfn = OpTypeFunction %void
1625 %func = OpFunction %void None %voidfn
1626 %entry = OpLabel
1627 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device
1628 OpReturn
1629 OpFunctionEnd
1630 )";
1631 
1632   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
1633   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1634 }
1635 
TEST_F(ValidateMemory,ArrayLengthStructIsLabel)1636 TEST_F(ValidateMemory, ArrayLengthStructIsLabel) {
1637   const std::string spirv = R"(
1638 OpCapability Tessellation
1639 OpMemoryModel Logical GLSL450
1640 OpName %20 "incorrect"
1641 %void = OpTypeVoid
1642 %3 = OpTypeFunction %void
1643 %float = OpTypeFloat 32
1644 %v4float = OpTypeVector %float 4
1645 %uint = OpTypeInt 32 0
1646 %4 = OpFunction %void None %3
1647 %20 = OpLabel
1648 %24 = OpArrayLength %uint %20 0
1649 %25 = OpLoad %v4float %24
1650 OpReturnValue %25
1651 OpFunctionEnd
1652 )";
1653 
1654   CompileSuccessfully(spirv);
1655   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1656   EXPECT_THAT(getDiagnosticString(),
1657               HasSubstr("Operand '1[%incorrect]' requires a type"));
1658 }
1659 
TEST_F(ValidateMemory,PSBLoadAlignedSuccess)1660 TEST_F(ValidateMemory, PSBLoadAlignedSuccess) {
1661   const std::string body = R"(
1662 OpCapability PhysicalStorageBufferAddresses
1663 OpCapability Int64
1664 OpCapability Shader
1665 OpExtension "SPV_EXT_physical_storage_buffer"
1666 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1667 OpEntryPoint Fragment %main "main"
1668 OpExecutionMode %main OriginUpperLeft
1669 OpDecorate %val1 AliasedPointer
1670 %uint64 = OpTypeInt 64 0
1671 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1672 %pptr_f = OpTypePointer Function %ptr
1673 %void = OpTypeVoid
1674 %voidfn = OpTypeFunction %void
1675 %main = OpFunction %void None %voidfn
1676 %entry = OpLabel
1677 %val1 = OpVariable %pptr_f Function
1678 %val2 = OpLoad %ptr %val1
1679 %val3 = OpLoad %uint64 %val2 Aligned 8
1680 OpReturn
1681 OpFunctionEnd
1682 )";
1683 
1684   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1685   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1686 }
1687 
TEST_F(ValidateMemory,PSBLoadAlignedMissing)1688 TEST_F(ValidateMemory, PSBLoadAlignedMissing) {
1689   const std::string body = R"(
1690 OpCapability PhysicalStorageBufferAddresses
1691 OpCapability Int64
1692 OpCapability Shader
1693 OpExtension "SPV_EXT_physical_storage_buffer"
1694 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1695 OpEntryPoint Fragment %main "main"
1696 OpExecutionMode %main OriginUpperLeft
1697 OpDecorate %val1 AliasedPointer
1698 %uint64 = OpTypeInt 64 0
1699 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1700 %pptr_f = OpTypePointer Function %ptr
1701 %void = OpTypeVoid
1702 %voidfn = OpTypeFunction %void
1703 %main = OpFunction %void None %voidfn
1704 %entry = OpLabel
1705 %val1 = OpVariable %pptr_f Function
1706 %val2 = OpLoad %ptr %val1
1707 %val3 = OpLoad %uint64 %val2
1708 OpReturn
1709 OpFunctionEnd
1710 )";
1711 
1712   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1713   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1714   EXPECT_THAT(getDiagnosticString(),
1715               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
1716   EXPECT_THAT(
1717       getDiagnosticString(),
1718       HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
1719 }
1720 
TEST_F(ValidateMemory,PSBLoadAlignedMissingWithOtherOperand)1721 TEST_F(ValidateMemory, PSBLoadAlignedMissingWithOtherOperand) {
1722   const std::string body = R"(
1723 OpCapability PhysicalStorageBufferAddresses
1724 OpCapability Int64
1725 OpCapability Shader
1726 OpExtension "SPV_EXT_physical_storage_buffer"
1727 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1728 OpEntryPoint Fragment %main "main"
1729 OpExecutionMode %main OriginUpperLeft
1730 OpDecorate %val1 AliasedPointer
1731 %uint64 = OpTypeInt 64 0
1732 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1733 %pptr_f = OpTypePointer Function %ptr
1734 %void = OpTypeVoid
1735 %voidfn = OpTypeFunction %void
1736 %main = OpFunction %void None %voidfn
1737 %entry = OpLabel
1738 %val1 = OpVariable %pptr_f Function
1739 %val2 = OpLoad %ptr %val1
1740 %val3 = OpLoad %uint64 %val2 Volatile
1741 OpReturn
1742 OpFunctionEnd
1743 )";
1744 
1745   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1746   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1747   EXPECT_THAT(getDiagnosticString(),
1748               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
1749   EXPECT_THAT(
1750       getDiagnosticString(),
1751       HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
1752 }
1753 
TEST_F(ValidateMemory,PSBStoreAlignedSuccess)1754 TEST_F(ValidateMemory, PSBStoreAlignedSuccess) {
1755   const std::string body = R"(
1756 OpCapability PhysicalStorageBufferAddresses
1757 OpCapability Int64
1758 OpCapability Shader
1759 OpExtension "SPV_EXT_physical_storage_buffer"
1760 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1761 OpEntryPoint Fragment %main "main"
1762 OpExecutionMode %main OriginUpperLeft
1763 OpDecorate %val1 AliasedPointer
1764 %uint64 = OpTypeInt 64 0
1765 %u64_1 = OpConstant %uint64 1
1766 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1767 %pptr_f = OpTypePointer Function %ptr
1768 %void = OpTypeVoid
1769 %voidfn = OpTypeFunction %void
1770 %main = OpFunction %void None %voidfn
1771 %entry = OpLabel
1772 %val1 = OpVariable %pptr_f Function
1773 %val2 = OpLoad %ptr %val1
1774 OpStore %val2 %u64_1 Aligned 8
1775 OpReturn
1776 OpFunctionEnd
1777 )";
1778 
1779   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1780   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1781 }
1782 
TEST_F(ValidateMemory,PSBStoreAlignedMissing)1783 TEST_F(ValidateMemory, PSBStoreAlignedMissing) {
1784   const std::string body = R"(
1785 OpCapability PhysicalStorageBufferAddresses
1786 OpCapability Int64
1787 OpCapability Shader
1788 OpExtension "SPV_EXT_physical_storage_buffer"
1789 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1790 OpEntryPoint Fragment %main "main"
1791 OpExecutionMode %main OriginUpperLeft
1792 OpDecorate %val1 AliasedPointer
1793 %uint64 = OpTypeInt 64 0
1794 %u64_1 = OpConstant %uint64 1
1795 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1796 %pptr_f = OpTypePointer Function %ptr
1797 %void = OpTypeVoid
1798 %voidfn = OpTypeFunction %void
1799 %main = OpFunction %void None %voidfn
1800 %entry = OpLabel
1801 %val1 = OpVariable %pptr_f Function
1802 %val2 = OpLoad %ptr %val1
1803 OpStore %val2 %u64_1 None
1804 OpReturn
1805 OpFunctionEnd
1806 )";
1807 
1808   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1809   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1810   EXPECT_THAT(getDiagnosticString(),
1811               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
1812   EXPECT_THAT(
1813       getDiagnosticString(),
1814       HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
1815 }
1816 
TEST_F(ValidateMemory,PSBCopyMemoryAlignedSuccess)1817 TEST_F(ValidateMemory, PSBCopyMemoryAlignedSuccess) {
1818   const std::string body = R"(
1819 OpCapability PhysicalStorageBufferAddresses
1820 OpCapability Int64
1821 OpCapability Shader
1822 OpExtension "SPV_EXT_physical_storage_buffer"
1823 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1824 OpEntryPoint Fragment %main "main"
1825 OpExecutionMode %main OriginUpperLeft
1826 OpDecorate %val1 AliasedPointer
1827 %int = OpTypeInt 32 0
1828 %uint64 = OpTypeInt 64 0
1829 %u64_1 = OpConstant %uint64 1
1830 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1831 %pptr_f = OpTypePointer Function %ptr
1832 %void = OpTypeVoid
1833 %voidfn = OpTypeFunction %void
1834 %main = OpFunction %void None %voidfn
1835 %entry = OpLabel
1836 %val1 = OpVariable %pptr_f Function
1837 %val2 = OpLoad %ptr %val1
1838 %val3 = OpLoad %ptr %val1
1839 OpCopyMemory %val2 %val3 Aligned 4
1840 OpCopyMemory %val3 %val2 Aligned 4 Aligned 4
1841 OpReturn
1842 OpFunctionEnd
1843 )";
1844 
1845   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1846   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1847 }
1848 
TEST_F(ValidateMemory,PSBCopyMemoryAlignedMissingTarget)1849 TEST_F(ValidateMemory, PSBCopyMemoryAlignedMissingTarget) {
1850   const std::string body = R"(
1851 OpCapability PhysicalStorageBufferAddresses
1852 OpCapability Int64
1853 OpCapability Shader
1854 OpExtension "SPV_EXT_physical_storage_buffer"
1855 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1856 OpEntryPoint Fragment %main "main"
1857 OpExecutionMode %main OriginUpperLeft
1858 OpDecorate %val1 AliasedPointer
1859 %int = OpTypeInt 32 0
1860 %uint64 = OpTypeInt 64 0
1861 %u64_1 = OpConstant %uint64 1
1862 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1863 %pptr_f = OpTypePointer Function %ptr
1864 %void = OpTypeVoid
1865 %voidfn = OpTypeFunction %void
1866 %main = OpFunction %void None %voidfn
1867 %entry = OpLabel
1868 %val1 = OpVariable %pptr_f Function
1869 %val2 = OpLoad %ptr %val1
1870 %val3 = OpLoad %ptr %val1
1871 OpCopyMemory %val2 %val3 Volatile Aligned 4
1872 OpReturn
1873 OpFunctionEnd
1874 )";
1875 
1876   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1877   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1878   EXPECT_THAT(getDiagnosticString(),
1879               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
1880   EXPECT_THAT(
1881       getDiagnosticString(),
1882       HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
1883 }
1884 
TEST_F(ValidateMemory,PSBCopyMemoryAlignedMissingSource)1885 TEST_F(ValidateMemory, PSBCopyMemoryAlignedMissingSource) {
1886   const std::string body = R"(
1887 OpCapability PhysicalStorageBufferAddresses
1888 OpCapability Int64
1889 OpCapability Shader
1890 OpExtension "SPV_EXT_physical_storage_buffer"
1891 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1892 OpEntryPoint Fragment %main "main"
1893 OpExecutionMode %main OriginUpperLeft
1894 OpDecorate %val1 AliasedPointer
1895 %int = OpTypeInt 32 0
1896 %uint64 = OpTypeInt 64 0
1897 %u64_1 = OpConstant %uint64 1
1898 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1899 %pptr_f = OpTypePointer Function %ptr
1900 %void = OpTypeVoid
1901 %voidfn = OpTypeFunction %void
1902 %main = OpFunction %void None %voidfn
1903 %entry = OpLabel
1904 %val1 = OpVariable %pptr_f Function
1905 %val2 = OpLoad %ptr %val1
1906 %val3 = OpLoad %ptr %val1
1907 OpCopyMemory %val2 %val3 Aligned 4 Volatile
1908 OpReturn
1909 OpFunctionEnd
1910 )";
1911 
1912   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1913   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1914   EXPECT_THAT(getDiagnosticString(),
1915               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
1916   EXPECT_THAT(
1917       getDiagnosticString(),
1918       HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
1919 }
1920 
TEST_F(ValidateMemory,PSBCopyMemoryAlignedMissingBoth)1921 TEST_F(ValidateMemory, PSBCopyMemoryAlignedMissingBoth) {
1922   const std::string body = R"(
1923 OpCapability PhysicalStorageBufferAddresses
1924 OpCapability Int64
1925 OpCapability Shader
1926 OpExtension "SPV_EXT_physical_storage_buffer"
1927 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1928 OpEntryPoint Fragment %main "main"
1929 OpExecutionMode %main OriginUpperLeft
1930 OpDecorate %val1 AliasedPointer
1931 %int = OpTypeInt 32 0
1932 %uint64 = OpTypeInt 64 0
1933 %u64_1 = OpConstant %uint64 1
1934 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1935 %pptr_f = OpTypePointer Function %ptr
1936 %void = OpTypeVoid
1937 %voidfn = OpTypeFunction %void
1938 %main = OpFunction %void None %voidfn
1939 %entry = OpLabel
1940 %val1 = OpVariable %pptr_f Function
1941 %val2 = OpLoad %ptr %val1
1942 %val3 = OpLoad %ptr %val1
1943 OpCopyMemory %val2 %val3 Volatile
1944 OpReturn
1945 OpFunctionEnd
1946 )";
1947 
1948   CompileSuccessfully(body.c_str(), SPV_ENV_VULKAN_1_2);
1949   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_2));
1950   EXPECT_THAT(getDiagnosticString(),
1951               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04708"));
1952   EXPECT_THAT(
1953       getDiagnosticString(),
1954       HasSubstr("Memory accesses with PhysicalStorageBuffer must use Aligned"));
1955 }
1956 
TEST_F(ValidateMemory,PSBVariable)1957 TEST_F(ValidateMemory, PSBVariable) {
1958   const std::string body = R"(
1959 OpCapability PhysicalStorageBufferAddresses
1960 OpCapability Int64
1961 OpCapability Shader
1962 OpExtension "SPV_EXT_physical_storage_buffer"
1963 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1964 OpEntryPoint Fragment %main "main"
1965 OpExecutionMode %main OriginUpperLeft
1966 OpDecorate %val1 AliasedPointer
1967 %uint64 = OpTypeInt 64 0
1968 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1969 %val1 = OpVariable %ptr PhysicalStorageBuffer
1970 %void = OpTypeVoid
1971 %voidfn = OpTypeFunction %void
1972 %main = OpFunction %void None %voidfn
1973 %entry = OpLabel
1974 OpReturn
1975 OpFunctionEnd
1976 )";
1977 
1978   CompileSuccessfully(body);
1979   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1980   EXPECT_THAT(
1981       getDiagnosticString(),
1982       HasSubstr("PhysicalStorageBuffer must not be used with OpVariable"));
1983 }
1984 
GenCoopMatLoadStoreShader(const std::string & storeMemoryAccess,const std::string & loadMemoryAccess)1985 std::string GenCoopMatLoadStoreShader(const std::string& storeMemoryAccess,
1986                                       const std::string& loadMemoryAccess) {
1987   std::string s = R"(
1988 OpCapability Shader
1989 OpCapability GroupNonUniform
1990 OpCapability VulkanMemoryModelKHR
1991 OpCapability CooperativeMatrixNV
1992 OpExtension "SPV_KHR_vulkan_memory_model"
1993 OpExtension "SPV_NV_cooperative_matrix"
1994 %1 = OpExtInstImport "GLSL.std.450"
1995 OpMemoryModel Logical VulkanKHR
1996 OpEntryPoint GLCompute %4 "main" %11 %21
1997 OpExecutionMode %4 LocalSize 1 1 1
1998 OpDecorate %11 BuiltIn SubgroupId
1999 OpDecorate %21 BuiltIn WorkgroupId
2000 OpDecorate %74 ArrayStride 4
2001 OpMemberDecorate %75 0 Offset 0
2002 OpDecorate %75 Block
2003 OpDecorate %77 DescriptorSet 0
2004 OpDecorate %77 Binding 0
2005 OpDecorate %92 ArrayStride 4
2006 OpMemberDecorate %93 0 Offset 0
2007 OpDecorate %93 Block
2008 OpDecorate %95 DescriptorSet 0
2009 OpDecorate %95 Binding 1
2010 OpDecorate %102 ArrayStride 4
2011 OpMemberDecorate %103 0 Offset 0
2012 OpDecorate %103 Block
2013 OpDecorate %105 DescriptorSet 0
2014 OpDecorate %105 Binding 2
2015 OpDecorate %117 ArrayStride 4
2016 OpMemberDecorate %118 0 Offset 0
2017 OpDecorate %118 Block
2018 OpDecorate %120 DescriptorSet 0
2019 OpDecorate %120 Binding 3
2020 OpDecorate %123 SpecId 2
2021 OpDecorate %124 SpecId 3
2022 OpDecorate %125 SpecId 4
2023 OpDecorate %126 SpecId 5
2024 OpDecorate %127 SpecId 0
2025 OpDecorate %128 SpecId 1
2026 OpDecorate %129 BuiltIn WorkgroupSize
2027 %2 = OpTypeVoid
2028 %3 = OpTypeFunction %2
2029 %6 = OpTypeInt 32 0
2030 %7 = OpTypeVector %6 2
2031 %8 = OpTypePointer Function %7
2032 %10 = OpTypePointer Input %6
2033 %11 = OpVariable %10 Input
2034 %13 = OpConstant %6 2
2035 %19 = OpTypeVector %6 3
2036 %20 = OpTypePointer Input %19
2037 %21 = OpVariable %20 Input
2038 %27 = OpConstantComposite %7 %13 %13
2039 %31 = OpTypePointer Function %6
2040 %33 = OpConstant %6 1024
2041 %34 = OpConstant %6 1
2042 %38 = OpConstant %6 8
2043 %39 = OpConstant %6 0
2044 %68 = OpTypeFloat 32
2045 %69 = OpConstant %6 16
2046 %70 = OpConstant %6 3
2047 %71 = OpTypeCooperativeMatrixNV %68 %70 %69 %38
2048 %72 = OpTypePointer Function %71
2049 %74 = OpTypeRuntimeArray %68
2050 %75 = OpTypeStruct %74
2051 %76 = OpTypePointer StorageBuffer %75
2052 %77 = OpVariable %76 StorageBuffer
2053 %78 = OpTypeInt 32 1
2054 %79 = OpConstant %78 0
2055 %81 = OpConstant %6 5
2056 %82 = OpTypePointer StorageBuffer %68
2057 %84 = OpConstant %6 64
2058 %85 = OpTypeBool
2059 %86 = OpConstantFalse %85
2060 %88 = OpTypePointer Private %71
2061 %89 = OpVariable %88 Private
2062 %92 = OpTypeRuntimeArray %68
2063 %93 = OpTypeStruct %92
2064 %94 = OpTypePointer StorageBuffer %93
2065 %95 = OpVariable %94 StorageBuffer
2066 %99 = OpVariable %88 Private
2067 %102 = OpTypeRuntimeArray %68
2068 %103 = OpTypeStruct %102
2069 %104 = OpTypePointer StorageBuffer %103
2070 %105 = OpVariable %104 StorageBuffer
2071 %109 = OpVariable %88 Private
2072 %111 = OpVariable %88 Private
2073 %112 = OpSpecConstantOp %6 CooperativeMatrixLengthNV %71
2074 %113 = OpSpecConstantOp %78 IAdd %112 %79
2075 %117 = OpTypeRuntimeArray %68
2076 %118 = OpTypeStruct %117
2077 %119 = OpTypePointer StorageBuffer %118
2078 %120 = OpVariable %119 StorageBuffer
2079 %123 = OpSpecConstant %78 1
2080 %124 = OpSpecConstant %78 1
2081 %125 = OpSpecConstant %78 1
2082 %126 = OpSpecConstant %78 1
2083 %127 = OpSpecConstant %6 1
2084 %128 = OpSpecConstant %6 1
2085 %129 = OpSpecConstantComposite %19 %127 %128 %34
2086 %4 = OpFunction %2 None %3
2087 %5 = OpLabel
2088 %9 = OpVariable %8 Function
2089 %18 = OpVariable %8 Function
2090 %32 = OpVariable %31 Function
2091 %44 = OpVariable %31 Function
2092 %52 = OpVariable %31 Function
2093 %60 = OpVariable %31 Function
2094 %73 = OpVariable %72 Function
2095 %91 = OpVariable %72 Function
2096 %101 = OpVariable %72 Function
2097 %12 = OpLoad %6 %11
2098 %14 = OpUMod %6 %12 %13
2099 %15 = OpLoad %6 %11
2100 %16 = OpUDiv %6 %15 %13
2101 %17 = OpCompositeConstruct %7 %14 %16
2102 OpStore %9 %17
2103 %22 = OpLoad %19 %21
2104 %23 = OpVectorShuffle %7 %22 %22 0 1
2105 %24 = OpCompositeExtract %6 %23 0
2106 %25 = OpCompositeExtract %6 %23 1
2107 %26 = OpCompositeConstruct %7 %24 %25
2108 %28 = OpIMul %7 %26 %27
2109 %29 = OpLoad %7 %9
2110 %30 = OpIAdd %7 %28 %29
2111 OpStore %18 %30
2112 %35 = OpAccessChain %31 %18 %34
2113 %36 = OpLoad %6 %35
2114 %37 = OpIMul %6 %33 %36
2115 %40 = OpAccessChain %31 %18 %39
2116 %41 = OpLoad %6 %40
2117 %42 = OpIMul %6 %38 %41
2118 %43 = OpIAdd %6 %37 %42
2119 OpStore %32 %43
2120 %45 = OpAccessChain %31 %18 %34
2121 %46 = OpLoad %6 %45
2122 %47 = OpIMul %6 %33 %46
2123 %48 = OpAccessChain %31 %18 %39
2124 %49 = OpLoad %6 %48
2125 %50 = OpIMul %6 %38 %49
2126 %51 = OpIAdd %6 %47 %50
2127 OpStore %44 %51
2128 %53 = OpAccessChain %31 %18 %34
2129 %54 = OpLoad %6 %53
2130 %55 = OpIMul %6 %33 %54
2131 %56 = OpAccessChain %31 %18 %39
2132 %57 = OpLoad %6 %56
2133 %58 = OpIMul %6 %38 %57
2134 %59 = OpIAdd %6 %55 %58
2135 OpStore %52 %59
2136 %61 = OpAccessChain %31 %18 %34
2137 %62 = OpLoad %6 %61
2138 %63 = OpIMul %6 %33 %62
2139 %64 = OpAccessChain %31 %18 %39
2140 %65 = OpLoad %6 %64
2141 %66 = OpIMul %6 %38 %65
2142 %67 = OpIAdd %6 %63 %66
2143 OpStore %60 %67
2144 %80 = OpLoad %6 %32
2145 %83 = OpAccessChain %82 %77 %79 %80
2146 %87 = OpCooperativeMatrixLoadNV %71 %83 %84 %86 )" +
2147                   loadMemoryAccess + R"( %81
2148 OpStore %73 %87
2149 %90 = OpLoad %71 %73
2150 OpStore %89 %90
2151 %96 = OpLoad %6 %44
2152 %97 = OpAccessChain %82 %95 %79 %96
2153 %98 = OpCooperativeMatrixLoadNV %71 %97 %84 %86 MakePointerVisibleKHR|NonPrivatePointerKHR %81
2154 OpStore %91 %98
2155 %100 = OpLoad %71 %91
2156 OpStore %99 %100
2157 %106 = OpLoad %6 %52
2158 %107 = OpAccessChain %82 %105 %79 %106
2159 %108 = OpCooperativeMatrixLoadNV %71 %107 %84 %86 MakePointerVisibleKHR|NonPrivatePointerKHR %81
2160 OpStore %101 %108
2161 %110 = OpLoad %71 %101
2162 OpStore %109 %110
2163 %114 = OpConvertSToF %68 %113
2164 %115 = OpCompositeConstruct %71 %114
2165 OpStore %111 %115
2166 %116 = OpLoad %71 %111
2167 %121 = OpLoad %6 %60
2168 %122 = OpAccessChain %82 %120 %79 %121
2169 OpCooperativeMatrixStoreNV %122 %116 %84 %86 )" + storeMemoryAccess + R"( %81
2170 OpReturn
2171 OpFunctionEnd
2172 )";
2173 
2174   return s;
2175 }
2176 
TEST_F(ValidateMemory,CoopMatLoadStoreSuccess)2177 TEST_F(ValidateMemory, CoopMatLoadStoreSuccess) {
2178   std::string spirv =
2179       GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR",
2180                                 "MakePointerVisibleKHR|NonPrivatePointerKHR");
2181 
2182   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2183   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2184 }
2185 
TEST_F(ValidateMemory,CoopMatStoreMemoryAccessFail)2186 TEST_F(ValidateMemory, CoopMatStoreMemoryAccessFail) {
2187   std::string spirv =
2188       GenCoopMatLoadStoreShader("MakePointerVisibleKHR|NonPrivatePointerKHR",
2189                                 "MakePointerVisibleKHR|NonPrivatePointerKHR");
2190 
2191   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2192   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2193   EXPECT_THAT(getDiagnosticString(),
2194               HasSubstr("MakePointerVisibleKHR cannot be used with OpStore"));
2195 }
2196 
TEST_F(ValidateMemory,CoopMatLoadMemoryAccessFail)2197 TEST_F(ValidateMemory, CoopMatLoadMemoryAccessFail) {
2198   std::string spirv =
2199       GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR",
2200                                 "MakePointerAvailableKHR|NonPrivatePointerKHR");
2201 
2202   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2203   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2204   EXPECT_THAT(getDiagnosticString(),
2205               HasSubstr("MakePointerAvailableKHR cannot be used with OpLoad"));
2206 }
2207 
TEST_F(ValidateMemory,CoopMatInvalidStorageClassFail)2208 TEST_F(ValidateMemory, CoopMatInvalidStorageClassFail) {
2209   const std::string body =
2210       R"(
2211 OpCapability Shader
2212 OpCapability Float16
2213 OpCapability CooperativeMatrixNV
2214 OpExtension "SPV_NV_cooperative_matrix"
2215 OpMemoryModel Logical GLSL450
2216 OpEntryPoint GLCompute %main "main"
2217 %void = OpTypeVoid
2218 %func = OpTypeFunction %void
2219 %f16 = OpTypeFloat 16
2220 %u32 = OpTypeInt 32 0
2221 
2222 %u32_8 = OpConstant %u32 8
2223 %subgroup = OpConstant %u32 3
2224 
2225 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
2226 
2227 %str = OpTypeStruct %f16mat
2228 %str_ptr = OpTypePointer Workgroup %str
2229 %sh = OpVariable %str_ptr Workgroup
2230 
2231 %main = OpFunction %void None %func
2232 %main_entry = OpLabel
2233 
2234 OpReturn
2235 OpFunctionEnd)";
2236 
2237   CompileSuccessfully(body.c_str());
2238   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2239   EXPECT_THAT(
2240       getDiagnosticString(),
2241       HasSubstr(
2242           "Cooperative matrix types (or types containing them) can only be "
2243           "allocated in Function or Private storage classes or as function "
2244           "parameters"));
2245 }
2246 
TEST_F(ValidateMemory,CoopMatMatrixLengthResultTypeBad)2247 TEST_F(ValidateMemory, CoopMatMatrixLengthResultTypeBad) {
2248   const std::string body =
2249       R"(
2250 OpCapability Shader
2251 OpCapability Float16
2252 OpCapability CooperativeMatrixNV
2253 OpExtension "SPV_NV_cooperative_matrix"
2254 OpMemoryModel Logical GLSL450
2255 OpEntryPoint GLCompute %main "main"
2256 %void = OpTypeVoid
2257 %func = OpTypeFunction %void
2258 %f16 = OpTypeFloat 16
2259 %u32 = OpTypeInt 32 0
2260 %i32 = OpTypeInt 32 1
2261 
2262 %u32_8 = OpConstant %u32 8
2263 %subgroup = OpConstant %u32 3
2264 
2265 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
2266 
2267 %main = OpFunction %void None %func
2268 %main_entry = OpLabel
2269 
2270 %1 = OpCooperativeMatrixLengthNV %i32 %f16mat
2271 
2272 OpReturn
2273 OpFunctionEnd)";
2274 
2275   CompileSuccessfully(body.c_str());
2276   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2277   EXPECT_THAT(
2278       getDiagnosticString(),
2279       HasSubstr("The Result Type of OpCooperativeMatrixLengthNV <id> "
2280                 "'11[%11]' must be OpTypeInt with width 32 and signedness 0"));
2281 }
2282 
TEST_F(ValidateMemory,CoopMatMatrixLengthOperandTypeBad)2283 TEST_F(ValidateMemory, CoopMatMatrixLengthOperandTypeBad) {
2284   const std::string body =
2285       R"(
2286 OpCapability Shader
2287 OpCapability Float16
2288 OpCapability CooperativeMatrixNV
2289 OpExtension "SPV_NV_cooperative_matrix"
2290 OpMemoryModel Logical GLSL450
2291 OpEntryPoint GLCompute %main "main"
2292 %void = OpTypeVoid
2293 %func = OpTypeFunction %void
2294 %f16 = OpTypeFloat 16
2295 %u32 = OpTypeInt 32 0
2296 %i32 = OpTypeInt 32 1
2297 
2298 %u32_8 = OpConstant %u32 8
2299 %subgroup = OpConstant %u32 3
2300 
2301 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
2302 
2303 %main = OpFunction %void None %func
2304 %main_entry = OpLabel
2305 
2306 %1 = OpCooperativeMatrixLengthNV %u32 %u32
2307 
2308 OpReturn
2309 OpFunctionEnd)";
2310 
2311   CompileSuccessfully(body.c_str());
2312   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2313   EXPECT_THAT(
2314       getDiagnosticString(),
2315       HasSubstr("The type in OpCooperativeMatrixLengthNV <id> '5[%uint]' "
2316                 "must be OpTypeCooperativeMatrixNV"));
2317 }
2318 
TEST_F(ValidateMemory,CoopMatMatrixLengthGood)2319 TEST_F(ValidateMemory, CoopMatMatrixLengthGood) {
2320   const std::string body =
2321       R"(
2322 OpCapability Shader
2323 OpCapability Float16
2324 OpCapability CooperativeMatrixNV
2325 OpExtension "SPV_NV_cooperative_matrix"
2326 OpMemoryModel Logical GLSL450
2327 OpEntryPoint GLCompute %main "main"
2328 %void = OpTypeVoid
2329 %func = OpTypeFunction %void
2330 %f16 = OpTypeFloat 16
2331 %u32 = OpTypeInt 32 0
2332 %i32 = OpTypeInt 32 1
2333 
2334 %u32_8 = OpConstant %u32 8
2335 %subgroup = OpConstant %u32 3
2336 
2337 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
2338 
2339 %main = OpFunction %void None %func
2340 %main_entry = OpLabel
2341 
2342 %1 = OpCooperativeMatrixLengthNV %u32 %f16mat
2343 
2344 OpReturn
2345 OpFunctionEnd)";
2346 
2347   CompileSuccessfully(body.c_str());
2348   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2349 }
2350 
TEST_F(ValidateMemory,CoopMatKHRLoadStoreSuccess)2351 TEST_F(ValidateMemory, CoopMatKHRLoadStoreSuccess) {
2352   std::string spirv =
2353       GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR",
2354                                 "MakePointerVisibleKHR|NonPrivatePointerKHR");
2355 
2356   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2357   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2358 }
2359 
TEST_F(ValidateMemory,CoopMatKHRStoreMemoryAccessFail)2360 TEST_F(ValidateMemory, CoopMatKHRStoreMemoryAccessFail) {
2361   std::string spirv =
2362       GenCoopMatLoadStoreShader("MakePointerVisibleKHR|NonPrivatePointerKHR",
2363                                 "MakePointerVisibleKHR|NonPrivatePointerKHR");
2364 
2365   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2366   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2367   EXPECT_THAT(getDiagnosticString(),
2368               HasSubstr("MakePointerVisibleKHR cannot be used with OpStore"));
2369 }
2370 
TEST_F(ValidateMemory,CoopMatKHRLoadMemoryAccessFail)2371 TEST_F(ValidateMemory, CoopMatKHRLoadMemoryAccessFail) {
2372   std::string spirv =
2373       GenCoopMatLoadStoreShader("MakePointerAvailableKHR|NonPrivatePointerKHR",
2374                                 "MakePointerAvailableKHR|NonPrivatePointerKHR");
2375 
2376   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2377   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2378   EXPECT_THAT(getDiagnosticString(),
2379               HasSubstr("MakePointerAvailableKHR cannot be used with OpLoad"));
2380 }
2381 
TEST_F(ValidateMemory,CoopMatKHRInvalidStorageClassFail)2382 TEST_F(ValidateMemory, CoopMatKHRInvalidStorageClassFail) {
2383   const std::string body = R"(
2384 OpCapability Shader
2385 OpCapability Float16
2386 OpCapability CooperativeMatrixKHR
2387 OpExtension "SPV_KHR_cooperative_matrix"
2388 OpExtension "SPV_KHR_vulkan_memory_model"
2389 OpMemoryModel Logical GLSL450
2390 OpEntryPoint GLCompute %main "main"
2391 %void = OpTypeVoid
2392 %func = OpTypeFunction %void
2393 %f16 = OpTypeFloat 16
2394 %u32 = OpTypeInt 32 0
2395 
2396 %u32_8 = OpConstant %u32 8
2397 %use_A = OpConstant %u32 0
2398 %subgroup = OpConstant %u32 3
2399 
2400 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
2401 
2402 %str = OpTypeStruct %f16mat
2403 %str_ptr = OpTypePointer Workgroup %str
2404 %sh = OpVariable %str_ptr Workgroup
2405 
2406 %main = OpFunction %void None %func
2407 %main_entry = OpLabel
2408 
2409 OpReturn
2410 OpFunctionEnd)";
2411 
2412   CompileSuccessfully(body.c_str());
2413   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2414   EXPECT_THAT(
2415       getDiagnosticString(),
2416       HasSubstr(
2417           "Cooperative matrix types (or types containing them) can only be "
2418           "allocated in Function or Private storage classes or as function "
2419           "parameters"));
2420 }
2421 
TEST_F(ValidateMemory,CoopMatMatrixKHRLengthResultTypeBad)2422 TEST_F(ValidateMemory, CoopMatMatrixKHRLengthResultTypeBad) {
2423   const std::string body = R"(
2424 OpCapability Shader
2425 OpCapability Float16
2426 OpCapability CooperativeMatrixKHR
2427 OpExtension "SPV_KHR_cooperative_matrix"
2428 OpExtension "SPV_KHR_vulkan_memory_model"
2429 OpMemoryModel Logical GLSL450
2430 OpEntryPoint GLCompute %main "main"
2431 %void = OpTypeVoid
2432 %func = OpTypeFunction %void
2433 %f16 = OpTypeFloat 16
2434 %u32 = OpTypeInt 32 0
2435 %i32 = OpTypeInt 32 1
2436 
2437 %u32_8 = OpConstant %u32 8
2438 %use_A = OpConstant %u32 0
2439 %subgroup = OpConstant %u32 3
2440 
2441 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
2442 
2443 %main = OpFunction %void None %func
2444 %main_entry = OpLabel
2445 
2446 %1 = OpCooperativeMatrixLengthKHR %i32 %f16mat
2447 
2448 OpReturn
2449 OpFunctionEnd)";
2450 
2451   CompileSuccessfully(body.c_str());
2452   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2453   EXPECT_THAT(
2454       getDiagnosticString(),
2455       HasSubstr("The Result Type of OpCooperativeMatrixLengthKHR <id> "
2456                 "'12[%12]' must be OpTypeInt with width 32 and signedness 0"));
2457 }
2458 
TEST_F(ValidateMemory,CoopMatMatrixKHRLengthOperandTypeBad)2459 TEST_F(ValidateMemory, CoopMatMatrixKHRLengthOperandTypeBad) {
2460   const std::string body =
2461       R"(
2462 OpCapability Shader
2463 OpCapability Float16
2464 OpCapability CooperativeMatrixKHR
2465 OpExtension "SPV_KHR_cooperative_matrix"
2466 OpExtension "SPV_KHR_vulkan_memory_model"
2467 OpMemoryModel Logical GLSL450
2468 OpEntryPoint GLCompute %main "main"
2469 %void = OpTypeVoid
2470 %func = OpTypeFunction %void
2471 %f16 = OpTypeFloat 16
2472 %u32 = OpTypeInt 32 0
2473 %i32 = OpTypeInt 32 1
2474 
2475 %u32_8 = OpConstant %u32 8
2476 %use_A = OpConstant %u32 0
2477 %subgroup = OpConstant %u32 3
2478 
2479 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
2480 
2481 %main = OpFunction %void None %func
2482 %main_entry = OpLabel
2483 
2484 %1 = OpCooperativeMatrixLengthKHR %u32 %u32
2485 
2486 OpReturn
2487 OpFunctionEnd)";
2488 
2489   CompileSuccessfully(body.c_str());
2490   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2491   EXPECT_THAT(
2492       getDiagnosticString(),
2493       HasSubstr("The type in OpCooperativeMatrixLengthKHR <id> '5[%uint]' "
2494                 "must be OpTypeCooperativeMatrixKHR"));
2495 }
2496 
TEST_F(ValidateMemory,CoopMatMatrixKHRLengthGood)2497 TEST_F(ValidateMemory, CoopMatMatrixKHRLengthGood) {
2498   const std::string body =
2499       R"(
2500 OpCapability Shader
2501 OpCapability Float16
2502 OpCapability CooperativeMatrixKHR
2503 OpExtension "SPV_KHR_cooperative_matrix"
2504 OpExtension "SPV_KHR_vulkan_memory_model"
2505 OpMemoryModel Logical GLSL450
2506 OpEntryPoint GLCompute %main "main"
2507 %void = OpTypeVoid
2508 %func = OpTypeFunction %void
2509 %f16 = OpTypeFloat 16
2510 %u32 = OpTypeInt 32 0
2511 %i32 = OpTypeInt 32 1
2512 
2513 %u32_8 = OpConstant %u32 8
2514 %use_A = OpConstant %u32 0
2515 %subgroup = OpConstant %u32 3
2516 
2517 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
2518 
2519 %main = OpFunction %void None %func
2520 %main_entry = OpLabel
2521 
2522 %1 = OpCooperativeMatrixLengthKHR %u32 %f16mat
2523 
2524 OpReturn
2525 OpFunctionEnd)";
2526 
2527   CompileSuccessfully(body.c_str());
2528   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2529 }
2530 
TEST_F(ValidateMemory,VulkanRTAOutsideOfStructBad)2531 TEST_F(ValidateMemory, VulkanRTAOutsideOfStructBad) {
2532   std::string spirv = R"(
2533 OpCapability Shader
2534 OpMemoryModel Logical GLSL450
2535 OpEntryPoint Fragment %func "func"
2536 OpExecutionMode %func OriginUpperLeft
2537 %sampler_t = OpTypeSampler
2538 %array_t = OpTypeRuntimeArray %sampler_t
2539 %array_ptr = OpTypePointer UniformConstant %array_t
2540 %2 = OpVariable %array_ptr UniformConstant
2541 %void = OpTypeVoid
2542 %func_t = OpTypeFunction %void
2543 %func = OpFunction %void None %func_t
2544 %1 = OpLabel
2545 OpReturn
2546 OpFunctionEnd
2547 )";
2548 
2549   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2550   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2551   EXPECT_THAT(getDiagnosticString(),
2552               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2553   EXPECT_THAT(
2554       getDiagnosticString(),
2555       HasSubstr(
2556           "OpVariable, <id> '5[%5]', is attempting to create memory for an "
2557           "illegal type, OpTypeRuntimeArray.\nFor Vulkan OpTypeRuntimeArray "
2558           "can only appear as the final member of an OpTypeStruct, thus cannot "
2559           "be instantiated via OpVariable\n  %5 = OpVariable "
2560           "%_ptr_UniformConstant__runtimearr_2 UniformConstant\n"));
2561 }
2562 
TEST_F(ValidateMemory,VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayGood)2563 TEST_F(ValidateMemory, VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayGood) {
2564   std::string spirv = R"(
2565 OpCapability Shader
2566 OpCapability RuntimeDescriptorArrayEXT
2567 OpExtension "SPV_EXT_descriptor_indexing"
2568 OpMemoryModel Logical GLSL450
2569 OpEntryPoint Fragment %func "func"
2570 OpExecutionMode %func OriginUpperLeft
2571 OpDecorate %struct Block
2572 OpMemberDecorate %struct 0 Offset 0
2573 %sampler_t = OpTypeSampler
2574 %uint = OpTypeInt 32 0
2575 %array_t = OpTypeRuntimeArray %sampler_t
2576 %struct = OpTypeStruct %uint
2577 %sb_array_t = OpTypeRuntimeArray %struct
2578 %array_sb_ptr = OpTypePointer StorageBuffer %sb_array_t
2579 %2 = OpVariable %array_sb_ptr StorageBuffer
2580 %array_uc_ptr = OpTypePointer UniformConstant %array_t
2581 %3 = OpVariable %array_uc_ptr UniformConstant
2582 %void = OpTypeVoid
2583 %func_t = OpTypeFunction %void
2584 %func = OpFunction %void None %func_t
2585 %1 = OpLabel
2586 OpReturn
2587 OpFunctionEnd
2588 )";
2589 
2590   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2591   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2592 }
2593 
TEST_F(ValidateMemory,VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayAndWrongStorageClassBad)2594 TEST_F(
2595     ValidateMemory,
2596     VulkanRTAOutsideOfStructWithRuntimeDescriptorArrayAndWrongStorageClassBad) {
2597   std::string spirv = R"(
2598 OpCapability Shader
2599 OpCapability RuntimeDescriptorArrayEXT
2600 OpExtension "SPV_EXT_descriptor_indexing"
2601 OpMemoryModel Logical GLSL450
2602 OpEntryPoint Fragment %func "func"
2603 OpExecutionMode %func OriginUpperLeft
2604 %uint_t = OpTypeInt 32 0
2605 %array_t = OpTypeRuntimeArray %uint_t
2606 %array_ptr = OpTypePointer Workgroup %array_t
2607 %2 = OpVariable %array_ptr Workgroup
2608 %void = OpTypeVoid
2609 %func_t = OpTypeFunction %void
2610 %func = OpFunction %void None %func_t
2611 %1 = OpLabel
2612 OpReturn
2613 OpFunctionEnd
2614 )";
2615 
2616   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2617   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2618   EXPECT_THAT(getDiagnosticString(),
2619               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2620   EXPECT_THAT(
2621       getDiagnosticString(),
2622       HasSubstr("For Vulkan with RuntimeDescriptorArrayEXT, a variable "
2623                 "containing OpTypeRuntimeArray must have storage class of "
2624                 "StorageBuffer, Uniform, or UniformConstant.\n  %5 = "
2625                 "OpVariable %_ptr_Workgroup__runtimearr_uint Workgroup\n"));
2626 }
2627 
TEST_F(ValidateMemory,VulkanRTAInsideStorageBufferStructGood)2628 TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructGood) {
2629   std::string spirv = R"(
2630 OpCapability Shader
2631 OpMemoryModel Logical GLSL450
2632 OpEntryPoint Fragment %func "func"
2633 OpExecutionMode %func OriginUpperLeft
2634 OpDecorate %array_t ArrayStride 4
2635 OpMemberDecorate %struct_t 0 Offset 0
2636 OpDecorate %struct_t Block
2637 %uint_t = OpTypeInt 32 0
2638 %array_t = OpTypeRuntimeArray %uint_t
2639 %struct_t = OpTypeStruct %array_t
2640 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2641 %2 = OpVariable %struct_ptr StorageBuffer
2642 %void = OpTypeVoid
2643 %func_t = OpTypeFunction %void
2644 %func = OpFunction %void None %func_t
2645 %1 = OpLabel
2646 OpReturn
2647 OpFunctionEnd
2648 )";
2649 
2650   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2651   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2652 }
2653 
TEST_F(ValidateMemory,VulkanRTAInsideWrongStorageClassStructBad)2654 TEST_F(ValidateMemory, VulkanRTAInsideWrongStorageClassStructBad) {
2655   std::string spirv = R"(
2656 OpCapability Shader
2657 OpMemoryModel Logical GLSL450
2658 OpEntryPoint Fragment %func "func"
2659 OpExecutionMode %func OriginUpperLeft
2660 OpDecorate %struct_t Block
2661 %uint_t = OpTypeInt 32 0
2662 %array_t = OpTypeRuntimeArray %uint_t
2663 %struct_t = OpTypeStruct %array_t
2664 %struct_ptr = OpTypePointer Workgroup %struct_t
2665 %2 = OpVariable %struct_ptr Workgroup
2666 %void = OpTypeVoid
2667 %func_t = OpTypeFunction %void
2668 %func = OpFunction %void None %func_t
2669 %1 = OpLabel
2670 OpReturn
2671 OpFunctionEnd
2672 )";
2673 
2674   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2675   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2676   EXPECT_THAT(getDiagnosticString(),
2677               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2678   EXPECT_THAT(
2679       getDiagnosticString(),
2680       HasSubstr(
2681           "For Vulkan, OpTypeStruct variables containing OpTypeRuntimeArray "
2682           "must have storage class of StorageBuffer, PhysicalStorageBuffer, or "
2683           "Uniform.\n  %6 = "
2684           "OpVariable %_ptr_Workgroup__struct_2 Workgroup\n"));
2685 }
2686 
TEST_F(ValidateMemory,VulkanRTAInsideStorageBufferStructWithoutBlockBad)2687 TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructWithoutBlockBad) {
2688   std::string spirv = R"(
2689 OpCapability Shader
2690 OpMemoryModel Logical GLSL450
2691 OpEntryPoint Fragment %func "func"
2692 OpExecutionMode %func OriginUpperLeft
2693 OpDecorate %struct_t BufferBlock
2694 %uint_t = OpTypeInt 32 0
2695 %array_t = OpTypeRuntimeArray %uint_t
2696 %struct_t = OpTypeStruct %array_t
2697 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2698 %2 = OpVariable %struct_ptr StorageBuffer
2699 %void = OpTypeVoid
2700 %func_t = OpTypeFunction %void
2701 %func = OpFunction %void None %func_t
2702 %1 = OpLabel
2703 OpReturn
2704 OpFunctionEnd
2705 )";
2706 
2707   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2708   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2709   EXPECT_THAT(getDiagnosticString(),
2710               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2711   EXPECT_THAT(getDiagnosticString(),
2712               HasSubstr("For Vulkan, an OpTypeStruct variable containing an "
2713                         "OpTypeRuntimeArray must be decorated with Block if it "
2714                         "has storage class StorageBuffer or "
2715                         "PhysicalStorageBuffer.\n  %6 = OpVariable "
2716                         "%_ptr_StorageBuffer__struct_2 StorageBuffer\n"));
2717 }
2718 
TEST_F(ValidateMemory,VulkanRTAInsideUniformStructGood)2719 TEST_F(ValidateMemory, VulkanRTAInsideUniformStructGood) {
2720   std::string spirv = R"(
2721 OpCapability Shader
2722 OpMemoryModel Logical GLSL450
2723 OpEntryPoint Fragment %func "func"
2724 OpExecutionMode %func OriginUpperLeft
2725 OpDecorate %array_t ArrayStride 4
2726 OpMemberDecorate %struct_t 0 Offset 0
2727 OpDecorate %struct_t BufferBlock
2728 %uint_t = OpTypeInt 32 0
2729 %array_t = OpTypeRuntimeArray %uint_t
2730 %struct_t = OpTypeStruct %array_t
2731 %struct_ptr = OpTypePointer Uniform %struct_t
2732 %2 = OpVariable %struct_ptr Uniform
2733 %void = OpTypeVoid
2734 %func_t = OpTypeFunction %void
2735 %func = OpFunction %void None %func_t
2736 %1 = OpLabel
2737 OpReturn
2738 OpFunctionEnd
2739 )";
2740 
2741   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2742   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2743 }
2744 
TEST_F(ValidateMemory,VulkanRTAInsideUniformStructWithoutBufferBlockBad)2745 TEST_F(ValidateMemory, VulkanRTAInsideUniformStructWithoutBufferBlockBad) {
2746   std::string spirv = R"(
2747 OpCapability Shader
2748 OpMemoryModel Logical GLSL450
2749 OpEntryPoint Fragment %func "func"
2750 OpExecutionMode %func OriginUpperLeft
2751 OpDecorate %struct_t Block
2752 %uint_t = OpTypeInt 32 0
2753 %array_t = OpTypeRuntimeArray %uint_t
2754 %struct_t = OpTypeStruct %array_t
2755 %struct_ptr = OpTypePointer Uniform %struct_t
2756 %2 = OpVariable %struct_ptr Uniform
2757 %void = OpTypeVoid
2758 %func_t = OpTypeFunction %void
2759 %func = OpFunction %void None %func_t
2760 %1 = OpLabel
2761 OpReturn
2762 OpFunctionEnd
2763 )";
2764 
2765   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2766   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2767   EXPECT_THAT(getDiagnosticString(),
2768               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2769   EXPECT_THAT(getDiagnosticString(),
2770               HasSubstr("For Vulkan, an OpTypeStruct variable containing an "
2771                         "OpTypeRuntimeArray must be decorated with BufferBlock "
2772                         "if it has storage class Uniform.\n  %6 = OpVariable "
2773                         "%_ptr_Uniform__struct_2 Uniform\n"));
2774 }
2775 
TEST_F(ValidateMemory,VulkanRTAInsideRTABad)2776 TEST_F(ValidateMemory, VulkanRTAInsideRTABad) {
2777   std::string spirv = R"(
2778 OpCapability Shader
2779 OpMemoryModel Logical GLSL450
2780 OpEntryPoint Fragment %func "func"
2781 OpExecutionMode %func OriginUpperLeft
2782 %sampler_t = OpTypeSampler
2783 %inner_array_t = OpTypeRuntimeArray %sampler_t
2784 %array_t = OpTypeRuntimeArray %inner_array_t
2785 %array_ptr = OpTypePointer UniformConstant %array_t
2786 %2 = OpVariable %array_ptr UniformConstant
2787 %void = OpTypeVoid
2788 %func_t = OpTypeFunction %void
2789 %func = OpFunction %void None %func_t
2790 %1 = OpLabel
2791 OpReturn
2792 OpFunctionEnd
2793 )";
2794 
2795   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2796   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2797   EXPECT_THAT(getDiagnosticString(),
2798               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2799   EXPECT_THAT(
2800       getDiagnosticString(),
2801       HasSubstr(
2802           "OpTypeRuntimeArray Element Type <id> '3[%_runtimearr_2]' is not "
2803           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_2 = "
2804           "OpTypeRuntimeArray %_runtimearr_2\n"));
2805 }
2806 
TEST_F(ValidateMemory,VulkanRTAInsideRTAWithRuntimeDescriptorArrayBad)2807 TEST_F(ValidateMemory, VulkanRTAInsideRTAWithRuntimeDescriptorArrayBad) {
2808   std::string spirv = R"(
2809 OpCapability RuntimeDescriptorArrayEXT
2810 OpCapability Shader
2811 OpExtension "SPV_EXT_descriptor_indexing"
2812 OpMemoryModel Logical GLSL450
2813 OpEntryPoint Fragment %func "func"
2814 OpExecutionMode %func OriginUpperLeft
2815 OpDecorate %struct Block
2816 %uint_t = OpTypeInt 32 0
2817 %inner_array_t = OpTypeRuntimeArray %uint_t
2818 %array_t = OpTypeRuntimeArray %inner_array_t
2819 %struct = OpTypeStruct %array_t
2820 %array_ptr = OpTypePointer StorageBuffer %struct
2821 %2 = OpVariable %array_ptr StorageBuffer
2822 %void = OpTypeVoid
2823 %func_t = OpTypeFunction %void
2824 %func = OpFunction %void None %func_t
2825 %1 = OpLabel
2826 OpReturn
2827 OpFunctionEnd
2828 )";
2829 
2830   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2831   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2832   EXPECT_THAT(getDiagnosticString(),
2833               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2834   EXPECT_THAT(
2835       getDiagnosticString(),
2836       HasSubstr(
2837           "OpTypeRuntimeArray Element Type <id> '4[%_runtimearr_uint]' is not "
2838           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
2839           "OpTypeRuntimeArray %_runtimearr_uint\n"));
2840 }
2841 
TEST_F(ValidateMemory,VulkanUniformStructInsideRTAWithRuntimeDescriptorArrayGood)2842 TEST_F(ValidateMemory,
2843        VulkanUniformStructInsideRTAWithRuntimeDescriptorArrayGood) {
2844   std::string spirv = R"(
2845 OpCapability RuntimeDescriptorArrayEXT
2846 OpCapability Shader
2847 OpExtension "SPV_EXT_descriptor_indexing"
2848 OpMemoryModel Logical GLSL450
2849 OpEntryPoint Fragment %func "func"
2850 OpExecutionMode %func OriginUpperLeft
2851 OpDecorate %array_t ArrayStride 4
2852 OpMemberDecorate %struct_t 0 Offset 0
2853 OpDecorate %struct_t Block
2854 %uint_t = OpTypeInt 32 0
2855 %struct_t = OpTypeStruct %uint_t
2856 %array_t = OpTypeRuntimeArray %struct_t
2857 %array_ptr = OpTypePointer Uniform %array_t
2858 %2 = OpVariable %array_ptr Uniform
2859 %void = OpTypeVoid
2860 %func_t = OpTypeFunction %void
2861 %func = OpFunction %void None %func_t
2862 %1 = OpLabel
2863 OpReturn
2864 OpFunctionEnd
2865 )";
2866 
2867   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2868   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2869 }
2870 
TEST_F(ValidateMemory,VulkanRTAInsideRTAInsideStructBad)2871 TEST_F(ValidateMemory, VulkanRTAInsideRTAInsideStructBad) {
2872   std::string spirv = R"(
2873 OpCapability Shader
2874 OpMemoryModel Logical GLSL450
2875 OpEntryPoint Fragment %func "func"
2876 OpExecutionMode %func OriginUpperLeft
2877 OpDecorate %array_t ArrayStride 4
2878 OpMemberDecorate %struct_t 0 Offset 0
2879 OpDecorate %struct_t Block
2880 %uint_t = OpTypeInt 32 0
2881 %inner_array_t = OpTypeRuntimeArray %uint_t
2882 %array_t = OpTypeRuntimeArray %inner_array_t
2883 %struct_t = OpTypeStruct %array_t
2884 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2885 %2 = OpVariable %struct_ptr StorageBuffer
2886 %void = OpTypeVoid
2887 %func_t = OpTypeFunction %void
2888 %func = OpFunction %void None %func_t
2889 %1 = OpLabel
2890 OpReturn
2891 OpFunctionEnd
2892 )";
2893 
2894   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2895   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2896   EXPECT_THAT(getDiagnosticString(),
2897               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2898   EXPECT_THAT(
2899       getDiagnosticString(),
2900       HasSubstr(
2901           "OpTypeRuntimeArray Element Type <id> '5[%_runtimearr_uint]' is not "
2902           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
2903           "OpTypeRuntimeArray %_runtimearr_uint\n"));
2904 }
2905 
TEST_F(ValidateMemory,VulkanRTAInsideRTAInsideStructWithRuntimeDescriptorArrayBad)2906 TEST_F(ValidateMemory,
2907        VulkanRTAInsideRTAInsideStructWithRuntimeDescriptorArrayBad) {
2908   std::string spirv = R"(
2909 OpCapability RuntimeDescriptorArrayEXT
2910 OpCapability Shader
2911 OpExtension "SPV_EXT_descriptor_indexing"
2912 OpMemoryModel Logical GLSL450
2913 OpEntryPoint Fragment %func "func"
2914 OpExecutionMode %func OriginUpperLeft
2915 OpDecorate %array_t ArrayStride 4
2916 OpMemberDecorate %struct_t 0 Offset 0
2917 OpDecorate %struct_t Block
2918 %uint_t = OpTypeInt 32 0
2919 %inner_array_t = OpTypeRuntimeArray %uint_t
2920 %array_t = OpTypeRuntimeArray %inner_array_t
2921 %struct_t = OpTypeStruct %array_t
2922 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2923 %2 = OpVariable %struct_ptr StorageBuffer
2924 %void = OpTypeVoid
2925 %func_t = OpTypeFunction %void
2926 %func = OpFunction %void None %func_t
2927 %1 = OpLabel
2928 OpReturn
2929 OpFunctionEnd
2930 )";
2931 
2932   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2933   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2934   EXPECT_THAT(getDiagnosticString(),
2935               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2936   EXPECT_THAT(
2937       getDiagnosticString(),
2938       HasSubstr(
2939           "OpTypeRuntimeArray Element Type <id> '5[%_runtimearr_uint]' is not "
2940           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
2941           "OpTypeRuntimeArray %_runtimearr_uint\n"));
2942 }
2943 
TEST_F(ValidateMemory,VulkanRTAInsideArrayBad)2944 TEST_F(ValidateMemory, VulkanRTAInsideArrayBad) {
2945   std::string spirv = R"(
2946 OpCapability Shader
2947 OpMemoryModel Logical GLSL450
2948 OpEntryPoint Fragment %func "func"
2949 OpExecutionMode %func OriginUpperLeft
2950 %uint_t = OpTypeInt 32 0
2951 %dim = OpConstant %uint_t 1
2952 %sampler_t = OpTypeSampler
2953 %inner_array_t = OpTypeRuntimeArray %sampler_t
2954 %array_t = OpTypeArray %inner_array_t %dim
2955 %array_ptr = OpTypePointer UniformConstant %array_t
2956 %2 = OpVariable %array_ptr UniformConstant
2957 %void = OpTypeVoid
2958 %func_t = OpTypeFunction %void
2959 %func = OpFunction %void None %func_t
2960 %1 = OpLabel
2961 OpReturn
2962 OpFunctionEnd
2963 )";
2964 
2965   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2966   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2967   EXPECT_THAT(getDiagnosticString(),
2968               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2969   EXPECT_THAT(
2970       getDiagnosticString(),
2971       HasSubstr("OpTypeArray Element Type <id> '5[%_runtimearr_4]' is not "
2972                 "valid in Vulkan environments.\n  %_arr__runtimearr_4_uint_1 = "
2973                 "OpTypeArray %_runtimearr_4 %uint_1\n"));
2974 }
2975 
TEST_F(ValidateMemory,VulkanRTAInsideArrayWithRuntimeDescriptorArrayBad)2976 TEST_F(ValidateMemory, VulkanRTAInsideArrayWithRuntimeDescriptorArrayBad) {
2977   std::string spirv = R"(
2978 OpCapability RuntimeDescriptorArrayEXT
2979 OpCapability Shader
2980 OpExtension "SPV_EXT_descriptor_indexing"
2981 OpMemoryModel Logical GLSL450
2982 OpEntryPoint Fragment %func "func"
2983 OpExecutionMode %func OriginUpperLeft
2984 OpDecorate %struct Block
2985 %uint_t = OpTypeInt 32 0
2986 %dim = OpConstant %uint_t 1
2987 %sampler_t = OpTypeSampler
2988 %inner_array_t = OpTypeRuntimeArray %uint_t
2989 %array_t = OpTypeRuntimeArray %inner_array_t
2990 %struct = OpTypeStruct %array_t
2991 %array_ptr = OpTypePointer StorageBuffer %struct
2992 %2 = OpVariable %array_ptr StorageBuffer
2993 %void = OpTypeVoid
2994 %func_t = OpTypeFunction %void
2995 %func = OpFunction %void None %func_t
2996 %1 = OpLabel
2997 OpReturn
2998 OpFunctionEnd
2999 )";
3000 
3001   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
3002   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3003   EXPECT_THAT(getDiagnosticString(),
3004               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
3005   EXPECT_THAT(
3006       getDiagnosticString(),
3007       HasSubstr(
3008           "OpTypeRuntimeArray Element Type <id> '6[%_runtimearr_uint]' is not "
3009           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
3010           "OpTypeRuntimeArray %_runtimearr_uint\n"));
3011 }
3012 
TEST_F(ValidateMemory,VulkanRTAInsideArrayInsideStructBad)3013 TEST_F(ValidateMemory, VulkanRTAInsideArrayInsideStructBad) {
3014   std::string spirv = R"(
3015 OpCapability Shader
3016 OpMemoryModel Logical GLSL450
3017 OpEntryPoint Fragment %func "func"
3018 OpExecutionMode %func OriginUpperLeft
3019 OpDecorate %array_t ArrayStride 4
3020 OpMemberDecorate %struct_t 0 Offset 0
3021 OpDecorate %struct_t Block
3022 %uint_t = OpTypeInt 32 0
3023 %dim = OpConstant %uint_t 1
3024 %inner_array_t = OpTypeRuntimeArray %uint_t
3025 %array_t = OpTypeArray %inner_array_t %dim
3026 %struct_t = OpTypeStruct %array_t
3027 %struct_ptr = OpTypePointer StorageBuffer %struct_t
3028 %2 = OpVariable %struct_ptr StorageBuffer
3029 %void = OpTypeVoid
3030 %func_t = OpTypeFunction %void
3031 %func = OpFunction %void None %func_t
3032 %1 = OpLabel
3033 OpReturn
3034 OpFunctionEnd
3035 )";
3036 
3037   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
3038   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3039   EXPECT_THAT(getDiagnosticString(),
3040               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
3041   EXPECT_THAT(
3042       getDiagnosticString(),
3043       HasSubstr(
3044           "OpTypeArray Element Type <id> '6[%_runtimearr_uint]' is not "
3045           "valid in Vulkan environments.\n  %_arr__runtimearr_uint_uint_1 "
3046           "= OpTypeArray %_runtimearr_uint %uint_1\n"));
3047 }
3048 
TEST_F(ValidateMemory,VulkanRTAInsideArrayInsideStructWithRuntimeDescriptorArrayBad)3049 TEST_F(ValidateMemory,
3050        VulkanRTAInsideArrayInsideStructWithRuntimeDescriptorArrayBad) {
3051   std::string spirv = R"(
3052 OpCapability RuntimeDescriptorArrayEXT
3053 OpCapability Shader
3054 OpExtension "SPV_EXT_descriptor_indexing"
3055 OpMemoryModel Logical GLSL450
3056 OpEntryPoint Fragment %func "func"
3057 OpExecutionMode %func OriginUpperLeft
3058 OpDecorate %array_t ArrayStride 4
3059 OpMemberDecorate %struct_t 0 Offset 0
3060 OpDecorate %struct_t Block
3061 %uint_t = OpTypeInt 32 0
3062 %dim = OpConstant %uint_t 1
3063 %inner_array_t = OpTypeRuntimeArray %uint_t
3064 %array_t = OpTypeArray %inner_array_t %dim
3065 %struct_t = OpTypeStruct %array_t
3066 %struct_ptr = OpTypePointer StorageBuffer %struct_t
3067 %2 = OpVariable %struct_ptr StorageBuffer
3068 %void = OpTypeVoid
3069 %func_t = OpTypeFunction %void
3070 %func = OpFunction %void None %func_t
3071 %1 = OpLabel
3072 OpReturn
3073 OpFunctionEnd
3074 )";
3075 
3076   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
3077   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3078   EXPECT_THAT(getDiagnosticString(),
3079               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
3080   EXPECT_THAT(
3081       getDiagnosticString(),
3082       HasSubstr(
3083           "OpTypeArray Element Type <id> '6[%_runtimearr_uint]' is not "
3084           "valid in Vulkan environments.\n  %_arr__runtimearr_uint_uint_1 "
3085           "= OpTypeArray %_runtimearr_uint %uint_1\n"));
3086 }
3087 
TEST_F(ValidateMemory,VulkanRTAStructInsideRTAWithRuntimeDescriptorArrayGood)3088 TEST_F(ValidateMemory, VulkanRTAStructInsideRTAWithRuntimeDescriptorArrayGood) {
3089   std::string spirv = R"(
3090 OpCapability RuntimeDescriptorArrayEXT
3091 OpCapability Shader
3092 OpExtension "SPV_EXT_descriptor_indexing"
3093 OpMemoryModel Logical GLSL450
3094 OpEntryPoint Fragment %func "func"
3095 OpExecutionMode %func OriginUpperLeft
3096 OpDecorate %inner_array_t ArrayStride 4
3097 OpDecorate %array_t ArrayStride 4
3098 OpMemberDecorate %struct_t 0 Offset 0
3099 OpDecorate %struct_t Block
3100 %uint_t = OpTypeInt 32 0
3101 %inner_array_t = OpTypeRuntimeArray %uint_t
3102 %struct_t = OpTypeStruct %inner_array_t
3103 %array_t = OpTypeRuntimeArray %struct_t
3104 %array_ptr = OpTypePointer StorageBuffer %array_t
3105 %2 = OpVariable %array_ptr StorageBuffer
3106 %void = OpTypeVoid
3107 %func_t = OpTypeFunction %void
3108 %func = OpFunction %void None %func_t
3109 %1 = OpLabel
3110 OpReturn
3111 OpFunctionEnd
3112 )";
3113 
3114   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
3115   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3116 }
3117 
TEST_F(ValidateMemory,VulkanRTAStructInsideArrayGood)3118 TEST_F(ValidateMemory, VulkanRTAStructInsideArrayGood) {
3119   std::string spirv = R"(
3120 OpCapability RuntimeDescriptorArrayEXT
3121 OpCapability Shader
3122 OpExtension "SPV_EXT_descriptor_indexing"
3123 OpMemoryModel Logical GLSL450
3124 OpEntryPoint Fragment %func "func"
3125 OpExecutionMode %func OriginUpperLeft
3126 OpDecorate %inner_array_t ArrayStride 4
3127 OpDecorate %array_t ArrayStride 4
3128 OpMemberDecorate %struct_t 0 Offset 0
3129 OpDecorate %struct_t Block
3130 %uint_t = OpTypeInt 32 0
3131 %inner_array_t = OpTypeRuntimeArray %uint_t
3132 %struct_t = OpTypeStruct %inner_array_t
3133 %array_size = OpConstant %uint_t 5
3134 %array_t = OpTypeArray %struct_t %array_size
3135 %array_ptr = OpTypePointer StorageBuffer %array_t
3136 %2 = OpVariable %array_ptr StorageBuffer
3137 %void = OpTypeVoid
3138 %func_t = OpTypeFunction %void
3139 %func = OpFunction %void None %func_t
3140 %1 = OpLabel
3141 OpReturn
3142 OpFunctionEnd
3143 )";
3144 
3145   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
3146   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3147 }
3148 
TEST_F(ValidateMemory,CopyMemoryNoAccessGood)3149 TEST_F(ValidateMemory, CopyMemoryNoAccessGood) {
3150   const std::string spirv = R"(
3151 OpCapability Shader
3152 OpCapability Linkage
3153 OpMemoryModel Logical GLSL450
3154 %void = OpTypeVoid
3155 %int = OpTypeInt 32 0
3156 %int_ptr_priv = OpTypePointer Private %int
3157 %var1 = OpVariable %int_ptr_priv Private
3158 %var2 = OpVariable %int_ptr_priv Private
3159 %voidfn = OpTypeFunction %void
3160 %func = OpFunction %void None %voidfn
3161 %entry = OpLabel
3162 OpCopyMemory %var1 %var2
3163 OpReturn
3164 OpFunctionEnd
3165 )";
3166 
3167   CompileSuccessfully(spirv);
3168   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3169   EXPECT_THAT(getDiagnosticString(), Eq(""));
3170 }
3171 
TEST_F(ValidateMemory,CopyMemorySimpleMixedAccessGood)3172 TEST_F(ValidateMemory, CopyMemorySimpleMixedAccessGood) {
3173   // Test one memory access operand using features that don't require the
3174   // Vulkan memory model.
3175   const std::string spirv = R"(
3176 OpCapability Shader
3177 OpCapability Linkage
3178 OpMemoryModel Logical GLSL450
3179 %void = OpTypeVoid
3180 %int = OpTypeInt 32 0
3181 %int_ptr_priv = OpTypePointer Private %int
3182 %var1 = OpVariable %int_ptr_priv Private
3183 %var2 = OpVariable %int_ptr_priv Private
3184 %voidfn = OpTypeFunction %void
3185 %func = OpFunction %void None %voidfn
3186 %entry = OpLabel
3187 OpCopyMemory %var1 %var2 Volatile|Aligned|Nontemporal 4
3188 OpReturn
3189 OpFunctionEnd
3190 )";
3191 
3192   CompileSuccessfully(spirv);
3193   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3194   EXPECT_THAT(getDiagnosticString(), Eq(""));
3195 }
3196 
TEST_F(ValidateMemory,CopyMemorySimpleTwoMixedAccessV13Bad)3197 TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV13Bad) {
3198   // Two memory access operands is invalid up to SPIR-V 1.3
3199   const std::string spirv = R"(
3200 OpCapability Shader
3201 OpCapability Linkage
3202 OpMemoryModel Logical GLSL450
3203 %void = OpTypeVoid
3204 %int = OpTypeInt 32 0
3205 %int_ptr_priv = OpTypePointer Private %int
3206 %var1 = OpVariable %int_ptr_priv Private
3207 %var2 = OpVariable %int_ptr_priv Private
3208 %voidfn = OpTypeFunction %void
3209 %func = OpFunction %void None %voidfn
3210 %entry = OpLabel
3211 OpCopyMemory %var1 %var2 Volatile Volatile
3212 OpReturn
3213 OpFunctionEnd
3214 )";
3215 
3216   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
3217   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
3218             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3219   EXPECT_THAT(getDiagnosticString(),
3220               HasSubstr("CopyMemory with two memory access operands requires "
3221                         "SPIR-V 1.4 or later"));
3222 }
3223 
TEST_F(ValidateMemory,CopyMemorySimpleTwoMixedAccessV14Good)3224 TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV14Good) {
3225   // Two memory access operands is valid in SPIR-V 1.4
3226   const std::string spirv = R"(
3227 OpCapability Shader
3228 OpCapability Linkage
3229 OpMemoryModel Logical GLSL450
3230 %void = OpTypeVoid
3231 %int = OpTypeInt 32 0
3232 %int_ptr_priv = OpTypePointer Private %int
3233 %var1 = OpVariable %int_ptr_priv Private
3234 %var2 = OpVariable %int_ptr_priv Private
3235 %voidfn = OpTypeFunction %void
3236 %func = OpFunction %void None %voidfn
3237 %entry = OpLabel
3238 OpCopyMemory %var1 %var2 Volatile Volatile
3239 OpReturn
3240 OpFunctionEnd
3241 )";
3242 
3243   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3244   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3245   EXPECT_THAT(getDiagnosticString(), Eq(""));
3246 }
3247 
TEST_F(ValidateMemory,CopyMemorySizedNoAccessGood)3248 TEST_F(ValidateMemory, CopyMemorySizedNoAccessGood) {
3249   const std::string spirv = R"(
3250 OpCapability Shader
3251 OpCapability Linkage
3252 OpCapability Addresses
3253 OpMemoryModel Logical GLSL450
3254 %void = OpTypeVoid
3255 %int = OpTypeInt 32 0
3256 %int_16 = OpConstant %int 16
3257 %int_ptr_priv = OpTypePointer Private %int
3258 %var1 = OpVariable %int_ptr_priv Private
3259 %var2 = OpVariable %int_ptr_priv Private
3260 %voidfn = OpTypeFunction %void
3261 %func = OpFunction %void None %voidfn
3262 %entry = OpLabel
3263 OpCopyMemorySized %var1 %var2 %int_16
3264 OpReturn
3265 OpFunctionEnd
3266 )";
3267 
3268   CompileSuccessfully(spirv);
3269   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3270   EXPECT_THAT(getDiagnosticString(), Eq(""));
3271 }
3272 
TEST_F(ValidateMemory,CopyMemorySizedSimpleMixedAccessGood)3273 TEST_F(ValidateMemory, CopyMemorySizedSimpleMixedAccessGood) {
3274   // Test one memory access operand using features that don't require the
3275   // Vulkan memory model.
3276   const std::string spirv = R"(
3277 OpCapability Shader
3278 OpCapability Linkage
3279 OpCapability Addresses
3280 OpMemoryModel Logical GLSL450
3281 %void = OpTypeVoid
3282 %int = OpTypeInt 32 0
3283 %int_16 = OpConstant %int 16
3284 %int_ptr_priv = OpTypePointer Private %int
3285 %var1 = OpVariable %int_ptr_priv Private
3286 %var2 = OpVariable %int_ptr_priv Private
3287 %voidfn = OpTypeFunction %void
3288 %func = OpFunction %void None %voidfn
3289 %entry = OpLabel
3290 OpCopyMemorySized %var1 %var2 %int_16 Volatile|Aligned|Nontemporal 4
3291 OpReturn
3292 OpFunctionEnd
3293 )";
3294 
3295   CompileSuccessfully(spirv);
3296   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3297 }
3298 
TEST_F(ValidateMemory,CopyMemorySizedSimpleTwoMixedAccessV13Bad)3299 TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV13Bad) {
3300   // Two memory access operands is invalid up to SPIR-V 1.3
3301   const std::string spirv = R"(
3302 OpCapability Shader
3303 OpCapability Linkage
3304 OpCapability Addresses
3305 OpMemoryModel Logical GLSL450
3306 %void = OpTypeVoid
3307 %int = OpTypeInt 32 0
3308 %int_16 = OpConstant %int 16
3309 %int_ptr_priv = OpTypePointer Private %int
3310 %var1 = OpVariable %int_ptr_priv Private
3311 %var2 = OpVariable %int_ptr_priv Private
3312 %voidfn = OpTypeFunction %void
3313 %func = OpFunction %void None %voidfn
3314 %entry = OpLabel
3315 OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile
3316 OpReturn
3317 OpFunctionEnd
3318 )";
3319 
3320   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
3321   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
3322             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3323   EXPECT_THAT(
3324       getDiagnosticString(),
3325       HasSubstr("CopyMemorySized with two memory access operands requires "
3326                 "SPIR-V 1.4 or later"));
3327 }
3328 
TEST_F(ValidateMemory,CopyMemorySizedSimpleTwoMixedAccessV14Good)3329 TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV14Good) {
3330   // Two memory access operands is valid in SPIR-V 1.4
3331   const std::string spirv = R"(
3332 OpCapability Shader
3333 OpCapability Linkage
3334 OpCapability Addresses
3335 OpMemoryModel Logical GLSL450
3336 %void = OpTypeVoid
3337 %int = OpTypeInt 32 0
3338 %int_16 = OpConstant %int 16
3339 %int_ptr_priv = OpTypePointer Private %int
3340 %var1 = OpVariable %int_ptr_priv Private
3341 %var2 = OpVariable %int_ptr_priv Private
3342 %voidfn = OpTypeFunction %void
3343 %func = OpFunction %void None %voidfn
3344 %entry = OpLabel
3345 OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile
3346 OpReturn
3347 OpFunctionEnd
3348 )";
3349 
3350   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3351   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3352   EXPECT_THAT(getDiagnosticString(), Eq(""));
3353 }
3354 
3355 using ValidatePointerComparisons = spvtest::ValidateBase<std::string>;
3356 
TEST_P(ValidatePointerComparisons,Good)3357 TEST_P(ValidatePointerComparisons, Good) {
3358   const std::string operation = GetParam();
3359 
3360   std::string spirv = R"(
3361 OpCapability Shader
3362 OpCapability Linkage
3363 OpCapability VariablePointersStorageBuffer
3364 OpMemoryModel Logical GLSL450
3365 %void = OpTypeVoid
3366 %bool = OpTypeBool
3367 %int = OpTypeInt 32 0
3368 %ptr_int = OpTypePointer StorageBuffer %int
3369 %var = OpVariable %ptr_int StorageBuffer
3370 %func_ty = OpTypeFunction %void
3371 %func = OpFunction %void None %func_ty
3372 %1 = OpLabel
3373 %equal = )" + operation;
3374 
3375   if (operation == "OpPtrDiff") {
3376     spirv += " %int ";
3377   } else {
3378     spirv += " %bool ";
3379   }
3380 
3381   spirv += R"(%var %var
3382 OpReturn
3383 OpFunctionEnd
3384 )";
3385 
3386   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3387   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3388 }
3389 
TEST_P(ValidatePointerComparisons,GoodWorkgroup)3390 TEST_P(ValidatePointerComparisons, GoodWorkgroup) {
3391   const std::string operation = GetParam();
3392 
3393   std::string spirv = R"(
3394 OpCapability Shader
3395 OpCapability Linkage
3396 OpCapability VariablePointers
3397 OpMemoryModel Logical GLSL450
3398 %void = OpTypeVoid
3399 %bool = OpTypeBool
3400 %int = OpTypeInt 32 0
3401 %ptr_int = OpTypePointer Workgroup %int
3402 %var = OpVariable %ptr_int Workgroup
3403 %func_ty = OpTypeFunction %void
3404 %func = OpFunction %void None %func_ty
3405 %1 = OpLabel
3406 %equal = )" + operation;
3407 
3408   if (operation == "OpPtrDiff") {
3409     spirv += " %int ";
3410   } else {
3411     spirv += " %bool ";
3412   }
3413 
3414   spirv += R"(%var %var
3415 OpReturn
3416 OpFunctionEnd
3417 )";
3418 
3419   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3420   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3421 }
3422 
TEST_P(ValidatePointerComparisons,BadResultType)3423 TEST_P(ValidatePointerComparisons, BadResultType) {
3424   const std::string operation = GetParam();
3425 
3426   std::string spirv = R"(
3427 OpCapability Shader
3428 OpCapability Linkage
3429 OpCapability VariablePointersStorageBuffer
3430 OpMemoryModel Logical GLSL450
3431 %void = OpTypeVoid
3432 %bool = OpTypeBool
3433 %int = OpTypeInt 32 0
3434 %ptr_int = OpTypePointer StorageBuffer %int
3435 %var = OpVariable %ptr_int StorageBuffer
3436 %func_ty = OpTypeFunction %void
3437 %func = OpFunction %void None %func_ty
3438 %1 = OpLabel
3439 %equal = )" + operation;
3440 
3441   if (operation == "OpPtrDiff") {
3442     spirv += " %bool ";
3443   } else {
3444     spirv += " %int ";
3445   }
3446 
3447   spirv += R"(%var %var
3448 OpReturn
3449 OpFunctionEnd
3450 )";
3451 
3452   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3453   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3454   if (operation == "OpPtrDiff") {
3455     EXPECT_THAT(getDiagnosticString(),
3456                 HasSubstr("Result Type must be an integer scalar"));
3457   } else {
3458     EXPECT_THAT(getDiagnosticString(),
3459                 HasSubstr("Result Type must be OpTypeBool"));
3460   }
3461 }
3462 
TEST_P(ValidatePointerComparisons,BadCapabilities)3463 TEST_P(ValidatePointerComparisons, BadCapabilities) {
3464   const std::string operation = GetParam();
3465 
3466   std::string spirv = R"(
3467 OpCapability Shader
3468 OpCapability Linkage
3469 OpMemoryModel Logical GLSL450
3470 %void = OpTypeVoid
3471 %bool = OpTypeBool
3472 %int = OpTypeInt 32 0
3473 %ptr_int = OpTypePointer StorageBuffer %int
3474 %var = OpVariable %ptr_int StorageBuffer
3475 %func_ty = OpTypeFunction %void
3476 %func = OpFunction %void None %func_ty
3477 %1 = OpLabel
3478 %equal = )" + operation;
3479 
3480   if (operation == "OpPtrDiff") {
3481     spirv += " %int ";
3482   } else {
3483     spirv += " %bool ";
3484   }
3485 
3486   spirv += R"(%var %var
3487 OpReturn
3488 OpFunctionEnd
3489 )";
3490 
3491   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3492   if (operation == "OpPtrDiff") {
3493     // Gets caught by the grammar.
3494     EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
3495               ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3496   } else {
3497     EXPECT_EQ(SPV_ERROR_INVALID_ID,
3498               ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3499     EXPECT_THAT(getDiagnosticString(),
3500                 HasSubstr("Instruction cannot for logical addressing model be "
3501                           "used without a variable pointers capability"));
3502   }
3503 }
3504 
TEST_P(ValidatePointerComparisons,BadOperandType)3505 TEST_P(ValidatePointerComparisons, BadOperandType) {
3506   const std::string operation = GetParam();
3507 
3508   std::string spirv = R"(
3509 OpCapability Shader
3510 OpCapability Linkage
3511 OpCapability VariablePointersStorageBuffer
3512 OpMemoryModel Logical GLSL450
3513 %void = OpTypeVoid
3514 %bool = OpTypeBool
3515 %int = OpTypeInt 32 0
3516 %ptr_int = OpTypePointer StorageBuffer %int
3517 %var = OpVariable %ptr_int StorageBuffer
3518 %func_ty = OpTypeFunction %void
3519 %func = OpFunction %void None %func_ty
3520 %1 = OpLabel
3521 %ld = OpLoad %int %var
3522 %equal = )" + operation;
3523 
3524   if (operation == "OpPtrDiff") {
3525     spirv += " %int ";
3526   } else {
3527     spirv += " %bool ";
3528   }
3529 
3530   spirv += R"(%ld %ld
3531 OpReturn
3532 OpFunctionEnd
3533 )";
3534 
3535   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3536   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3537   EXPECT_THAT(getDiagnosticString(),
3538               HasSubstr("Operand type must be a pointer"));
3539 }
3540 
TEST_P(ValidatePointerComparisons,BadStorageClassWorkgroup)3541 TEST_P(ValidatePointerComparisons, BadStorageClassWorkgroup) {
3542   const std::string operation = GetParam();
3543 
3544   std::string spirv = R"(
3545 OpCapability Shader
3546 OpCapability Linkage
3547 OpCapability VariablePointersStorageBuffer
3548 OpMemoryModel Logical GLSL450
3549 %void = OpTypeVoid
3550 %bool = OpTypeBool
3551 %int = OpTypeInt 32 0
3552 %ptr_int = OpTypePointer Workgroup %int
3553 %var = OpVariable %ptr_int Workgroup
3554 %func_ty = OpTypeFunction %void
3555 %func = OpFunction %void None %func_ty
3556 %1 = OpLabel
3557 %equal = )" + operation;
3558 
3559   if (operation == "OpPtrDiff") {
3560     spirv += " %int ";
3561   } else {
3562     spirv += " %bool ";
3563   }
3564 
3565   spirv += R"(%var %var
3566 OpReturn
3567 OpFunctionEnd
3568 )";
3569 
3570   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3571   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3572   EXPECT_THAT(getDiagnosticString(),
3573               HasSubstr("Workgroup storage class pointer requires "
3574                         "VariablePointers capability to be specified"));
3575 }
3576 
TEST_P(ValidatePointerComparisons,BadStorageClass)3577 TEST_P(ValidatePointerComparisons, BadStorageClass) {
3578   const std::string operation = GetParam();
3579 
3580   std::string spirv = R"(
3581 OpCapability Shader
3582 OpCapability Linkage
3583 OpCapability VariablePointersStorageBuffer
3584 OpMemoryModel Logical GLSL450
3585 %void = OpTypeVoid
3586 %bool = OpTypeBool
3587 %int = OpTypeInt 32 0
3588 %ptr_int = OpTypePointer Private %int
3589 %var = OpVariable %ptr_int Private
3590 %func_ty = OpTypeFunction %void
3591 %func = OpFunction %void None %func_ty
3592 %1 = OpLabel
3593 %equal = )" + operation;
3594 
3595   if (operation == "OpPtrDiff") {
3596     spirv += " %int ";
3597   } else {
3598     spirv += " %bool ";
3599   }
3600 
3601   spirv += R"(%var %var
3602 OpReturn
3603 OpFunctionEnd
3604 )";
3605 
3606   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3607   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3608   EXPECT_THAT(getDiagnosticString(),
3609               HasSubstr("Invalid pointer storage class"));
3610 }
3611 
TEST_P(ValidatePointerComparisons,BadDiffOperandTypes)3612 TEST_P(ValidatePointerComparisons, BadDiffOperandTypes) {
3613   const std::string operation = GetParam();
3614 
3615   std::string spirv = R"(
3616 OpCapability Shader
3617 OpCapability Linkage
3618 OpCapability VariablePointersStorageBuffer
3619 OpMemoryModel Logical GLSL450
3620 %void = OpTypeVoid
3621 %bool = OpTypeBool
3622 %int = OpTypeInt 32 0
3623 %ptr_int = OpTypePointer Private %int
3624 %var = OpVariable %ptr_int Private
3625 %func_ty = OpTypeFunction %void
3626 %func = OpFunction %void None %func_ty
3627 %1 = OpLabel
3628 %ld = OpLoad %int %var
3629 %equal = )" + operation;
3630 
3631   if (operation == "OpPtrDiff") {
3632     spirv += " %int ";
3633   } else {
3634     spirv += " %bool ";
3635   }
3636 
3637   spirv += R"(%var %ld
3638 OpReturn
3639 OpFunctionEnd
3640 )";
3641 
3642   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3643   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3644   EXPECT_THAT(getDiagnosticString(),
3645               HasSubstr("The types of Operand 1 and Operand 2 must match"));
3646 }
3647 
3648 INSTANTIATE_TEST_SUITE_P(PointerComparisons, ValidatePointerComparisons,
3649                          Values("OpPtrEqual", "OpPtrNotEqual", "OpPtrDiff"));
3650 
TEST_F(ValidateMemory,VariableInitializerWrongType)3651 TEST_F(ValidateMemory, VariableInitializerWrongType) {
3652   const std::string spirv = R"(
3653 OpCapability Shader
3654 OpCapability Linkage
3655 OpCapability VariablePointersStorageBuffer
3656 OpMemoryModel Logical GLSL450
3657 %void = OpTypeVoid
3658 %int = OpTypeInt 32 0
3659 %float = OpTypeFloat 32
3660 %ptr_wg_int = OpTypePointer Workgroup %int
3661 %ptr_wg_float = OpTypePointer Workgroup %int
3662 %wg_var = OpVariable %ptr_wg_int Workgroup
3663 %ptr_private_wg_float = OpTypePointer Private %ptr_wg_float
3664 %priv_var = OpVariable %ptr_private_wg_float Private %wg_var
3665 )";
3666 
3667   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
3668   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3669   EXPECT_THAT(getDiagnosticString(),
3670               HasSubstr("Initializer type must match the type pointed to by "
3671                         "the Result Type"));
3672 }
3673 
TEST_F(ValidateMemory,StoreToUniformBlock)3674 TEST_F(ValidateMemory, StoreToUniformBlock) {
3675   const std::string spirv = R"(
3676 OpCapability Shader
3677 OpMemoryModel Logical GLSL450
3678 OpEntryPoint GLCompute %main "main"
3679 OpExecutionMode %main LocalSize 1 1 1
3680 OpDecorate %struct Block
3681 OpMemberDecorate %struct 0 Offset 0
3682 OpDecorate %var DescriptorSet 0
3683 OpDecorate %var Binding 0
3684 %void = OpTypeVoid
3685 %int = OpTypeInt 32 0
3686 %int_0 = OpConstant %int 0
3687 %int4 = OpTypeVector %int 4
3688 %struct = OpTypeStruct %int4
3689 %ptr_uniform_struct = OpTypePointer Uniform %struct
3690 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3691 %ptr_uniform_int = OpTypePointer Uniform %int
3692 %var = OpVariable %ptr_uniform_struct Uniform
3693 %void_fn = OpTypeFunction %void
3694 %main = OpFunction %void None %void_fn
3695 %entry = OpLabel
3696 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3697 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3698 OpStore %gep2 %int_0
3699 OpReturn
3700 OpFunctionEnd
3701 )";
3702 
3703   CompileSuccessfully(spirv);
3704   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3705 }
3706 
TEST_F(ValidateMemory,StoreToUniformBlockVulkan)3707 TEST_F(ValidateMemory, StoreToUniformBlockVulkan) {
3708   const std::string spirv = R"(
3709 OpCapability Shader
3710 OpMemoryModel Logical GLSL450
3711 OpEntryPoint GLCompute %main "main"
3712 OpExecutionMode %main LocalSize 1 1 1
3713 OpDecorate %struct Block
3714 OpMemberDecorate %struct 0 Offset 0
3715 OpDecorate %var DescriptorSet 0
3716 OpDecorate %var Binding 0
3717 %void = OpTypeVoid
3718 %int = OpTypeInt 32 0
3719 %int_0 = OpConstant %int 0
3720 %int4 = OpTypeVector %int 4
3721 %struct = OpTypeStruct %int4
3722 %ptr_uniform_struct = OpTypePointer Uniform %struct
3723 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3724 %ptr_uniform_int = OpTypePointer Uniform %int
3725 %var = OpVariable %ptr_uniform_struct Uniform
3726 %void_fn = OpTypeFunction %void
3727 %main = OpFunction %void None %void_fn
3728 %entry = OpLabel
3729 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3730 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3731 OpStore %gep2 %int_0
3732 OpReturn
3733 OpFunctionEnd
3734 )";
3735 
3736   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3737   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3738   EXPECT_THAT(getDiagnosticString(),
3739               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3740   EXPECT_THAT(
3741       getDiagnosticString(),
3742       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3743 }
3744 
3745 // This test requires that the struct is not id 2.
TEST_F(ValidateMemory,StoreToUniformBlockVulkan2)3746 TEST_F(ValidateMemory, StoreToUniformBlockVulkan2) {
3747   const std::string spirv = R"(
3748 OpCapability Shader
3749 OpMemoryModel Logical GLSL450
3750 OpEntryPoint GLCompute %main "main" %gid_var
3751 OpExecutionMode %main LocalSize 1 1 1
3752 OpDecorate %3 Block
3753 OpMemberDecorate %3 0 Offset 0
3754 OpDecorate %var DescriptorSet 0
3755 OpDecorate %var Binding 0
3756 OpDecorate %gid_var BuiltIn GlobalInvocationId
3757 %void = OpTypeVoid
3758 %int = OpTypeInt 32 0
3759 %int_0 = OpConstant %int 0
3760 %int3 = OpTypeVector %int 3
3761 %int4 = OpTypeVector %int 4
3762 %3 = OpTypeStruct %int4
3763 %ptr_uniform_struct = OpTypePointer Uniform %3
3764 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3765 %ptr_uniform_int = OpTypePointer Uniform %int
3766 %var = OpVariable %ptr_uniform_struct Uniform
3767 %ptr_input_int3 = OpTypePointer Input %int3
3768 %gid_var = OpVariable %ptr_input_int3 Input
3769 %void_fn = OpTypeFunction %void
3770 %main = OpFunction %void None %void_fn
3771 %entry = OpLabel
3772 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3773 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3774 OpStore %gep2 %int_0
3775 OpReturn
3776 OpFunctionEnd
3777 )";
3778 
3779   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3780   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3781   EXPECT_THAT(getDiagnosticString(),
3782               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3783   EXPECT_THAT(
3784       getDiagnosticString(),
3785       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3786 }
3787 
TEST_F(ValidateMemory,StoreToUniformBufferBlockVulkan)3788 TEST_F(ValidateMemory, StoreToUniformBufferBlockVulkan) {
3789   const std::string spirv = R"(
3790 OpCapability Shader
3791 OpMemoryModel Logical GLSL450
3792 OpEntryPoint GLCompute %main "main"
3793 OpExecutionMode %main LocalSize 1 1 1
3794 OpDecorate %struct BufferBlock
3795 OpMemberDecorate %struct 0 Offset 0
3796 OpDecorate %var DescriptorSet 0
3797 OpDecorate %var Binding 0
3798 %void = OpTypeVoid
3799 %int = OpTypeInt 32 0
3800 %int_0 = OpConstant %int 0
3801 %int4 = OpTypeVector %int 4
3802 %struct = OpTypeStruct %int4
3803 %ptr_uniform_struct = OpTypePointer Uniform %struct
3804 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3805 %ptr_uniform_int = OpTypePointer Uniform %int
3806 %var = OpVariable %ptr_uniform_struct Uniform
3807 %void_fn = OpTypeFunction %void
3808 %main = OpFunction %void None %void_fn
3809 %entry = OpLabel
3810 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3811 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3812 OpStore %gep2 %int_0
3813 OpReturn
3814 OpFunctionEnd
3815 )";
3816 
3817   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3818   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3819 }
3820 
TEST_F(ValidateMemory,StoreToUniformBlockVulkanArray)3821 TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray) {
3822   const std::string spirv = R"(
3823 OpCapability Shader
3824 OpMemoryModel Logical GLSL450
3825 OpEntryPoint GLCompute %main "main"
3826 OpExecutionMode %main LocalSize 1 1 1
3827 OpDecorate %struct Block
3828 OpMemberDecorate %struct 0 Offset 0
3829 OpDecorate %var DescriptorSet 0
3830 OpDecorate %var Binding 0
3831 %void = OpTypeVoid
3832 %int = OpTypeInt 32 0
3833 %int_0 = OpConstant %int 0
3834 %int_1 = OpConstant %int 1
3835 %int4 = OpTypeVector %int 4
3836 %struct = OpTypeStruct %int4
3837 %array_struct = OpTypeArray %struct %int_1
3838 %ptr_uniform_array = OpTypePointer Uniform %array_struct
3839 %ptr_uniform_struct = OpTypePointer Uniform %struct
3840 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3841 %ptr_uniform_int = OpTypePointer Uniform %int
3842 %var = OpVariable %ptr_uniform_array Uniform
3843 %void_fn = OpTypeFunction %void
3844 %main = OpFunction %void None %void_fn
3845 %entry = OpLabel
3846 %gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0
3847 %gep2 = OpCopyObject %ptr_uniform_int %gep1
3848 OpStore %gep2 %int_0
3849 OpReturn
3850 OpFunctionEnd
3851 )";
3852 
3853   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3854   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3855   EXPECT_THAT(getDiagnosticString(),
3856               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3857   EXPECT_THAT(
3858       getDiagnosticString(),
3859       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3860 }
3861 
3862 // This test requires that the struct is not id 2.
TEST_F(ValidateMemory,StoreToUniformBlockVulkanArray2)3863 TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray2) {
3864   const std::string spirv = R"(
3865 OpCapability Shader
3866 OpMemoryModel Logical GLSL450
3867 OpEntryPoint GLCompute %main "main" %gid_var
3868 OpExecutionMode %main LocalSize 1 1 1
3869 OpDecorate %struct Block
3870 OpMemberDecorate %struct 0 Offset 0
3871 OpDecorate %var DescriptorSet 0
3872 OpDecorate %var Binding 0
3873 OpDecorate %gid_var BuiltIn GlobalInvocationId
3874 %void = OpTypeVoid
3875 %int = OpTypeInt 32 0
3876 %int_0 = OpConstant %int 0
3877 %int_1 = OpConstant %int 1
3878 %int3 = OpTypeVector %int 3
3879 %int4 = OpTypeVector %int 4
3880 %struct = OpTypeStruct %int4
3881 %array_struct = OpTypeArray %struct %int_1
3882 %ptr_uniform_array = OpTypePointer Uniform %array_struct
3883 %ptr_uniform_struct = OpTypePointer Uniform %struct
3884 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3885 %ptr_uniform_int = OpTypePointer Uniform %int
3886 %var = OpVariable %ptr_uniform_array Uniform
3887 %ptr_input_int3 = OpTypePointer Input %int3
3888 %gid_var = OpVariable %ptr_input_int3 Input
3889 %void_fn = OpTypeFunction %void
3890 %main = OpFunction %void None %void_fn
3891 %entry = OpLabel
3892 %gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0
3893 %gep2 = OpCopyObject %ptr_uniform_int %gep1
3894 OpStore %gep2 %int_0
3895 OpReturn
3896 OpFunctionEnd
3897 )";
3898 
3899   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3900   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3901   EXPECT_THAT(getDiagnosticString(),
3902               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3903   EXPECT_THAT(
3904       getDiagnosticString(),
3905       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3906 }
3907 
TEST_F(ValidateMemory,StoreToUniformBlockVulkanRuntimeArray)3908 TEST_F(ValidateMemory, StoreToUniformBlockVulkanRuntimeArray) {
3909   const std::string spirv = R"(
3910 OpCapability Shader
3911 OpCapability RuntimeDescriptorArrayEXT
3912 OpExtension "SPV_EXT_descriptor_indexing"
3913 OpMemoryModel Logical GLSL450
3914 OpEntryPoint GLCompute %main "main"
3915 OpExecutionMode %main LocalSize 1 1 1
3916 OpDecorate %struct Block
3917 OpMemberDecorate %struct 0 Offset 0
3918 OpDecorate %var DescriptorSet 0
3919 OpDecorate %var Binding 0
3920 %void = OpTypeVoid
3921 %int = OpTypeInt 32 0
3922 %int_0 = OpConstant %int 0
3923 %int4 = OpTypeVector %int 4
3924 %struct = OpTypeStruct %int4
3925 %array_struct = OpTypeRuntimeArray %struct
3926 %ptr_uniform_array = OpTypePointer Uniform %array_struct
3927 %ptr_uniform_struct = OpTypePointer Uniform %struct
3928 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3929 %ptr_uniform_int = OpTypePointer Uniform %int
3930 %var = OpVariable %ptr_uniform_array Uniform
3931 %void_fn = OpTypeFunction %void
3932 %main = OpFunction %void None %void_fn
3933 %entry = OpLabel
3934 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 %int_0
3935 %gep2 = OpInBoundsAccessChain %ptr_uniform_int %gep1 %int_0
3936 OpStore %gep2 %int_0
3937 OpReturn
3938 OpFunctionEnd
3939 )";
3940 
3941   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3942   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3943   EXPECT_THAT(getDiagnosticString(),
3944               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3945   EXPECT_THAT(
3946       getDiagnosticString(),
3947       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3948 }
3949 
3950 using ValidateSizedVariable = spvtest::ValidateBase<
3951     std::tuple<std::string, std::string, std::string, spv_target_env>>;
3952 
GetSizedVariableCodeGenerator(bool is_8bit,bool buffer_block)3953 CodeGenerator GetSizedVariableCodeGenerator(bool is_8bit, bool buffer_block) {
3954   CodeGenerator generator;
3955   generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n";
3956   generator.extensions_ =
3957       "OpExtension \"SPV_KHR_16bit_storage\"\nOpExtension "
3958       "\"SPV_KHR_8bit_storage\"\n";
3959   generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
3960   if (is_8bit) {
3961     generator.before_types_ =
3962         "OpMemberDecorate %char_buffer_block 0 Offset 0\n";
3963     if (buffer_block)
3964       generator.before_types_ += "OpDecorate %char_buffer_block BufferBlock\n";
3965 
3966     generator.types_ = R"(%void = OpTypeVoid
3967 %char = OpTypeInt 8 0
3968 %char4 = OpTypeVector %char 4
3969 %char_buffer_block = OpTypeStruct %char
3970 )";
3971   } else {
3972     generator.before_types_ =
3973         "OpMemberDecorate %half_buffer_block 0 Offset 0\n"
3974         "OpMemberDecorate %short_buffer_block 0 Offset 0\n";
3975     if (buffer_block) {
3976       generator.before_types_ +=
3977           "OpDecorate %half_buffer_block BufferBlock\n"
3978           "OpDecorate %short_buffer_block BufferBlock\n";
3979     }
3980 
3981     generator.types_ = R"(%void = OpTypeVoid
3982 %short = OpTypeInt 16 0
3983 %half = OpTypeFloat 16
3984 %short4 = OpTypeVector %short 4
3985 %half4 = OpTypeVector %half 4
3986 %mat4x4 = OpTypeMatrix %half4 4
3987 %short_buffer_block = OpTypeStruct %short
3988 %half_buffer_block = OpTypeStruct %half
3989 )";
3990   }
3991   generator.after_types_ = R"(%void_fn = OpTypeFunction %void
3992 %func = OpFunction %void None %void_fn
3993 %entry = OpLabel
3994 )";
3995   generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n";
3996   return generator;
3997 }
3998 
TEST_P(ValidateSizedVariable,Capability)3999 TEST_P(ValidateSizedVariable, Capability) {
4000   const std::string storage_class = std::get<0>(GetParam());
4001   const std::string capability = std::get<1>(GetParam());
4002   const std::string var_type = std::get<2>(GetParam());
4003   const spv_target_env target = std::get<3>(GetParam());
4004 
4005   ASSERT_TRUE(target == SPV_ENV_UNIVERSAL_1_3 ||
4006               target == SPV_ENV_UNIVERSAL_1_4);
4007 
4008   bool type_8bit = false;
4009   if (var_type == "%char" || var_type == "%char4" ||
4010       var_type == "%char_buffer_block") {
4011     type_8bit = true;
4012   }
4013 
4014   const bool buffer_block = var_type.find("buffer_block") != std::string::npos;
4015 
4016   auto generator = GetSizedVariableCodeGenerator(type_8bit, buffer_block);
4017 
4018   if (capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR" ||
4019       capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR") {
4020     generator.extensions_ +=
4021         "OpExtension \"SPV_KHR_workgroup_memory_explicit_layout\"\n";
4022   }
4023 
4024   generator.types_ += "%ptr_type = OpTypePointer " + storage_class + " " +
4025                       var_type + "\n%var = OpVariable %ptr_type " +
4026                       storage_class + "\n";
4027   generator.capabilities_ += "OpCapability " + capability + "\n";
4028 
4029   bool capability_ok = false;
4030   bool storage_class_ok = false;
4031   if (storage_class == "Input" || storage_class == "Output") {
4032     if (!type_8bit) {
4033       capability_ok = capability == "StorageInputOutput16";
4034       storage_class_ok = true;
4035     }
4036   } else if (storage_class == "StorageBuffer") {
4037     if (type_8bit) {
4038       capability_ok = capability == "StorageBuffer8BitAccess" ||
4039                       capability == "UniformAndStorageBuffer8BitAccess";
4040     } else {
4041       capability_ok = capability == "StorageBuffer16BitAccess" ||
4042                       capability == "UniformAndStorageBuffer16BitAccess";
4043     }
4044     storage_class_ok = true;
4045   } else if (storage_class == "PushConstant") {
4046     if (type_8bit) {
4047       capability_ok = capability == "StoragePushConstant8";
4048     } else {
4049       capability_ok = capability == "StoragePushConstant16";
4050     }
4051     storage_class_ok = true;
4052   } else if (storage_class == "Uniform") {
4053     if (type_8bit) {
4054       capability_ok = capability == "UniformAndStorageBuffer8BitAccess" ||
4055                       (capability == "StorageBuffer8BitAccess" && buffer_block);
4056     } else {
4057       capability_ok =
4058           capability == "UniformAndStorageBuffer16BitAccess" ||
4059           (capability == "StorageBuffer16BitAccess" && buffer_block);
4060     }
4061     storage_class_ok = true;
4062   } else if (storage_class == "Workgroup") {
4063     if (type_8bit) {
4064       capability_ok =
4065           capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR";
4066     } else {
4067       capability_ok =
4068           capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR";
4069     }
4070     storage_class_ok = true;
4071   }
4072 
4073   CompileSuccessfully(generator.Build(), target);
4074   spv_result_t result = ValidateInstructions(target);
4075   if (target < SPV_ENV_UNIVERSAL_1_4 &&
4076       (capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR" ||
4077        capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR")) {
4078     EXPECT_EQ(SPV_ERROR_WRONG_VERSION, result);
4079     EXPECT_THAT(getDiagnosticString(),
4080                 HasSubstr("requires SPIR-V version 1.4 or later"));
4081   } else if (buffer_block && target > SPV_ENV_UNIVERSAL_1_3) {
4082     EXPECT_EQ(SPV_ERROR_WRONG_VERSION, result);
4083     EXPECT_THAT(getDiagnosticString(),
4084                 HasSubstr("requires SPIR-V version 1.3 or earlier"));
4085   } else if (capability_ok) {
4086     EXPECT_EQ(SPV_SUCCESS, result);
4087   } else {
4088     EXPECT_EQ(SPV_ERROR_INVALID_ID, result);
4089     if (storage_class_ok) {
4090       std::string message = std::string("Allocating a variable containing a ") +
4091                             (type_8bit ? "8" : "16") + "-bit element in " +
4092                             storage_class +
4093                             " storage class requires an additional capability";
4094       EXPECT_THAT(getDiagnosticString(), HasSubstr(message));
4095     } else {
4096       std::string message =
4097           std::string("Cannot allocate a variable containing a ") +
4098           (type_8bit ? "8" : "16") + "-bit type in " + storage_class +
4099           " storage class";
4100       EXPECT_THAT(getDiagnosticString(), HasSubstr(message));
4101     }
4102   }
4103 }
4104 
4105 INSTANTIATE_TEST_SUITE_P(
4106     Storage8, ValidateSizedVariable,
4107     Combine(Values("UniformConstant", "Input", "Output", "Workgroup",
4108                    "CrossWorkgroup", "Private", "StorageBuffer", "Uniform"),
4109             Values("StorageBuffer8BitAccess",
4110                    "UniformAndStorageBuffer8BitAccess", "StoragePushConstant8",
4111                    "WorkgroupMemoryExplicitLayout8BitAccessKHR"),
4112             Values("%char", "%char4", "%char_buffer_block"),
4113             Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4)));
4114 
4115 INSTANTIATE_TEST_SUITE_P(
4116     Storage16, ValidateSizedVariable,
4117     Combine(Values("UniformConstant", "Input", "Output", "Workgroup",
4118                    "CrossWorkgroup", "Private", "StorageBuffer", "Uniform"),
4119             Values("StorageBuffer16BitAccess",
4120                    "UniformAndStorageBuffer16BitAccess",
4121                    "StoragePushConstant16", "StorageInputOutput16",
4122                    "WorkgroupMemoryExplicitLayout16BitAccessKHR"),
4123             Values("%short", "%half", "%short4", "%half4", "%mat4x4",
4124                    "%short_buffer_block", "%half_buffer_block"),
4125             Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4)));
4126 
4127 using ValidateSizedLoadStore =
4128     spvtest::ValidateBase<std::tuple<std::string, uint32_t, std::string>>;
4129 
GetSizedLoadStoreCodeGenerator(const std::string & base_type,uint32_t width)4130 CodeGenerator GetSizedLoadStoreCodeGenerator(const std::string& base_type,
4131                                              uint32_t width) {
4132   CodeGenerator generator;
4133   generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n";
4134   if (width == 8) {
4135     generator.capabilities_ +=
4136         "OpCapability UniformAndStorageBuffer8BitAccess\n";
4137     generator.extensions_ = "OpExtension \"SPV_KHR_8bit_storage\"\n";
4138   } else {
4139     generator.capabilities_ +=
4140         "OpCapability UniformAndStorageBuffer16BitAccess\n";
4141     generator.extensions_ = "OpExtension \"SPV_KHR_16bit_storage\"\n";
4142   }
4143   generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
4144   generator.before_types_ = R"(OpDecorate %block Block
4145 OpMemberDecorate %block 0 Offset 0
4146 OpMemberDecorate %struct 0 Offset 0
4147 )";
4148   generator.types_ = R"(%void = OpTypeVoid
4149 %int = OpTypeInt 32 0
4150 %int_0 = OpConstant %int 0
4151 %int_1 = OpConstant %int 1
4152 %int_2 = OpConstant %int 2
4153 %int_3 = OpConstant %int 3
4154 )";
4155 
4156   if (width == 8) {
4157     generator.types_ += R"(%scalar = OpTypeInt 8 0
4158 %vector = OpTypeVector %scalar 4
4159 %struct = OpTypeStruct %vector
4160 )";
4161   } else if (base_type == "int") {
4162     generator.types_ += R"(%scalar = OpTypeInt 16 0
4163 %vector = OpTypeVector %scalar 4
4164 %struct = OpTypeStruct %vector
4165 )";
4166   } else {
4167     generator.types_ += R"(%scalar = OpTypeFloat 16
4168 %vector = OpTypeVector %scalar 4
4169 %matrix = OpTypeMatrix %vector 4
4170 %struct = OpTypeStruct %matrix
4171 %ptr_ssbo_matrix = OpTypePointer StorageBuffer %matrix
4172 )";
4173     generator.before_types_ += R"(OpMemberDecorate %struct 0 RowMajor
4174 OpMemberDecorate %struct 0 MatrixStride 16
4175 )";
4176   }
4177   generator.types_ += R"(%block = OpTypeStruct %struct
4178 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
4179 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
4180 %ptr_ssbo_vector = OpTypePointer StorageBuffer %vector
4181 %ptr_ssbo_scalar = OpTypePointer StorageBuffer %scalar
4182 %ld_var = OpVariable %ptr_ssbo_block StorageBuffer
4183 %st_var = OpVariable %ptr_ssbo_block StorageBuffer
4184 )";
4185 
4186   generator.after_types_ = R"(%void_fn = OpTypeFunction %void
4187 %func = OpFunction %void None %void_fn
4188 %entry = OpLabel
4189 )";
4190   generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n";
4191   return generator;
4192 }
4193 
TEST_P(ValidateSizedLoadStore,Load)4194 TEST_P(ValidateSizedLoadStore, Load) {
4195   std::string base_type = std::get<0>(GetParam());
4196   uint32_t width = std::get<1>(GetParam());
4197   std::string mem_type = std::get<2>(GetParam());
4198 
4199   CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width);
4200   generator.after_types_ +=
4201       "%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0";
4202   if (mem_type != "struct") {
4203     generator.after_types_ += " %int_0";
4204     if (mem_type != "matrix" && base_type == "float") {
4205       generator.after_types_ += " %int_0";
4206     }
4207     if (mem_type == "scalar") {
4208       generator.after_types_ += " %int_0";
4209     }
4210   }
4211   generator.after_types_ += "\n";
4212   generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n";
4213 
4214   CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
4215   if (mem_type == "struct") {
4216     EXPECT_EQ(SPV_ERROR_INVALID_ID,
4217               ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4218     EXPECT_THAT(
4219         getDiagnosticString(),
4220         HasSubstr(
4221             "8- or 16-bit loads must be a scalar, vector or matrix type"));
4222   } else {
4223     EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4224   }
4225 }
4226 
TEST_P(ValidateSizedLoadStore,Store)4227 TEST_P(ValidateSizedLoadStore, Store) {
4228   std::string base_type = std::get<0>(GetParam());
4229   uint32_t width = std::get<1>(GetParam());
4230   std::string mem_type = std::get<2>(GetParam());
4231 
4232   CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width);
4233   generator.after_types_ +=
4234       "%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0";
4235   if (mem_type != "struct") {
4236     generator.after_types_ += " %int_0";
4237     if (mem_type != "matrix" && base_type == "float") {
4238       generator.after_types_ += " %int_0";
4239     }
4240     if (mem_type == "scalar") {
4241       generator.after_types_ += " %int_0";
4242     }
4243   }
4244   generator.after_types_ += "\n";
4245   generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n";
4246   generator.after_types_ +=
4247       "%st_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %st_var %int_0";
4248   if (mem_type != "struct") {
4249     generator.after_types_ += " %int_0";
4250     if (mem_type != "matrix" && base_type == "float") {
4251       generator.after_types_ += " %int_0";
4252     }
4253     if (mem_type == "scalar") {
4254       generator.after_types_ += " %int_0";
4255     }
4256   }
4257   generator.after_types_ += "\n";
4258   generator.after_types_ += "OpStore %st_gep %ld\n";
4259 
4260   CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
4261   if (mem_type == "struct") {
4262     EXPECT_EQ(SPV_ERROR_INVALID_ID,
4263               ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4264     // Can only catch the load.
4265     EXPECT_THAT(
4266         getDiagnosticString(),
4267         HasSubstr(
4268             "8- or 16-bit loads must be a scalar, vector or matrix type"));
4269   } else {
4270     EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4271   }
4272 }
4273 
4274 INSTANTIATE_TEST_SUITE_P(LoadStoreInt8, ValidateSizedLoadStore,
4275                          Combine(Values("int"), Values(8u),
4276                                  Values("scalar", "vector", "struct")));
4277 INSTANTIATE_TEST_SUITE_P(LoadStoreInt16, ValidateSizedLoadStore,
4278                          Combine(Values("int"), Values(16u),
4279                                  Values("scalar", "vector", "struct")));
4280 INSTANTIATE_TEST_SUITE_P(LoadStoreFloat16, ValidateSizedLoadStore,
4281                          Combine(Values("float"), Values(16u),
4282                                  Values("scalar", "vector", "matrix",
4283                                         "struct")));
4284 
TEST_F(ValidateMemory,SmallStorageCopyMemoryChar)4285 TEST_F(ValidateMemory, SmallStorageCopyMemoryChar) {
4286   const std::string spirv = R"(
4287 OpCapability Shader
4288 OpCapability Linkage
4289 OpCapability UniformAndStorageBuffer8BitAccess
4290 OpExtension "SPV_KHR_8bit_storage"
4291 OpMemoryModel Logical GLSL450
4292 OpDecorate %block Block
4293 OpMemberDecorate %block 0 Offset 0
4294 %void = OpTypeVoid
4295 %int = OpTypeInt 32 0
4296 %int_0 = OpConstant %int 0
4297 %char = OpTypeInt 8 0
4298 %block = OpTypeStruct %char
4299 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
4300 %in = OpVariable %ptr_ssbo_block StorageBuffer
4301 %out = OpVariable %ptr_ssbo_block StorageBuffer
4302 %void_fn = OpTypeFunction %void
4303 %func = OpFunction %void None %void_fn
4304 %entry = OpLabel
4305 OpCopyMemory %out %in
4306 OpReturn
4307 OpFunctionEnd
4308 )";
4309 
4310   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4311   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4312   EXPECT_THAT(
4313       getDiagnosticString(),
4314       HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
4315 }
4316 
TEST_F(ValidateMemory,SmallStorageCopyMemoryShort)4317 TEST_F(ValidateMemory, SmallStorageCopyMemoryShort) {
4318   const std::string spirv = R"(
4319 OpCapability Shader
4320 OpCapability Linkage
4321 OpCapability UniformAndStorageBuffer16BitAccess
4322 OpExtension "SPV_KHR_16bit_storage"
4323 OpMemoryModel Logical GLSL450
4324 OpDecorate %block Block
4325 OpMemberDecorate %block 0 Offset 0
4326 %void = OpTypeVoid
4327 %int = OpTypeInt 32 0
4328 %int_0 = OpConstant %int 0
4329 %short = OpTypeInt 16 0
4330 %block = OpTypeStruct %short
4331 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
4332 %in = OpVariable %ptr_ssbo_block StorageBuffer
4333 %out = OpVariable %ptr_ssbo_block StorageBuffer
4334 %void_fn = OpTypeFunction %void
4335 %func = OpFunction %void None %void_fn
4336 %entry = OpLabel
4337 OpCopyMemory %out %in
4338 OpReturn
4339 OpFunctionEnd
4340 )";
4341 
4342   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4343   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4344   EXPECT_THAT(
4345       getDiagnosticString(),
4346       HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
4347 }
4348 
TEST_F(ValidateMemory,SmallStorageCopyMemoryHalf)4349 TEST_F(ValidateMemory, SmallStorageCopyMemoryHalf) {
4350   const std::string spirv = R"(
4351 OpCapability Shader
4352 OpCapability Linkage
4353 OpCapability UniformAndStorageBuffer16BitAccess
4354 OpExtension "SPV_KHR_16bit_storage"
4355 OpMemoryModel Logical GLSL450
4356 OpDecorate %block Block
4357 OpMemberDecorate %block 0 Offset 0
4358 %void = OpTypeVoid
4359 %int = OpTypeInt 32 0
4360 %int_0 = OpConstant %int 0
4361 %half = OpTypeFloat 16
4362 %block = OpTypeStruct %half
4363 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
4364 %in = OpVariable %ptr_ssbo_block StorageBuffer
4365 %out = OpVariable %ptr_ssbo_block StorageBuffer
4366 %void_fn = OpTypeFunction %void
4367 %func = OpFunction %void None %void_fn
4368 %entry = OpLabel
4369 OpCopyMemory %out %in
4370 OpReturn
4371 OpFunctionEnd
4372 )";
4373 
4374   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4375   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4376   EXPECT_THAT(
4377       getDiagnosticString(),
4378       HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
4379 }
4380 
TEST_F(ValidateMemory,SmallStorageVariableArrayBufferBlockShort)4381 TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockShort) {
4382   const std::string spirv = R"(
4383 OpCapability Shader
4384 OpCapability Linkage
4385 OpCapability StorageBuffer16BitAccess
4386 OpExtension "SPV_KHR_16bit_storage"
4387 OpMemoryModel Logical GLSL450
4388 OpDecorate %block BufferBlock
4389 OpMemberDecorate %block 0 Offset 0
4390 %void = OpTypeVoid
4391 %short = OpTypeInt 16 0
4392 %int = OpTypeInt 32 0
4393 %int_4 = OpConstant %int 4
4394 %block = OpTypeStruct %short
4395 %block_array = OpTypeArray %block %int_4
4396 %ptr_block_array = OpTypePointer Uniform %block_array
4397 %var = OpVariable %ptr_block_array Uniform
4398 )";
4399 
4400   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4401   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4402 }
4403 
TEST_F(ValidateMemory,SmallStorageVariableArrayBufferBlockChar)4404 TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockChar) {
4405   const std::string spirv = R"(
4406 OpCapability Shader
4407 OpCapability Linkage
4408 OpCapability StorageBuffer8BitAccess
4409 OpExtension "SPV_KHR_8bit_storage"
4410 OpMemoryModel Logical GLSL450
4411 OpDecorate %block BufferBlock
4412 OpMemberDecorate %block 0 Offset 0
4413 %void = OpTypeVoid
4414 %char = OpTypeInt 8 0
4415 %int = OpTypeInt 32 0
4416 %int_4 = OpConstant %int 4
4417 %block = OpTypeStruct %char
4418 %block_array = OpTypeArray %block %int_4
4419 %ptr_block_array = OpTypePointer Uniform %block_array
4420 %var = OpVariable %ptr_block_array Uniform
4421 )";
4422 
4423   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4424   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4425 }
4426 
TEST_F(ValidateMemory,SmallStorageVariableArrayBufferBlockHalf)4427 TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockHalf) {
4428   const std::string spirv = R"(
4429 OpCapability Shader
4430 OpCapability Linkage
4431 OpCapability StorageBuffer16BitAccess
4432 OpExtension "SPV_KHR_16bit_storage"
4433 OpMemoryModel Logical GLSL450
4434 OpDecorate %block BufferBlock
4435 OpMemberDecorate %block 0 Offset 0
4436 %void = OpTypeVoid
4437 %half = OpTypeFloat 16
4438 %int = OpTypeInt 32 0
4439 %int_4 = OpConstant %int 4
4440 %block = OpTypeStruct %half
4441 %block_array = OpTypeArray %block %int_4
4442 %ptr_block_array = OpTypePointer Uniform %block_array
4443 %var = OpVariable %ptr_block_array Uniform
4444 )";
4445 
4446   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4447   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4448 }
4449 
TEST_F(ValidateMemory,VulkanStorageBufferNotAStruct)4450 TEST_F(ValidateMemory, VulkanStorageBufferNotAStruct) {
4451   const std::string spirv = R"(
4452 OpCapability Shader
4453 OpExtension "SPV_KHR_storage_buffer_storage_class"
4454 OpMemoryModel Logical GLSL450
4455 OpEntryPoint GLCompute %main "main"
4456 OpExecutionMode %main LocalSize 1 1 1
4457 %void = OpTypeVoid
4458 %uint = OpTypeInt 32 0
4459 %ptr_ssbo = OpTypePointer StorageBuffer %uint
4460 %var = OpVariable %ptr_ssbo StorageBuffer
4461 %void_fn = OpTypeFunction %void
4462 %main = OpFunction %void None %void_fn
4463 %entry = OpLabel
4464 OpReturn
4465 OpFunctionEnd
4466 )";
4467 
4468   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4469   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4470   EXPECT_THAT(getDiagnosticString(),
4471               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
4472   EXPECT_THAT(
4473       getDiagnosticString(),
4474       HasSubstr("From Vulkan spec:\nVariables identified with "
4475                 "the StorageBuffer storage class are used to access "
4476                 "transparent buffer backed resources. Such variables must be "
4477                 "typed as OpTypeStruct, or an array of this type"));
4478 }
4479 
TEST_F(ValidateMemory,VulkanStorageBufferRuntimeArrayNotAStruct)4480 TEST_F(ValidateMemory, VulkanStorageBufferRuntimeArrayNotAStruct) {
4481   const std::string spirv = R"(
4482 OpCapability Shader
4483 OpCapability RuntimeDescriptorArrayEXT
4484 OpExtension "SPV_KHR_storage_buffer_storage_class"
4485 OpExtension "SPV_EXT_descriptor_indexing"
4486 OpMemoryModel Logical GLSL450
4487 OpEntryPoint GLCompute %main "main"
4488 OpExecutionMode %main LocalSize 1 1 1
4489 %void = OpTypeVoid
4490 %uint = OpTypeInt 32 0
4491 %array = OpTypeRuntimeArray %uint
4492 %ptr_ssbo = OpTypePointer StorageBuffer %array
4493 %var = OpVariable %ptr_ssbo StorageBuffer
4494 %void_fn = OpTypeFunction %void
4495 %main = OpFunction %void None %void_fn
4496 %entry = OpLabel
4497 OpReturn
4498 OpFunctionEnd
4499 )";
4500 
4501   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4502   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4503   EXPECT_THAT(getDiagnosticString(),
4504               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
4505   EXPECT_THAT(
4506       getDiagnosticString(),
4507       HasSubstr("From Vulkan spec:\nVariables identified with "
4508                 "the StorageBuffer storage class are used to access "
4509                 "transparent buffer backed resources. Such variables must be "
4510                 "typed as OpTypeStruct, or an array of this type"));
4511 }
4512 
TEST_F(ValidateMemory,VulkanStorageBufferArrayNotAStruct)4513 TEST_F(ValidateMemory, VulkanStorageBufferArrayNotAStruct) {
4514   const std::string spirv = R"(
4515 OpCapability Shader
4516 OpExtension "SPV_KHR_storage_buffer_storage_class"
4517 OpMemoryModel Logical GLSL450
4518 OpEntryPoint GLCompute %main "main"
4519 OpExecutionMode %main LocalSize 1 1 1
4520 %void = OpTypeVoid
4521 %uint = OpTypeInt 32 0
4522 %uint_4 = OpConstant %uint 4
4523 %array = OpTypeArray %uint %uint_4
4524 %ptr_ssbo = OpTypePointer StorageBuffer %array
4525 %var = OpVariable %ptr_ssbo StorageBuffer
4526 %void_fn = OpTypeFunction %void
4527 %main = OpFunction %void None %void_fn
4528 %entry = OpLabel
4529 OpReturn
4530 OpFunctionEnd
4531 )";
4532 
4533   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4534   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4535   EXPECT_THAT(getDiagnosticString(),
4536               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
4537   EXPECT_THAT(
4538       getDiagnosticString(),
4539       HasSubstr("From Vulkan spec:\nVariables identified with "
4540                 "the StorageBuffer storage class are used to access "
4541                 "transparent buffer backed resources. Such variables must be "
4542                 "typed as OpTypeStruct, or an array of this type"));
4543 }
4544 
TEST_F(ValidateMemory,VulkanInvariantOutputSuccess)4545 TEST_F(ValidateMemory, VulkanInvariantOutputSuccess) {
4546   const std::string spirv = R"(
4547 OpCapability Shader
4548 OpMemoryModel Logical GLSL450
4549 OpEntryPoint Vertex %main "main" %var
4550 OpDecorate %var Location 0
4551 OpDecorate %var Invariant
4552 %void = OpTypeVoid
4553 %f32 = OpTypeFloat 32
4554 %ptr_output = OpTypePointer Output %f32
4555 %var = OpVariable %ptr_output Output
4556 %void_fn = OpTypeFunction %void
4557 %main = OpFunction %void None %void_fn
4558 %entry = OpLabel
4559 OpReturn
4560 OpFunctionEnd
4561 )";
4562 
4563   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4564   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4565 }
4566 
TEST_F(ValidateMemory,VulkanInvariantInputStructSuccess)4567 TEST_F(ValidateMemory, VulkanInvariantInputStructSuccess) {
4568   const std::string spirv = R"(
4569 OpCapability Shader
4570 OpMemoryModel Logical GLSL450
4571 OpEntryPoint Fragment %main "main" %var
4572 OpExecutionMode %main OriginUpperLeft
4573 OpDecorate %var Location 0
4574 OpMemberDecorate %struct 1 Invariant
4575 %void = OpTypeVoid
4576 %f32 = OpTypeFloat 32
4577 %struct = OpTypeStruct %f32 %f32
4578 %ptr_input = OpTypePointer Input %struct
4579 %var = OpVariable %ptr_input Input
4580 %void_fn = OpTypeFunction %void
4581 %main = OpFunction %void None %void_fn
4582 %entry = OpLabel
4583 OpReturn
4584 OpFunctionEnd
4585 )";
4586 
4587   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4588   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4589 }
4590 
TEST_F(ValidateMemory,VulkanInvariantWrongStorageClass)4591 TEST_F(ValidateMemory, VulkanInvariantWrongStorageClass) {
4592   const std::string spirv = R"(
4593 OpCapability Shader
4594 OpMemoryModel Logical GLSL450
4595 OpEntryPoint Vertex %main "main"
4596 OpDecorate %var Invariant
4597 %void = OpTypeVoid
4598 %f32 = OpTypeFloat 32
4599 %ptr_private = OpTypePointer Private %f32
4600 %var = OpVariable %ptr_private Private
4601 %void_fn = OpTypeFunction %void
4602 %main = OpFunction %void None %void_fn
4603 %entry = OpLabel
4604 OpReturn
4605 OpFunctionEnd
4606 )";
4607 
4608   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4609   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4610   EXPECT_THAT(getDiagnosticString(),
4611               AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
4612   EXPECT_THAT(
4613       getDiagnosticString(),
4614       HasSubstr(
4615           "Variable decorated with Invariant must only be identified with the "
4616           "Input or Output storage class in Vulkan environment."));
4617 }
4618 
TEST_F(ValidateMemory,VulkanInvariantMemberWrongStorageClass)4619 TEST_F(ValidateMemory, VulkanInvariantMemberWrongStorageClass) {
4620   const std::string spirv = R"(
4621 OpCapability Shader
4622 OpMemoryModel Logical GLSL450
4623 OpEntryPoint Fragment %main "main"
4624 OpExecutionMode %main OriginUpperLeft
4625 OpMemberDecorate %struct 1 Invariant
4626 %void = OpTypeVoid
4627 %f32 = OpTypeFloat 32
4628 %struct = OpTypeStruct %f32 %f32
4629 %ptr_private = OpTypePointer Private %struct
4630 %var = OpVariable %ptr_private Private
4631 %void_fn = OpTypeFunction %void
4632 %main = OpFunction %void None %void_fn
4633 %entry = OpLabel
4634 OpReturn
4635 OpFunctionEnd
4636 )";
4637 
4638   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4639   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4640   EXPECT_THAT(getDiagnosticString(),
4641               AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
4642   EXPECT_THAT(getDiagnosticString(),
4643               HasSubstr("Variable struct member decorated with Invariant must "
4644                         "only be identified with the Input or Output storage "
4645                         "class in Vulkan environment."));
4646 }
4647 
TEST_F(ValidateMemory,PhysicalStorageBufferPtrEqual)4648 TEST_F(ValidateMemory, PhysicalStorageBufferPtrEqual) {
4649   const std::string spirv = R"(
4650 OpCapability Shader
4651 OpCapability Int64
4652 OpCapability PhysicalStorageBufferAddresses
4653 OpMemoryModel PhysicalStorageBuffer64 GLSL450
4654 OpEntryPoint GLCompute %main "main"
4655 OpExecutionMode %main LocalSize 1 1 1
4656 %void = OpTypeVoid
4657 %bool = OpTypeBool
4658 %long = OpTypeInt 64 0
4659 %long_0 = OpConstant %long 0
4660 %ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
4661 %void_fn = OpTypeFunction %void
4662 %main = OpFunction %void None %void_fn
4663 %entry = OpLabel
4664 %conv = OpConvertUToPtr %ptr_pssbo_long %long_0
4665 %eq = OpPtrEqual %bool %conv %conv
4666 OpReturn
4667 OpFunctionEnd
4668 )";
4669 
4670   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4671   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4672   EXPECT_THAT(
4673       getDiagnosticString(),
4674       HasSubstr(
4675           "Cannot use a pointer in the PhysicalStorageBuffer storage class"));
4676 }
4677 
TEST_F(ValidateMemory,PhysicalStorageBufferPtrNotEqual)4678 TEST_F(ValidateMemory, PhysicalStorageBufferPtrNotEqual) {
4679   const std::string spirv = R"(
4680 OpCapability Shader
4681 OpCapability Int64
4682 OpCapability PhysicalStorageBufferAddresses
4683 OpMemoryModel PhysicalStorageBuffer64 GLSL450
4684 OpEntryPoint GLCompute %main "main"
4685 OpExecutionMode %main LocalSize 1 1 1
4686 %void = OpTypeVoid
4687 %bool = OpTypeBool
4688 %long = OpTypeInt 64 0
4689 %long_0 = OpConstant %long 0
4690 %ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
4691 %void_fn = OpTypeFunction %void
4692 %main = OpFunction %void None %void_fn
4693 %entry = OpLabel
4694 %conv = OpConvertUToPtr %ptr_pssbo_long %long_0
4695 %neq = OpPtrNotEqual %bool %conv %conv
4696 OpReturn
4697 OpFunctionEnd
4698 )";
4699 
4700   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4701   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4702   EXPECT_THAT(
4703       getDiagnosticString(),
4704       HasSubstr(
4705           "Cannot use a pointer in the PhysicalStorageBuffer storage class"));
4706 }
4707 
TEST_F(ValidateMemory,PhysicalStorageBufferPtrDiff)4708 TEST_F(ValidateMemory, PhysicalStorageBufferPtrDiff) {
4709   const std::string spirv = R"(
4710 OpCapability Shader
4711 OpCapability Int64
4712 OpCapability PhysicalStorageBufferAddresses
4713 OpCapability VariablePointers
4714 OpMemoryModel PhysicalStorageBuffer64 GLSL450
4715 OpEntryPoint GLCompute %main "main"
4716 OpExecutionMode %main LocalSize 1 1 1
4717 %void = OpTypeVoid
4718 %long = OpTypeInt 64 0
4719 %long_0 = OpConstant %long 0
4720 %ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
4721 %void_fn = OpTypeFunction %void
4722 %main = OpFunction %void None %void_fn
4723 %entry = OpLabel
4724 %conv = OpConvertUToPtr %ptr_pssbo_long %long_0
4725 %diff = OpPtrDiff %long %conv %conv
4726 OpReturn
4727 OpFunctionEnd
4728 )";
4729 
4730   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4731   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4732   EXPECT_THAT(
4733       getDiagnosticString(),
4734       HasSubstr(
4735           "Cannot use a pointer in the PhysicalStorageBuffer storage class"));
4736 }
4737 
TEST_F(ValidateMemory,VulkanInitializerWithWorkgroupStorageClassBad)4738 TEST_F(ValidateMemory, VulkanInitializerWithWorkgroupStorageClassBad) {
4739   std::string spirv = R"(
4740 OpCapability Shader
4741 OpCapability VulkanMemoryModelKHR
4742 OpExtension "SPV_KHR_vulkan_memory_model"
4743 OpMemoryModel Logical VulkanKHR
4744 OpEntryPoint Fragment %func "func"
4745 OpExecutionMode %func OriginUpperLeft
4746 %float = OpTypeFloat 32
4747 %float_ptr = OpTypePointer Workgroup %float
4748 %init_val = OpConstant %float 1.0
4749 %1 = OpVariable %float_ptr Workgroup %init_val
4750 %void = OpTypeVoid
4751 %functy = OpTypeFunction %void
4752 %func = OpFunction %void None %functy
4753 %2 = OpLabel
4754 OpReturn
4755 OpFunctionEnd
4756 )";
4757   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
4758   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4759   EXPECT_THAT(getDiagnosticString(),
4760               AnyVUID(" VUID-StandaloneSpirv-OpVariable-04734"));
4761   EXPECT_THAT(getDiagnosticString(),
4762               HasSubstr("OpVariable, <id> '5[%5]', initializers are limited to "
4763                         "OpConstantNull in Workgroup storage class"));
4764 }
4765 
TEST_F(ValidateMemory,VulkanInitializerWithWorkgroupStorageClassGood)4766 TEST_F(ValidateMemory, VulkanInitializerWithWorkgroupStorageClassGood) {
4767   std::string spirv = R"(
4768 OpCapability Shader
4769 OpCapability VulkanMemoryModelKHR
4770 OpExtension "SPV_KHR_vulkan_memory_model"
4771 OpMemoryModel Logical VulkanKHR
4772 OpEntryPoint Fragment %func "func"
4773 OpExecutionMode %func OriginUpperLeft
4774 %float = OpTypeFloat 32
4775 %float_ptr = OpTypePointer Workgroup %float
4776 %init_val = OpConstantNull %float
4777 %1 = OpVariable %float_ptr Workgroup %init_val
4778 %void = OpTypeVoid
4779 %functy = OpTypeFunction %void
4780 %func = OpFunction %void None %functy
4781 %2 = OpLabel
4782 OpReturn
4783 OpFunctionEnd
4784 )";
4785   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
4786   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4787 }
4788 
TEST_F(ValidateMemory,LoadRuntimeArray)4789 TEST_F(ValidateMemory, LoadRuntimeArray) {
4790   const std::string spirv = R"(
4791 OpCapability Shader
4792 OpExtension "SPV_KHR_storage_buffer_storage_class"
4793 OpMemoryModel Logical GLSL450
4794 OpEntryPoint GLCompute %main "main"
4795 %void = OpTypeVoid
4796 %int = OpTypeInt 32 0
4797 %int_0 = OpConstant %int 0
4798 %rta = OpTypeRuntimeArray %int
4799 %block = OpTypeStruct %rta
4800 %ptr_rta = OpTypePointer StorageBuffer %rta
4801 %ptr_block = OpTypePointer StorageBuffer %block
4802 %var = OpVariable %ptr_block StorageBuffer
4803 %void_fn = OpTypeFunction %void
4804 %main = OpFunction %void None %void_fn
4805 %entry = OpLabel
4806 %gep = OpAccessChain %ptr_rta %var %int_0
4807 %ld = OpLoad %rta %gep
4808 OpReturn
4809 OpFunctionEnd
4810 )";
4811 
4812   CompileSuccessfully(spirv);
4813   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4814   EXPECT_THAT(getDiagnosticString(),
4815               HasSubstr("Cannot load a runtime-sized array"));
4816 }
4817 
TEST_F(ValidateMemory,LoadRuntimeArrayInStruct)4818 TEST_F(ValidateMemory, LoadRuntimeArrayInStruct) {
4819   const std::string spirv = R"(
4820 OpCapability Shader
4821 OpExtension "SPV_KHR_storage_buffer_storage_class"
4822 OpMemoryModel Logical GLSL450
4823 OpEntryPoint GLCompute %main "main"
4824 %void = OpTypeVoid
4825 %int = OpTypeInt 32 0
4826 %int_0 = OpConstant %int 0
4827 %rta = OpTypeRuntimeArray %int
4828 %block = OpTypeStruct %rta
4829 %ptr_rta = OpTypePointer StorageBuffer %rta
4830 %ptr_block = OpTypePointer StorageBuffer %block
4831 %var = OpVariable %ptr_block StorageBuffer
4832 %void_fn = OpTypeFunction %void
4833 %main = OpFunction %void None %void_fn
4834 %entry = OpLabel
4835 %ld = OpLoad %block %var
4836 OpReturn
4837 OpFunctionEnd
4838 )";
4839 
4840   CompileSuccessfully(spirv);
4841   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4842   EXPECT_THAT(getDiagnosticString(),
4843               HasSubstr("Cannot load a runtime-sized array"));
4844 }
4845 
TEST_F(ValidateMemory,LoadRuntimeArrayInArray)4846 TEST_F(ValidateMemory, LoadRuntimeArrayInArray) {
4847   const std::string spirv = R"(
4848 OpCapability Shader
4849 OpExtension "SPV_KHR_storage_buffer_storage_class"
4850 OpMemoryModel Logical GLSL450
4851 OpEntryPoint GLCompute %main "main"
4852 %void = OpTypeVoid
4853 %int = OpTypeInt 32 0
4854 %int_0 = OpConstant %int 0
4855 %int_4 = OpConstant %int 4
4856 %rta = OpTypeRuntimeArray %int
4857 %block = OpTypeStruct %rta
4858 %array = OpTypeArray %block %int_4
4859 %ptr_rta = OpTypePointer StorageBuffer %rta
4860 %ptr_block = OpTypePointer StorageBuffer %block
4861 %ptr_array = OpTypePointer StorageBuffer %array
4862 %var = OpVariable %ptr_array StorageBuffer
4863 %void_fn = OpTypeFunction %void
4864 %main = OpFunction %void None %void_fn
4865 %entry = OpLabel
4866 %ld = OpLoad %array %var
4867 OpReturn
4868 OpFunctionEnd
4869 )";
4870 
4871   CompileSuccessfully(spirv);
4872   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4873   EXPECT_THAT(getDiagnosticString(),
4874               HasSubstr("Cannot load a runtime-sized array"));
4875 }
4876 
TEST_F(ValidateMemory,Pre1p4WorkgroupMemoryBadLayoutOk)4877 TEST_F(ValidateMemory, Pre1p4WorkgroupMemoryBadLayoutOk) {
4878   const std::string spirv = R"(
4879 OpCapability Shader
4880 OpMemoryModel Logical GLSL450
4881 OpEntryPoint GLCompute %main "main"
4882 OpDecorate %struct Block
4883 OpMemberDecorate %struct 0 Offset 0
4884 %void = OpTypeVoid
4885 %bool = OpTypeBool
4886 %struct = OpTypeStruct %bool
4887 %ptr = OpTypePointer Workgroup %struct
4888 %var = OpVariable %ptr Workgroup
4889 %void_fn = OpTypeFunction %void
4890 %main = OpFunction %void None %void_fn
4891 %entry = OpLabel
4892 OpReturn
4893 OpFunctionEnd
4894 )";
4895 
4896   CompileSuccessfully(spirv);
4897   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4898 }
4899 
TEST_F(ValidateMemory,PtrAccessChainArrayStrideBad)4900 TEST_F(ValidateMemory, PtrAccessChainArrayStrideBad) {
4901   const std::string spirv = R"(
4902                OpCapability Shader
4903                OpCapability VariablePointersStorageBuffer
4904                OpExtension "SPV_KHR_storage_buffer_storage_class"
4905                OpExtension "SPV_KHR_variable_pointers"
4906                OpMemoryModel Logical GLSL450
4907                OpEntryPoint GLCompute %main "foo" %var
4908                OpExecutionMode %main LocalSize 1 1 1
4909                OpDecorate %var DescriptorSet 0
4910                OpDecorate %var Binding 0
4911        %uint = OpTypeInt 32 0
4912      %uint_0 = OpConstant %uint 0
4913      %uint_1 = OpConstant %uint 1
4914         %ptr = OpTypePointer StorageBuffer %uint
4915        %void = OpTypeVoid
4916        %func = OpTypeFunction %void
4917         %var = OpVariable %ptr StorageBuffer
4918        %main = OpFunction %void None %func
4919       %label = OpLabel
4920      %access = OpAccessChain %ptr %var
4921  %ptr_access = OpPtrAccessChain %ptr %access %uint_1
4922                OpReturn
4923                OpFunctionEnd
4924 )";
4925 
4926   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4927   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
4928             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4929   EXPECT_THAT(getDiagnosticString(),
4930               HasSubstr("OpPtrAccessChain must have a Base whose type is "
4931                         "decorated with ArrayStride"));
4932 }
4933 
TEST_F(ValidateMemory,PtrAccessChainArrayStrideSuccess)4934 TEST_F(ValidateMemory, PtrAccessChainArrayStrideSuccess) {
4935   const std::string spirv = R"(
4936                OpCapability Shader
4937                OpCapability VariablePointersStorageBuffer
4938                OpExtension "SPV_KHR_storage_buffer_storage_class"
4939                OpExtension "SPV_KHR_variable_pointers"
4940                OpMemoryModel Logical GLSL450
4941                OpEntryPoint GLCompute %main "foo" %var
4942                OpExecutionMode %main LocalSize 1 1 1
4943                OpDecorate %var DescriptorSet 0
4944                OpDecorate %var Binding 00
4945                OpDecorate %ptr ArrayStride 4
4946        %uint = OpTypeInt 32 0
4947      %uint_0 = OpConstant %uint 0
4948      %uint_1 = OpConstant %uint 1
4949         %ptr = OpTypePointer StorageBuffer %uint
4950        %void = OpTypeVoid
4951        %func = OpTypeFunction %void
4952         %var = OpVariable %ptr StorageBuffer
4953        %main = OpFunction %void None %func
4954       %label = OpLabel
4955      %access = OpAccessChain %ptr %var
4956  %ptr_access = OpPtrAccessChain %ptr %access %uint_1
4957                OpReturn
4958                OpFunctionEnd
4959 )";
4960 
4961   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4962   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4963 }
4964 
TEST_F(ValidateMemory,VulkanPtrAccessChainStorageBufferSuccess)4965 TEST_F(ValidateMemory, VulkanPtrAccessChainStorageBufferSuccess) {
4966   const std::string spirv = R"(
4967                OpCapability Shader
4968                OpCapability VariablePointersStorageBuffer
4969                OpExtension "SPV_KHR_storage_buffer_storage_class"
4970                OpExtension "SPV_KHR_variable_pointers"
4971                OpMemoryModel Logical GLSL450
4972                OpEntryPoint GLCompute %main "foo" %var
4973                OpExecutionMode %main LocalSize 1 1 1
4974                OpDecorate %_runtimearr_uint ArrayStride 4
4975                OpMemberDecorate %_struct_10 0 Offset 0
4976                OpDecorate %_struct_10 Block
4977                OpDecorate %var DescriptorSet 0
4978                OpDecorate %var Binding 0
4979                OpDecorate %_ptr_StorageBuffer_uint ArrayStride 4
4980        %uint = OpTypeInt 32 0
4981      %uint_0 = OpConstant %uint 0
4982      %uint_1 = OpConstant %uint 1
4983 %_runtimearr_uint = OpTypeRuntimeArray %uint
4984  %_struct_10 = OpTypeStruct %_runtimearr_uint
4985 %_ptr_StorageBuffer__struct_10 = OpTypePointer StorageBuffer %_struct_10
4986 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
4987        %void = OpTypeVoid
4988       %func2 = OpTypeFunction %void %_ptr_StorageBuffer_uint
4989       %func1 = OpTypeFunction %void
4990          %var = OpVariable %_ptr_StorageBuffer__struct_10 StorageBuffer
4991      %called = OpFunction %void None %func2
4992       %param = OpFunctionParameter %_ptr_StorageBuffer_uint
4993      %label2 = OpLabel
4994  %ptr_access = OpPtrAccessChain %_ptr_StorageBuffer_uint %param %uint_1
4995                OpReturn
4996                OpFunctionEnd
4997        %main = OpFunction %void None %func1
4998      %label1 = OpLabel
4999      %access = OpAccessChain %_ptr_StorageBuffer_uint %var %uint_0 %uint_0
5000        %call = OpFunctionCall %void %called %access
5001                OpReturn
5002                OpFunctionEnd
5003 )";
5004 
5005   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5006   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
5007 }
5008 
TEST_F(ValidateMemory,VulkanPtrAccessChainStorageBufferCapability)5009 TEST_F(ValidateMemory, VulkanPtrAccessChainStorageBufferCapability) {
5010   const std::string spirv = R"(
5011                OpCapability Shader
5012                OpCapability PhysicalStorageBufferAddresses
5013                OpExtension "SPV_KHR_storage_buffer_storage_class"
5014                OpExtension "SPV_KHR_variable_pointers"
5015                OpMemoryModel PhysicalStorageBuffer64 GLSL450
5016                OpEntryPoint GLCompute %main "foo" %var
5017                OpExecutionMode %main LocalSize 1 1 1
5018                OpDecorate %_runtimearr_uint ArrayStride 4
5019                OpMemberDecorate %_struct_10 0 Offset 0
5020                OpDecorate %_struct_10 Block
5021                OpDecorate %var DescriptorSet 0
5022                OpDecorate %var Binding 0
5023                OpDecorate %_ptr_StorageBuffer_uint ArrayStride 4
5024        %uint = OpTypeInt 32 0
5025      %uint_0 = OpConstant %uint 0
5026      %uint_1 = OpConstant %uint 1
5027 %_runtimearr_uint = OpTypeRuntimeArray %uint
5028  %_struct_10 = OpTypeStruct %_runtimearr_uint
5029 %_ptr_StorageBuffer__struct_10 = OpTypePointer StorageBuffer %_struct_10
5030 %_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint
5031        %void = OpTypeVoid
5032        %func = OpTypeFunction %void
5033          %var = OpVariable %_ptr_StorageBuffer__struct_10 StorageBuffer
5034        %main = OpFunction %void None %func
5035       %label = OpLabel
5036      %access = OpAccessChain %_ptr_StorageBuffer_uint %var %uint_0 %uint_0
5037  %ptr_access = OpPtrAccessChain %_ptr_StorageBuffer_uint %access %uint_1
5038                OpReturn
5039                OpFunctionEnd
5040 )";
5041 
5042   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5043   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
5044   EXPECT_THAT(getDiagnosticString(),
5045               AnyVUID("VUID-StandaloneSpirv-Base-07652"));
5046   EXPECT_THAT(getDiagnosticString(),
5047               HasSubstr("OpPtrAccessChain Base operand pointing to "
5048                         "StorageBuffer storage class must use VariablePointers "
5049                         "or VariablePointersStorageBuffer capability"));
5050 }
5051 
TEST_F(ValidateMemory,VulkanPtrAccessChainWorkgroupCapability)5052 TEST_F(ValidateMemory, VulkanPtrAccessChainWorkgroupCapability) {
5053   const std::string spirv = R"(
5054                OpCapability Shader
5055                OpCapability VariablePointersStorageBuffer
5056                OpExtension "SPV_KHR_storage_buffer_storage_class"
5057                OpExtension "SPV_KHR_variable_pointers"
5058                OpMemoryModel Logical GLSL450
5059                OpEntryPoint GLCompute %main "foo" %var
5060                OpExecutionMode %main LocalSize 1 1 1
5061                OpDecorate %_ptr_Workgroup_uint ArrayStride 4
5062        %uint = OpTypeInt 32 0
5063      %uint_0 = OpConstant %uint 0
5064      %uint_1 = OpConstant %uint 1
5065 %_arr_uint = OpTypeArray %uint %uint_1
5066 %_ptr_Workgroup__arr_uint = OpTypePointer Workgroup %_arr_uint
5067 %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
5068        %void = OpTypeVoid
5069        %func = OpTypeFunction %void
5070         %var = OpVariable %_ptr_Workgroup__arr_uint Workgroup
5071        %main = OpFunction %void None %func
5072       %label = OpLabel
5073      %access = OpAccessChain %_ptr_Workgroup_uint %var %uint_0
5074  %ptr_access = OpPtrAccessChain %_ptr_Workgroup_uint %access %uint_1
5075                OpReturn
5076                OpFunctionEnd
5077 )";
5078 
5079   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5080   EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_2));
5081   EXPECT_THAT(getDiagnosticString(),
5082               AnyVUID("VUID-StandaloneSpirv-Base-07651"));
5083   EXPECT_THAT(getDiagnosticString(),
5084               HasSubstr("OpPtrAccessChain Base operand pointing to Workgroup "
5085                         "storage class must use VariablePointers capability"));
5086 }
5087 
TEST_F(ValidateMemory,VulkanPtrAccessChainWorkgroupNoArrayStrideSuccess)5088 TEST_F(ValidateMemory, VulkanPtrAccessChainWorkgroupNoArrayStrideSuccess) {
5089   const std::string spirv = R"(
5090                OpCapability Shader
5091                OpCapability VariablePointers
5092                OpExtension "SPV_KHR_storage_buffer_storage_class"
5093                OpExtension "SPV_KHR_variable_pointers"
5094                OpMemoryModel Logical GLSL450
5095                OpEntryPoint GLCompute %main "foo" %var
5096                OpExecutionMode %main LocalSize 1 1 1
5097        %uint = OpTypeInt 32 0
5098      %uint_0 = OpConstant %uint 0
5099      %uint_1 = OpConstant %uint 1
5100 %_arr_uint = OpTypeArray %uint %uint_1
5101 %_ptr_Workgroup__arr_uint = OpTypePointer Workgroup %_arr_uint
5102 %_ptr_Workgroup_uint = OpTypePointer Workgroup %uint
5103        %void = OpTypeVoid
5104        %func = OpTypeFunction %void
5105         %var = OpVariable %_ptr_Workgroup__arr_uint Workgroup
5106        %main = OpFunction %void None %func
5107       %label = OpLabel
5108      %access = OpAccessChain %_ptr_Workgroup_uint %var %uint_0
5109  %ptr_access = OpPtrAccessChain %_ptr_Workgroup_uint %access %uint_1
5110                OpReturn
5111                OpFunctionEnd
5112 )";
5113 
5114   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_2);
5115   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_2));
5116 }
5117 
5118 }  // namespace
5119 }  // namespace val
5120 }  // namespace spvtools
5121