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