• 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 %uint_t = OpTypeInt 32 0
2479 %array_t = OpTypeRuntimeArray %uint_t
2480 %struct_t = OpTypeStruct %array_t
2481 %struct_ptr = OpTypePointer Workgroup %struct_t
2482 %2 = OpVariable %struct_ptr Workgroup
2483 %void = OpTypeVoid
2484 %func_t = OpTypeFunction %void
2485 %func = OpFunction %void None %func_t
2486 %1 = OpLabel
2487 OpReturn
2488 OpFunctionEnd
2489 )";
2490 
2491   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2492   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2493   EXPECT_THAT(getDiagnosticString(),
2494               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2495   EXPECT_THAT(
2496       getDiagnosticString(),
2497       HasSubstr(
2498           "For Vulkan, OpTypeStruct variables containing OpTypeRuntimeArray "
2499           "must have storage class of StorageBuffer, PhysicalStorageBuffer, or "
2500           "Uniform.\n  %6 = "
2501           "OpVariable %_ptr_Workgroup__struct_4 Workgroup\n"));
2502 }
2503 
TEST_F(ValidateMemory,VulkanRTAInsideStorageBufferStructWithoutBlockBad)2504 TEST_F(ValidateMemory, VulkanRTAInsideStorageBufferStructWithoutBlockBad) {
2505   std::string spirv = R"(
2506 OpCapability Shader
2507 OpMemoryModel Logical GLSL450
2508 OpEntryPoint Fragment %func "func"
2509 OpExecutionMode %func OriginUpperLeft
2510 %uint_t = OpTypeInt 32 0
2511 %array_t = OpTypeRuntimeArray %uint_t
2512 %struct_t = OpTypeStruct %array_t
2513 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2514 %2 = OpVariable %struct_ptr StorageBuffer
2515 %void = OpTypeVoid
2516 %func_t = OpTypeFunction %void
2517 %func = OpFunction %void None %func_t
2518 %1 = OpLabel
2519 OpReturn
2520 OpFunctionEnd
2521 )";
2522 
2523   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2524   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2525   EXPECT_THAT(getDiagnosticString(),
2526               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2527   EXPECT_THAT(getDiagnosticString(),
2528               HasSubstr("For Vulkan, an OpTypeStruct variable containing an "
2529                         "OpTypeRuntimeArray must be decorated with Block if it "
2530                         "has storage class StorageBuffer or "
2531                         "PhysicalStorageBuffer.\n  %6 = OpVariable "
2532                         "%_ptr_StorageBuffer__struct_4 StorageBuffer\n"));
2533 }
2534 
TEST_F(ValidateMemory,VulkanRTAInsideUniformStructGood)2535 TEST_F(ValidateMemory, VulkanRTAInsideUniformStructGood) {
2536   std::string spirv = R"(
2537 OpCapability Shader
2538 OpMemoryModel Logical GLSL450
2539 OpEntryPoint Fragment %func "func"
2540 OpExecutionMode %func OriginUpperLeft
2541 OpDecorate %array_t ArrayStride 4
2542 OpMemberDecorate %struct_t 0 Offset 0
2543 OpDecorate %struct_t BufferBlock
2544 %uint_t = OpTypeInt 32 0
2545 %array_t = OpTypeRuntimeArray %uint_t
2546 %struct_t = OpTypeStruct %array_t
2547 %struct_ptr = OpTypePointer Uniform %struct_t
2548 %2 = OpVariable %struct_ptr Uniform
2549 %void = OpTypeVoid
2550 %func_t = OpTypeFunction %void
2551 %func = OpFunction %void None %func_t
2552 %1 = OpLabel
2553 OpReturn
2554 OpFunctionEnd
2555 )";
2556 
2557   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2558   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2559 }
2560 
TEST_F(ValidateMemory,VulkanRTAInsideUniformStructWithoutBufferBlockBad)2561 TEST_F(ValidateMemory, VulkanRTAInsideUniformStructWithoutBufferBlockBad) {
2562   std::string spirv = R"(
2563 OpCapability Shader
2564 OpMemoryModel Logical GLSL450
2565 OpEntryPoint Fragment %func "func"
2566 OpExecutionMode %func OriginUpperLeft
2567 %uint_t = OpTypeInt 32 0
2568 %array_t = OpTypeRuntimeArray %uint_t
2569 %struct_t = OpTypeStruct %array_t
2570 %struct_ptr = OpTypePointer Uniform %struct_t
2571 %2 = OpVariable %struct_ptr Uniform
2572 %void = OpTypeVoid
2573 %func_t = OpTypeFunction %void
2574 %func = OpFunction %void None %func_t
2575 %1 = OpLabel
2576 OpReturn
2577 OpFunctionEnd
2578 )";
2579 
2580   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2581   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2582   EXPECT_THAT(getDiagnosticString(),
2583               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2584   EXPECT_THAT(getDiagnosticString(),
2585               HasSubstr("For Vulkan, an OpTypeStruct variable containing an "
2586                         "OpTypeRuntimeArray must be decorated with BufferBlock "
2587                         "if it has storage class Uniform.\n  %6 = OpVariable "
2588                         "%_ptr_Uniform__struct_4 Uniform\n"));
2589 }
2590 
TEST_F(ValidateMemory,VulkanRTAInsideRTABad)2591 TEST_F(ValidateMemory, VulkanRTAInsideRTABad) {
2592   std::string spirv = R"(
2593 OpCapability Shader
2594 OpMemoryModel Logical GLSL450
2595 OpEntryPoint Fragment %func "func"
2596 OpExecutionMode %func OriginUpperLeft
2597 %sampler_t = OpTypeSampler
2598 %inner_array_t = OpTypeRuntimeArray %sampler_t
2599 %array_t = OpTypeRuntimeArray %inner_array_t
2600 %array_ptr = OpTypePointer UniformConstant %array_t
2601 %2 = OpVariable %array_ptr UniformConstant
2602 %void = OpTypeVoid
2603 %func_t = OpTypeFunction %void
2604 %func = OpFunction %void None %func_t
2605 %1 = OpLabel
2606 OpReturn
2607 OpFunctionEnd
2608 )";
2609 
2610   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2611   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2612   EXPECT_THAT(getDiagnosticString(),
2613               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2614   EXPECT_THAT(
2615       getDiagnosticString(),
2616       HasSubstr(
2617           "OpTypeRuntimeArray Element Type <id> '3[%_runtimearr_2]' is not "
2618           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_2 = "
2619           "OpTypeRuntimeArray %_runtimearr_2\n"));
2620 }
2621 
TEST_F(ValidateMemory,VulkanRTAInsideRTAWithRuntimeDescriptorArrayBad)2622 TEST_F(ValidateMemory, VulkanRTAInsideRTAWithRuntimeDescriptorArrayBad) {
2623   std::string spirv = R"(
2624 OpCapability RuntimeDescriptorArrayEXT
2625 OpCapability Shader
2626 OpExtension "SPV_EXT_descriptor_indexing"
2627 OpMemoryModel Logical GLSL450
2628 OpEntryPoint Fragment %func "func"
2629 OpExecutionMode %func OriginUpperLeft
2630 OpDecorate %struct Block
2631 %uint_t = OpTypeInt 32 0
2632 %inner_array_t = OpTypeRuntimeArray %uint_t
2633 %array_t = OpTypeRuntimeArray %inner_array_t
2634 %struct = OpTypeStruct %array_t
2635 %array_ptr = OpTypePointer StorageBuffer %struct
2636 %2 = OpVariable %array_ptr StorageBuffer
2637 %void = OpTypeVoid
2638 %func_t = OpTypeFunction %void
2639 %func = OpFunction %void None %func_t
2640 %1 = OpLabel
2641 OpReturn
2642 OpFunctionEnd
2643 )";
2644 
2645   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2646   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2647   EXPECT_THAT(getDiagnosticString(),
2648               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2649   EXPECT_THAT(
2650       getDiagnosticString(),
2651       HasSubstr(
2652           "OpTypeRuntimeArray Element Type <id> '4[%_runtimearr_uint]' is not "
2653           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
2654           "OpTypeRuntimeArray %_runtimearr_uint\n"));
2655 }
2656 
TEST_F(ValidateMemory,VulkanUniformStructInsideRTAWithRuntimeDescriptorArrayGood)2657 TEST_F(ValidateMemory,
2658        VulkanUniformStructInsideRTAWithRuntimeDescriptorArrayGood) {
2659   std::string spirv = R"(
2660 OpCapability RuntimeDescriptorArrayEXT
2661 OpCapability Shader
2662 OpExtension "SPV_EXT_descriptor_indexing"
2663 OpMemoryModel Logical GLSL450
2664 OpEntryPoint Fragment %func "func"
2665 OpExecutionMode %func OriginUpperLeft
2666 OpDecorate %array_t ArrayStride 4
2667 OpMemberDecorate %struct_t 0 Offset 0
2668 OpDecorate %struct_t Block
2669 %uint_t = OpTypeInt 32 0
2670 %struct_t = OpTypeStruct %uint_t
2671 %array_t = OpTypeRuntimeArray %struct_t
2672 %array_ptr = OpTypePointer Uniform %array_t
2673 %2 = OpVariable %array_ptr Uniform
2674 %void = OpTypeVoid
2675 %func_t = OpTypeFunction %void
2676 %func = OpFunction %void None %func_t
2677 %1 = OpLabel
2678 OpReturn
2679 OpFunctionEnd
2680 )";
2681 
2682   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2683   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2684 }
2685 
TEST_F(ValidateMemory,VulkanRTAInsideRTAInsideStructBad)2686 TEST_F(ValidateMemory, VulkanRTAInsideRTAInsideStructBad) {
2687   std::string spirv = R"(
2688 OpCapability Shader
2689 OpMemoryModel Logical GLSL450
2690 OpEntryPoint Fragment %func "func"
2691 OpExecutionMode %func OriginUpperLeft
2692 OpDecorate %array_t ArrayStride 4
2693 OpMemberDecorate %struct_t 0 Offset 0
2694 OpDecorate %struct_t Block
2695 %uint_t = OpTypeInt 32 0
2696 %inner_array_t = OpTypeRuntimeArray %uint_t
2697 %array_t = OpTypeRuntimeArray %inner_array_t
2698 %struct_t = OpTypeStruct %array_t
2699 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2700 %2 = OpVariable %struct_ptr StorageBuffer
2701 %void = OpTypeVoid
2702 %func_t = OpTypeFunction %void
2703 %func = OpFunction %void None %func_t
2704 %1 = OpLabel
2705 OpReturn
2706 OpFunctionEnd
2707 )";
2708 
2709   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2710   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2711   EXPECT_THAT(getDiagnosticString(),
2712               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2713   EXPECT_THAT(
2714       getDiagnosticString(),
2715       HasSubstr(
2716           "OpTypeRuntimeArray Element Type <id> '5[%_runtimearr_uint]' is not "
2717           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
2718           "OpTypeRuntimeArray %_runtimearr_uint\n"));
2719 }
2720 
TEST_F(ValidateMemory,VulkanRTAInsideRTAInsideStructWithRuntimeDescriptorArrayBad)2721 TEST_F(ValidateMemory,
2722        VulkanRTAInsideRTAInsideStructWithRuntimeDescriptorArrayBad) {
2723   std::string spirv = R"(
2724 OpCapability RuntimeDescriptorArrayEXT
2725 OpCapability Shader
2726 OpExtension "SPV_EXT_descriptor_indexing"
2727 OpMemoryModel Logical GLSL450
2728 OpEntryPoint Fragment %func "func"
2729 OpExecutionMode %func OriginUpperLeft
2730 OpDecorate %array_t ArrayStride 4
2731 OpMemberDecorate %struct_t 0 Offset 0
2732 OpDecorate %struct_t Block
2733 %uint_t = OpTypeInt 32 0
2734 %inner_array_t = OpTypeRuntimeArray %uint_t
2735 %array_t = OpTypeRuntimeArray %inner_array_t
2736 %struct_t = OpTypeStruct %array_t
2737 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2738 %2 = OpVariable %struct_ptr StorageBuffer
2739 %void = OpTypeVoid
2740 %func_t = OpTypeFunction %void
2741 %func = OpFunction %void None %func_t
2742 %1 = OpLabel
2743 OpReturn
2744 OpFunctionEnd
2745 )";
2746 
2747   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2748   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2749   EXPECT_THAT(getDiagnosticString(),
2750               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2751   EXPECT_THAT(
2752       getDiagnosticString(),
2753       HasSubstr(
2754           "OpTypeRuntimeArray Element Type <id> '5[%_runtimearr_uint]' is not "
2755           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
2756           "OpTypeRuntimeArray %_runtimearr_uint\n"));
2757 }
2758 
TEST_F(ValidateMemory,VulkanRTAInsideArrayBad)2759 TEST_F(ValidateMemory, VulkanRTAInsideArrayBad) {
2760   std::string spirv = R"(
2761 OpCapability Shader
2762 OpMemoryModel Logical GLSL450
2763 OpEntryPoint Fragment %func "func"
2764 OpExecutionMode %func OriginUpperLeft
2765 %uint_t = OpTypeInt 32 0
2766 %dim = OpConstant %uint_t 1
2767 %sampler_t = OpTypeSampler
2768 %inner_array_t = OpTypeRuntimeArray %sampler_t
2769 %array_t = OpTypeArray %inner_array_t %dim
2770 %array_ptr = OpTypePointer UniformConstant %array_t
2771 %2 = OpVariable %array_ptr UniformConstant
2772 %void = OpTypeVoid
2773 %func_t = OpTypeFunction %void
2774 %func = OpFunction %void None %func_t
2775 %1 = OpLabel
2776 OpReturn
2777 OpFunctionEnd
2778 )";
2779 
2780   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2781   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2782   EXPECT_THAT(getDiagnosticString(),
2783               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2784   EXPECT_THAT(
2785       getDiagnosticString(),
2786       HasSubstr("OpTypeArray Element Type <id> '5[%_runtimearr_4]' is not "
2787                 "valid in Vulkan environments.\n  %_arr__runtimearr_4_uint_1 = "
2788                 "OpTypeArray %_runtimearr_4 %uint_1\n"));
2789 }
2790 
TEST_F(ValidateMemory,VulkanRTAInsideArrayWithRuntimeDescriptorArrayBad)2791 TEST_F(ValidateMemory, VulkanRTAInsideArrayWithRuntimeDescriptorArrayBad) {
2792   std::string spirv = R"(
2793 OpCapability RuntimeDescriptorArrayEXT
2794 OpCapability Shader
2795 OpExtension "SPV_EXT_descriptor_indexing"
2796 OpMemoryModel Logical GLSL450
2797 OpEntryPoint Fragment %func "func"
2798 OpExecutionMode %func OriginUpperLeft
2799 OpDecorate %struct Block
2800 %uint_t = OpTypeInt 32 0
2801 %dim = OpConstant %uint_t 1
2802 %sampler_t = OpTypeSampler
2803 %inner_array_t = OpTypeRuntimeArray %uint_t
2804 %array_t = OpTypeRuntimeArray %inner_array_t
2805 %struct = OpTypeStruct %array_t
2806 %array_ptr = OpTypePointer StorageBuffer %struct
2807 %2 = OpVariable %array_ptr StorageBuffer
2808 %void = OpTypeVoid
2809 %func_t = OpTypeFunction %void
2810 %func = OpFunction %void None %func_t
2811 %1 = OpLabel
2812 OpReturn
2813 OpFunctionEnd
2814 )";
2815 
2816   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2817   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2818   EXPECT_THAT(getDiagnosticString(),
2819               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2820   EXPECT_THAT(
2821       getDiagnosticString(),
2822       HasSubstr(
2823           "OpTypeRuntimeArray Element Type <id> '6[%_runtimearr_uint]' is not "
2824           "valid in Vulkan environments.\n  %_runtimearr__runtimearr_uint = "
2825           "OpTypeRuntimeArray %_runtimearr_uint\n"));
2826 }
2827 
TEST_F(ValidateMemory,VulkanRTAInsideArrayInsideStructBad)2828 TEST_F(ValidateMemory, VulkanRTAInsideArrayInsideStructBad) {
2829   std::string spirv = R"(
2830 OpCapability Shader
2831 OpMemoryModel Logical GLSL450
2832 OpEntryPoint Fragment %func "func"
2833 OpExecutionMode %func OriginUpperLeft
2834 OpDecorate %array_t ArrayStride 4
2835 OpMemberDecorate %struct_t 0 Offset 0
2836 OpDecorate %struct_t Block
2837 %uint_t = OpTypeInt 32 0
2838 %dim = OpConstant %uint_t 1
2839 %inner_array_t = OpTypeRuntimeArray %uint_t
2840 %array_t = OpTypeArray %inner_array_t %dim
2841 %struct_t = OpTypeStruct %array_t
2842 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2843 %2 = OpVariable %struct_ptr StorageBuffer
2844 %void = OpTypeVoid
2845 %func_t = OpTypeFunction %void
2846 %func = OpFunction %void None %func_t
2847 %1 = OpLabel
2848 OpReturn
2849 OpFunctionEnd
2850 )";
2851 
2852   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2853   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2854   EXPECT_THAT(getDiagnosticString(),
2855               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2856   EXPECT_THAT(
2857       getDiagnosticString(),
2858       HasSubstr(
2859           "OpTypeArray Element Type <id> '6[%_runtimearr_uint]' is not "
2860           "valid in Vulkan environments.\n  %_arr__runtimearr_uint_uint_1 "
2861           "= OpTypeArray %_runtimearr_uint %uint_1\n"));
2862 }
2863 
TEST_F(ValidateMemory,VulkanRTAInsideArrayInsideStructWithRuntimeDescriptorArrayBad)2864 TEST_F(ValidateMemory,
2865        VulkanRTAInsideArrayInsideStructWithRuntimeDescriptorArrayBad) {
2866   std::string spirv = R"(
2867 OpCapability RuntimeDescriptorArrayEXT
2868 OpCapability Shader
2869 OpExtension "SPV_EXT_descriptor_indexing"
2870 OpMemoryModel Logical GLSL450
2871 OpEntryPoint Fragment %func "func"
2872 OpExecutionMode %func OriginUpperLeft
2873 OpDecorate %array_t ArrayStride 4
2874 OpMemberDecorate %struct_t 0 Offset 0
2875 OpDecorate %struct_t Block
2876 %uint_t = OpTypeInt 32 0
2877 %dim = OpConstant %uint_t 1
2878 %inner_array_t = OpTypeRuntimeArray %uint_t
2879 %array_t = OpTypeArray %inner_array_t %dim
2880 %struct_t = OpTypeStruct %array_t
2881 %struct_ptr = OpTypePointer StorageBuffer %struct_t
2882 %2 = OpVariable %struct_ptr StorageBuffer
2883 %void = OpTypeVoid
2884 %func_t = OpTypeFunction %void
2885 %func = OpFunction %void None %func_t
2886 %1 = OpLabel
2887 OpReturn
2888 OpFunctionEnd
2889 )";
2890 
2891   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2892   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2893   EXPECT_THAT(getDiagnosticString(),
2894               AnyVUID("VUID-StandaloneSpirv-OpTypeRuntimeArray-04680"));
2895   EXPECT_THAT(
2896       getDiagnosticString(),
2897       HasSubstr(
2898           "OpTypeArray Element Type <id> '6[%_runtimearr_uint]' is not "
2899           "valid in Vulkan environments.\n  %_arr__runtimearr_uint_uint_1 "
2900           "= OpTypeArray %_runtimearr_uint %uint_1\n"));
2901 }
2902 
TEST_F(ValidateMemory,VulkanRTAStructInsideRTAWithRuntimeDescriptorArrayGood)2903 TEST_F(ValidateMemory, VulkanRTAStructInsideRTAWithRuntimeDescriptorArrayGood) {
2904   std::string spirv = R"(
2905 OpCapability RuntimeDescriptorArrayEXT
2906 OpCapability Shader
2907 OpExtension "SPV_EXT_descriptor_indexing"
2908 OpMemoryModel Logical GLSL450
2909 OpEntryPoint Fragment %func "func"
2910 OpExecutionMode %func OriginUpperLeft
2911 OpDecorate %inner_array_t ArrayStride 4
2912 OpDecorate %array_t ArrayStride 4
2913 OpMemberDecorate %struct_t 0 Offset 0
2914 OpDecorate %struct_t Block
2915 %uint_t = OpTypeInt 32 0
2916 %inner_array_t = OpTypeRuntimeArray %uint_t
2917 %struct_t = OpTypeStruct %inner_array_t
2918 %array_t = OpTypeRuntimeArray %struct_t
2919 %array_ptr = OpTypePointer StorageBuffer %array_t
2920 %2 = OpVariable %array_ptr StorageBuffer
2921 %void = OpTypeVoid
2922 %func_t = OpTypeFunction %void
2923 %func = OpFunction %void None %func_t
2924 %1 = OpLabel
2925 OpReturn
2926 OpFunctionEnd
2927 )";
2928 
2929   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2930   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2931 }
2932 
TEST_F(ValidateMemory,VulkanRTAStructInsideArrayGood)2933 TEST_F(ValidateMemory, VulkanRTAStructInsideArrayGood) {
2934   std::string spirv = R"(
2935 OpCapability RuntimeDescriptorArrayEXT
2936 OpCapability Shader
2937 OpExtension "SPV_EXT_descriptor_indexing"
2938 OpMemoryModel Logical GLSL450
2939 OpEntryPoint Fragment %func "func"
2940 OpExecutionMode %func OriginUpperLeft
2941 OpDecorate %inner_array_t ArrayStride 4
2942 OpDecorate %array_t ArrayStride 4
2943 OpMemberDecorate %struct_t 0 Offset 0
2944 OpDecorate %struct_t Block
2945 %uint_t = OpTypeInt 32 0
2946 %inner_array_t = OpTypeRuntimeArray %uint_t
2947 %struct_t = OpTypeStruct %inner_array_t
2948 %array_size = OpConstant %uint_t 5
2949 %array_t = OpTypeArray %struct_t %array_size
2950 %array_ptr = OpTypePointer StorageBuffer %array_t
2951 %2 = OpVariable %array_ptr StorageBuffer
2952 %void = OpTypeVoid
2953 %func_t = OpTypeFunction %void
2954 %func = OpFunction %void None %func_t
2955 %1 = OpLabel
2956 OpReturn
2957 OpFunctionEnd
2958 )";
2959 
2960   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1);
2961   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
2962 }
2963 
TEST_F(ValidateMemory,CopyMemoryNoAccessGood)2964 TEST_F(ValidateMemory, CopyMemoryNoAccessGood) {
2965   const std::string spirv = R"(
2966 OpCapability Shader
2967 OpCapability Linkage
2968 OpMemoryModel Logical GLSL450
2969 %void = OpTypeVoid
2970 %int = OpTypeInt 32 0
2971 %int_ptr_priv = OpTypePointer Private %int
2972 %var1 = OpVariable %int_ptr_priv Private
2973 %var2 = OpVariable %int_ptr_priv Private
2974 %voidfn = OpTypeFunction %void
2975 %func = OpFunction %void None %voidfn
2976 %entry = OpLabel
2977 OpCopyMemory %var1 %var2
2978 OpReturn
2979 OpFunctionEnd
2980 )";
2981 
2982   CompileSuccessfully(spirv);
2983   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2984   EXPECT_THAT(getDiagnosticString(), Eq(""));
2985 }
2986 
TEST_F(ValidateMemory,CopyMemorySimpleMixedAccessGood)2987 TEST_F(ValidateMemory, CopyMemorySimpleMixedAccessGood) {
2988   // Test one memory access operand using features that don't require the
2989   // Vulkan memory model.
2990   const std::string spirv = R"(
2991 OpCapability Shader
2992 OpCapability Linkage
2993 OpMemoryModel Logical GLSL450
2994 %void = OpTypeVoid
2995 %int = OpTypeInt 32 0
2996 %int_ptr_priv = OpTypePointer Private %int
2997 %var1 = OpVariable %int_ptr_priv Private
2998 %var2 = OpVariable %int_ptr_priv Private
2999 %voidfn = OpTypeFunction %void
3000 %func = OpFunction %void None %voidfn
3001 %entry = OpLabel
3002 OpCopyMemory %var1 %var2 Volatile|Aligned|Nontemporal 4
3003 OpReturn
3004 OpFunctionEnd
3005 )";
3006 
3007   CompileSuccessfully(spirv);
3008   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3009   EXPECT_THAT(getDiagnosticString(), Eq(""));
3010 }
3011 
TEST_F(ValidateMemory,CopyMemorySimpleTwoMixedAccessV13Bad)3012 TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV13Bad) {
3013   // Two memory access operands is invalid up to SPIR-V 1.3
3014   const std::string spirv = R"(
3015 OpCapability Shader
3016 OpCapability Linkage
3017 OpMemoryModel Logical GLSL450
3018 %void = OpTypeVoid
3019 %int = OpTypeInt 32 0
3020 %int_ptr_priv = OpTypePointer Private %int
3021 %var1 = OpVariable %int_ptr_priv Private
3022 %var2 = OpVariable %int_ptr_priv Private
3023 %voidfn = OpTypeFunction %void
3024 %func = OpFunction %void None %voidfn
3025 %entry = OpLabel
3026 OpCopyMemory %var1 %var2 Volatile Volatile
3027 OpReturn
3028 OpFunctionEnd
3029 )";
3030 
3031   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
3032   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
3033             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3034   EXPECT_THAT(getDiagnosticString(),
3035               HasSubstr("CopyMemory with two memory access operands requires "
3036                         "SPIR-V 1.4 or later"));
3037 }
3038 
TEST_F(ValidateMemory,CopyMemorySimpleTwoMixedAccessV14Good)3039 TEST_F(ValidateMemory, CopyMemorySimpleTwoMixedAccessV14Good) {
3040   // Two memory access operands is valid in SPIR-V 1.4
3041   const std::string spirv = R"(
3042 OpCapability Shader
3043 OpCapability Linkage
3044 OpMemoryModel Logical GLSL450
3045 %void = OpTypeVoid
3046 %int = OpTypeInt 32 0
3047 %int_ptr_priv = OpTypePointer Private %int
3048 %var1 = OpVariable %int_ptr_priv Private
3049 %var2 = OpVariable %int_ptr_priv Private
3050 %voidfn = OpTypeFunction %void
3051 %func = OpFunction %void None %voidfn
3052 %entry = OpLabel
3053 OpCopyMemory %var1 %var2 Volatile Volatile
3054 OpReturn
3055 OpFunctionEnd
3056 )";
3057 
3058   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3059   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3060   EXPECT_THAT(getDiagnosticString(), Eq(""));
3061 }
3062 
TEST_F(ValidateMemory,CopyMemorySizedNoAccessGood)3063 TEST_F(ValidateMemory, CopyMemorySizedNoAccessGood) {
3064   const std::string spirv = R"(
3065 OpCapability Shader
3066 OpCapability Linkage
3067 OpCapability Addresses
3068 OpMemoryModel Logical GLSL450
3069 %void = OpTypeVoid
3070 %int = OpTypeInt 32 0
3071 %int_16 = OpConstant %int 16
3072 %int_ptr_priv = OpTypePointer Private %int
3073 %var1 = OpVariable %int_ptr_priv Private
3074 %var2 = OpVariable %int_ptr_priv Private
3075 %voidfn = OpTypeFunction %void
3076 %func = OpFunction %void None %voidfn
3077 %entry = OpLabel
3078 OpCopyMemorySized %var1 %var2 %int_16
3079 OpReturn
3080 OpFunctionEnd
3081 )";
3082 
3083   CompileSuccessfully(spirv);
3084   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3085   EXPECT_THAT(getDiagnosticString(), Eq(""));
3086 }
3087 
TEST_F(ValidateMemory,CopyMemorySizedSimpleMixedAccessGood)3088 TEST_F(ValidateMemory, CopyMemorySizedSimpleMixedAccessGood) {
3089   // Test one memory access operand using features that don't require the
3090   // Vulkan memory model.
3091   const std::string spirv = R"(
3092 OpCapability Shader
3093 OpCapability Linkage
3094 OpCapability Addresses
3095 OpMemoryModel Logical GLSL450
3096 %void = OpTypeVoid
3097 %int = OpTypeInt 32 0
3098 %int_16 = OpConstant %int 16
3099 %int_ptr_priv = OpTypePointer Private %int
3100 %var1 = OpVariable %int_ptr_priv Private
3101 %var2 = OpVariable %int_ptr_priv Private
3102 %voidfn = OpTypeFunction %void
3103 %func = OpFunction %void None %voidfn
3104 %entry = OpLabel
3105 OpCopyMemorySized %var1 %var2 %int_16 Volatile|Aligned|Nontemporal 4
3106 OpReturn
3107 OpFunctionEnd
3108 )";
3109 
3110   CompileSuccessfully(spirv);
3111   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
3112 }
3113 
TEST_F(ValidateMemory,CopyMemorySizedSimpleTwoMixedAccessV13Bad)3114 TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV13Bad) {
3115   // Two memory access operands is invalid up to SPIR-V 1.3
3116   const std::string spirv = R"(
3117 OpCapability Shader
3118 OpCapability Linkage
3119 OpCapability Addresses
3120 OpMemoryModel Logical GLSL450
3121 %void = OpTypeVoid
3122 %int = OpTypeInt 32 0
3123 %int_16 = OpConstant %int 16
3124 %int_ptr_priv = OpTypePointer Private %int
3125 %var1 = OpVariable %int_ptr_priv Private
3126 %var2 = OpVariable %int_ptr_priv Private
3127 %voidfn = OpTypeFunction %void
3128 %func = OpFunction %void None %voidfn
3129 %entry = OpLabel
3130 OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile
3131 OpReturn
3132 OpFunctionEnd
3133 )";
3134 
3135   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
3136   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
3137             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3138   EXPECT_THAT(
3139       getDiagnosticString(),
3140       HasSubstr("CopyMemorySized with two memory access operands requires "
3141                 "SPIR-V 1.4 or later"));
3142 }
3143 
TEST_F(ValidateMemory,CopyMemorySizedSimpleTwoMixedAccessV14Good)3144 TEST_F(ValidateMemory, CopyMemorySizedSimpleTwoMixedAccessV14Good) {
3145   // Two memory access operands is valid in SPIR-V 1.4
3146   const std::string spirv = R"(
3147 OpCapability Shader
3148 OpCapability Linkage
3149 OpCapability Addresses
3150 OpMemoryModel Logical GLSL450
3151 %void = OpTypeVoid
3152 %int = OpTypeInt 32 0
3153 %int_16 = OpConstant %int 16
3154 %int_ptr_priv = OpTypePointer Private %int
3155 %var1 = OpVariable %int_ptr_priv Private
3156 %var2 = OpVariable %int_ptr_priv Private
3157 %voidfn = OpTypeFunction %void
3158 %func = OpFunction %void None %voidfn
3159 %entry = OpLabel
3160 OpCopyMemorySized %var1 %var2 %int_16 Volatile Volatile
3161 OpReturn
3162 OpFunctionEnd
3163 )";
3164 
3165   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3166   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3167   EXPECT_THAT(getDiagnosticString(), Eq(""));
3168 }
3169 
3170 using ValidatePointerComparisons = spvtest::ValidateBase<std::string>;
3171 
TEST_P(ValidatePointerComparisons,Good)3172 TEST_P(ValidatePointerComparisons, Good) {
3173   const std::string operation = GetParam();
3174 
3175   std::string spirv = R"(
3176 OpCapability Shader
3177 OpCapability Linkage
3178 OpCapability VariablePointersStorageBuffer
3179 OpMemoryModel Logical GLSL450
3180 %void = OpTypeVoid
3181 %bool = OpTypeBool
3182 %int = OpTypeInt 32 0
3183 %ptr_int = OpTypePointer StorageBuffer %int
3184 %var = OpVariable %ptr_int StorageBuffer
3185 %func_ty = OpTypeFunction %void
3186 %func = OpFunction %void None %func_ty
3187 %1 = OpLabel
3188 %equal = )" + operation;
3189 
3190   if (operation == "OpPtrDiff") {
3191     spirv += " %int ";
3192   } else {
3193     spirv += " %bool ";
3194   }
3195 
3196   spirv += R"(%var %var
3197 OpReturn
3198 OpFunctionEnd
3199 )";
3200 
3201   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3202   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3203 }
3204 
TEST_P(ValidatePointerComparisons,GoodWorkgroup)3205 TEST_P(ValidatePointerComparisons, GoodWorkgroup) {
3206   const std::string operation = GetParam();
3207 
3208   std::string spirv = R"(
3209 OpCapability Shader
3210 OpCapability Linkage
3211 OpCapability VariablePointers
3212 OpMemoryModel Logical GLSL450
3213 %void = OpTypeVoid
3214 %bool = OpTypeBool
3215 %int = OpTypeInt 32 0
3216 %ptr_int = OpTypePointer Workgroup %int
3217 %var = OpVariable %ptr_int Workgroup
3218 %func_ty = OpTypeFunction %void
3219 %func = OpFunction %void None %func_ty
3220 %1 = OpLabel
3221 %equal = )" + operation;
3222 
3223   if (operation == "OpPtrDiff") {
3224     spirv += " %int ";
3225   } else {
3226     spirv += " %bool ";
3227   }
3228 
3229   spirv += R"(%var %var
3230 OpReturn
3231 OpFunctionEnd
3232 )";
3233 
3234   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3235   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3236 }
3237 
TEST_P(ValidatePointerComparisons,BadResultType)3238 TEST_P(ValidatePointerComparisons, BadResultType) {
3239   const std::string operation = GetParam();
3240 
3241   std::string spirv = R"(
3242 OpCapability Shader
3243 OpCapability Linkage
3244 OpCapability VariablePointersStorageBuffer
3245 OpMemoryModel Logical GLSL450
3246 %void = OpTypeVoid
3247 %bool = OpTypeBool
3248 %int = OpTypeInt 32 0
3249 %ptr_int = OpTypePointer StorageBuffer %int
3250 %var = OpVariable %ptr_int StorageBuffer
3251 %func_ty = OpTypeFunction %void
3252 %func = OpFunction %void None %func_ty
3253 %1 = OpLabel
3254 %equal = )" + operation;
3255 
3256   if (operation == "OpPtrDiff") {
3257     spirv += " %bool ";
3258   } else {
3259     spirv += " %int ";
3260   }
3261 
3262   spirv += R"(%var %var
3263 OpReturn
3264 OpFunctionEnd
3265 )";
3266 
3267   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3268   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3269   if (operation == "OpPtrDiff") {
3270     EXPECT_THAT(getDiagnosticString(),
3271                 HasSubstr("Result Type must be an integer scalar"));
3272   } else {
3273     EXPECT_THAT(getDiagnosticString(),
3274                 HasSubstr("Result Type must be OpTypeBool"));
3275   }
3276 }
3277 
TEST_P(ValidatePointerComparisons,BadCapabilities)3278 TEST_P(ValidatePointerComparisons, BadCapabilities) {
3279   const std::string operation = GetParam();
3280 
3281   std::string spirv = R"(
3282 OpCapability Shader
3283 OpCapability Linkage
3284 OpMemoryModel Logical GLSL450
3285 %void = OpTypeVoid
3286 %bool = OpTypeBool
3287 %int = OpTypeInt 32 0
3288 %ptr_int = OpTypePointer StorageBuffer %int
3289 %var = OpVariable %ptr_int StorageBuffer
3290 %func_ty = OpTypeFunction %void
3291 %func = OpFunction %void None %func_ty
3292 %1 = OpLabel
3293 %equal = )" + operation;
3294 
3295   if (operation == "OpPtrDiff") {
3296     spirv += " %int ";
3297   } else {
3298     spirv += " %bool ";
3299   }
3300 
3301   spirv += R"(%var %var
3302 OpReturn
3303 OpFunctionEnd
3304 )";
3305 
3306   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3307   if (operation == "OpPtrDiff") {
3308     // Gets caught by the grammar.
3309     EXPECT_EQ(SPV_ERROR_INVALID_CAPABILITY,
3310               ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3311   } else {
3312     EXPECT_EQ(SPV_ERROR_INVALID_ID,
3313               ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3314     EXPECT_THAT(getDiagnosticString(),
3315                 HasSubstr("Instruction cannot for logical addressing model be "
3316                           "used without a variable pointers capability"));
3317   }
3318 }
3319 
TEST_P(ValidatePointerComparisons,BadOperandType)3320 TEST_P(ValidatePointerComparisons, BadOperandType) {
3321   const std::string operation = GetParam();
3322 
3323   std::string spirv = R"(
3324 OpCapability Shader
3325 OpCapability Linkage
3326 OpCapability VariablePointersStorageBuffer
3327 OpMemoryModel Logical GLSL450
3328 %void = OpTypeVoid
3329 %bool = OpTypeBool
3330 %int = OpTypeInt 32 0
3331 %ptr_int = OpTypePointer StorageBuffer %int
3332 %var = OpVariable %ptr_int StorageBuffer
3333 %func_ty = OpTypeFunction %void
3334 %func = OpFunction %void None %func_ty
3335 %1 = OpLabel
3336 %ld = OpLoad %int %var
3337 %equal = )" + operation;
3338 
3339   if (operation == "OpPtrDiff") {
3340     spirv += " %int ";
3341   } else {
3342     spirv += " %bool ";
3343   }
3344 
3345   spirv += R"(%ld %ld
3346 OpReturn
3347 OpFunctionEnd
3348 )";
3349 
3350   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3351   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3352   EXPECT_THAT(getDiagnosticString(),
3353               HasSubstr("Operand type must be a pointer"));
3354 }
3355 
TEST_P(ValidatePointerComparisons,BadStorageClassWorkgroup)3356 TEST_P(ValidatePointerComparisons, BadStorageClassWorkgroup) {
3357   const std::string operation = GetParam();
3358 
3359   std::string spirv = R"(
3360 OpCapability Shader
3361 OpCapability Linkage
3362 OpCapability VariablePointersStorageBuffer
3363 OpMemoryModel Logical GLSL450
3364 %void = OpTypeVoid
3365 %bool = OpTypeBool
3366 %int = OpTypeInt 32 0
3367 %ptr_int = OpTypePointer Workgroup %int
3368 %var = OpVariable %ptr_int Workgroup
3369 %func_ty = OpTypeFunction %void
3370 %func = OpFunction %void None %func_ty
3371 %1 = OpLabel
3372 %equal = )" + operation;
3373 
3374   if (operation == "OpPtrDiff") {
3375     spirv += " %int ";
3376   } else {
3377     spirv += " %bool ";
3378   }
3379 
3380   spirv += R"(%var %var
3381 OpReturn
3382 OpFunctionEnd
3383 )";
3384 
3385   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3386   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3387   EXPECT_THAT(getDiagnosticString(),
3388               HasSubstr("Workgroup storage class pointer requires "
3389                         "VariablePointers capability to be specified"));
3390 }
3391 
TEST_P(ValidatePointerComparisons,BadStorageClass)3392 TEST_P(ValidatePointerComparisons, BadStorageClass) {
3393   const std::string operation = GetParam();
3394 
3395   std::string spirv = R"(
3396 OpCapability Shader
3397 OpCapability Linkage
3398 OpCapability VariablePointersStorageBuffer
3399 OpMemoryModel Logical GLSL450
3400 %void = OpTypeVoid
3401 %bool = OpTypeBool
3402 %int = OpTypeInt 32 0
3403 %ptr_int = OpTypePointer Private %int
3404 %var = OpVariable %ptr_int Private
3405 %func_ty = OpTypeFunction %void
3406 %func = OpFunction %void None %func_ty
3407 %1 = OpLabel
3408 %equal = )" + operation;
3409 
3410   if (operation == "OpPtrDiff") {
3411     spirv += " %int ";
3412   } else {
3413     spirv += " %bool ";
3414   }
3415 
3416   spirv += R"(%var %var
3417 OpReturn
3418 OpFunctionEnd
3419 )";
3420 
3421   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3422   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3423   EXPECT_THAT(getDiagnosticString(),
3424               HasSubstr("Invalid pointer storage class"));
3425 }
3426 
TEST_P(ValidatePointerComparisons,BadDiffOperandTypes)3427 TEST_P(ValidatePointerComparisons, BadDiffOperandTypes) {
3428   const std::string operation = GetParam();
3429 
3430   std::string spirv = R"(
3431 OpCapability Shader
3432 OpCapability Linkage
3433 OpCapability VariablePointersStorageBuffer
3434 OpMemoryModel Logical GLSL450
3435 %void = OpTypeVoid
3436 %bool = OpTypeBool
3437 %int = OpTypeInt 32 0
3438 %ptr_int = OpTypePointer Private %int
3439 %var = OpVariable %ptr_int Private
3440 %func_ty = OpTypeFunction %void
3441 %func = OpFunction %void None %func_ty
3442 %1 = OpLabel
3443 %ld = OpLoad %int %var
3444 %equal = )" + operation;
3445 
3446   if (operation == "OpPtrDiff") {
3447     spirv += " %int ";
3448   } else {
3449     spirv += " %bool ";
3450   }
3451 
3452   spirv += R"(%var %ld
3453 OpReturn
3454 OpFunctionEnd
3455 )";
3456 
3457   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
3458   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
3459   EXPECT_THAT(getDiagnosticString(),
3460               HasSubstr("The types of Operand 1 and Operand 2 must match"));
3461 }
3462 
3463 INSTANTIATE_TEST_SUITE_P(PointerComparisons, ValidatePointerComparisons,
3464                          Values("OpPtrEqual", "OpPtrNotEqual", "OpPtrDiff"));
3465 
TEST_F(ValidateMemory,VariableInitializerWrongType)3466 TEST_F(ValidateMemory, VariableInitializerWrongType) {
3467   const std::string spirv = R"(
3468 OpCapability Shader
3469 OpCapability Linkage
3470 OpCapability VariablePointersStorageBuffer
3471 OpMemoryModel Logical GLSL450
3472 %void = OpTypeVoid
3473 %int = OpTypeInt 32 0
3474 %float = OpTypeFloat 32
3475 %ptr_wg_int = OpTypePointer Workgroup %int
3476 %ptr_wg_float = OpTypePointer Workgroup %int
3477 %wg_var = OpVariable %ptr_wg_int Workgroup
3478 %ptr_private_wg_float = OpTypePointer Private %ptr_wg_float
3479 %priv_var = OpVariable %ptr_private_wg_float Private %wg_var
3480 )";
3481 
3482   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
3483   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
3484   EXPECT_THAT(getDiagnosticString(),
3485               HasSubstr("Initializer type must match the type pointed to by "
3486                         "the Result Type"));
3487 }
3488 
TEST_F(ValidateMemory,StoreToUniformBlock)3489 TEST_F(ValidateMemory, StoreToUniformBlock) {
3490   const std::string spirv = R"(
3491 OpCapability Shader
3492 OpMemoryModel Logical GLSL450
3493 OpEntryPoint GLCompute %main "main"
3494 OpExecutionMode %main LocalSize 1 1 1
3495 OpDecorate %struct Block
3496 OpMemberDecorate %struct 0 Offset 0
3497 OpDecorate %var DescriptorSet 0
3498 OpDecorate %var Binding 0
3499 %void = OpTypeVoid
3500 %int = OpTypeInt 32 0
3501 %int_0 = OpConstant %int 0
3502 %int4 = OpTypeVector %int 4
3503 %struct = OpTypeStruct %int4
3504 %ptr_uniform_struct = OpTypePointer Uniform %struct
3505 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3506 %ptr_uniform_int = OpTypePointer Uniform %int
3507 %var = OpVariable %ptr_uniform_struct Uniform
3508 %void_fn = OpTypeFunction %void
3509 %main = OpFunction %void None %void_fn
3510 %entry = OpLabel
3511 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3512 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3513 OpStore %gep2 %int_0
3514 OpReturn
3515 OpFunctionEnd
3516 )";
3517 
3518   CompileSuccessfully(spirv);
3519   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3520 }
3521 
TEST_F(ValidateMemory,StoreToUniformBlockVulkan)3522 TEST_F(ValidateMemory, StoreToUniformBlockVulkan) {
3523   const std::string spirv = R"(
3524 OpCapability Shader
3525 OpMemoryModel Logical GLSL450
3526 OpEntryPoint GLCompute %main "main"
3527 OpExecutionMode %main LocalSize 1 1 1
3528 OpDecorate %struct Block
3529 OpMemberDecorate %struct 0 Offset 0
3530 OpDecorate %var DescriptorSet 0
3531 OpDecorate %var Binding 0
3532 %void = OpTypeVoid
3533 %int = OpTypeInt 32 0
3534 %int_0 = OpConstant %int 0
3535 %int4 = OpTypeVector %int 4
3536 %struct = OpTypeStruct %int4
3537 %ptr_uniform_struct = OpTypePointer Uniform %struct
3538 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3539 %ptr_uniform_int = OpTypePointer Uniform %int
3540 %var = OpVariable %ptr_uniform_struct Uniform
3541 %void_fn = OpTypeFunction %void
3542 %main = OpFunction %void None %void_fn
3543 %entry = OpLabel
3544 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3545 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3546 OpStore %gep2 %int_0
3547 OpReturn
3548 OpFunctionEnd
3549 )";
3550 
3551   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3552   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3553   EXPECT_THAT(getDiagnosticString(),
3554               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3555   EXPECT_THAT(
3556       getDiagnosticString(),
3557       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3558 }
3559 
3560 // This test requires that the struct is not id 2.
TEST_F(ValidateMemory,StoreToUniformBlockVulkan2)3561 TEST_F(ValidateMemory, StoreToUniformBlockVulkan2) {
3562   const std::string spirv = R"(
3563 OpCapability Shader
3564 OpMemoryModel Logical GLSL450
3565 OpEntryPoint GLCompute %main "main" %gid_var
3566 OpExecutionMode %main LocalSize 1 1 1
3567 OpDecorate %3 Block
3568 OpMemberDecorate %3 0 Offset 0
3569 OpDecorate %var DescriptorSet 0
3570 OpDecorate %var Binding 0
3571 OpDecorate %gid_var BuiltIn GlobalInvocationId
3572 %void = OpTypeVoid
3573 %int = OpTypeInt 32 0
3574 %int_0 = OpConstant %int 0
3575 %int3 = OpTypeVector %int 3
3576 %int4 = OpTypeVector %int 4
3577 %3 = OpTypeStruct %int4
3578 %ptr_uniform_struct = OpTypePointer Uniform %3
3579 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3580 %ptr_uniform_int = OpTypePointer Uniform %int
3581 %var = OpVariable %ptr_uniform_struct Uniform
3582 %ptr_input_int3 = OpTypePointer Input %int3
3583 %gid_var = OpVariable %ptr_input_int3 Input
3584 %void_fn = OpTypeFunction %void
3585 %main = OpFunction %void None %void_fn
3586 %entry = OpLabel
3587 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3588 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3589 OpStore %gep2 %int_0
3590 OpReturn
3591 OpFunctionEnd
3592 )";
3593 
3594   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3595   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3596   EXPECT_THAT(getDiagnosticString(),
3597               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3598   EXPECT_THAT(
3599       getDiagnosticString(),
3600       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3601 }
3602 
TEST_F(ValidateMemory,StoreToUniformBufferBlockVulkan)3603 TEST_F(ValidateMemory, StoreToUniformBufferBlockVulkan) {
3604   const std::string spirv = R"(
3605 OpCapability Shader
3606 OpMemoryModel Logical GLSL450
3607 OpEntryPoint GLCompute %main "main"
3608 OpExecutionMode %main LocalSize 1 1 1
3609 OpDecorate %struct BufferBlock
3610 OpMemberDecorate %struct 0 Offset 0
3611 OpDecorate %var DescriptorSet 0
3612 OpDecorate %var Binding 0
3613 %void = OpTypeVoid
3614 %int = OpTypeInt 32 0
3615 %int_0 = OpConstant %int 0
3616 %int4 = OpTypeVector %int 4
3617 %struct = OpTypeStruct %int4
3618 %ptr_uniform_struct = OpTypePointer Uniform %struct
3619 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3620 %ptr_uniform_int = OpTypePointer Uniform %int
3621 %var = OpVariable %ptr_uniform_struct Uniform
3622 %void_fn = OpTypeFunction %void
3623 %main = OpFunction %void None %void_fn
3624 %entry = OpLabel
3625 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0
3626 %gep2 = OpAccessChain %ptr_uniform_int %gep1 %int_0
3627 OpStore %gep2 %int_0
3628 OpReturn
3629 OpFunctionEnd
3630 )";
3631 
3632   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3633   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3634 }
3635 
TEST_F(ValidateMemory,StoreToUniformBlockVulkanArray)3636 TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray) {
3637   const std::string spirv = R"(
3638 OpCapability Shader
3639 OpMemoryModel Logical GLSL450
3640 OpEntryPoint GLCompute %main "main"
3641 OpExecutionMode %main LocalSize 1 1 1
3642 OpDecorate %struct Block
3643 OpMemberDecorate %struct 0 Offset 0
3644 OpDecorate %var DescriptorSet 0
3645 OpDecorate %var Binding 0
3646 %void = OpTypeVoid
3647 %int = OpTypeInt 32 0
3648 %int_0 = OpConstant %int 0
3649 %int_1 = OpConstant %int 1
3650 %int4 = OpTypeVector %int 4
3651 %struct = OpTypeStruct %int4
3652 %array_struct = OpTypeArray %struct %int_1
3653 %ptr_uniform_array = OpTypePointer Uniform %array_struct
3654 %ptr_uniform_struct = OpTypePointer Uniform %struct
3655 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3656 %ptr_uniform_int = OpTypePointer Uniform %int
3657 %var = OpVariable %ptr_uniform_array Uniform
3658 %void_fn = OpTypeFunction %void
3659 %main = OpFunction %void None %void_fn
3660 %entry = OpLabel
3661 %gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0
3662 %gep2 = OpCopyObject %ptr_uniform_int %gep1
3663 OpStore %gep2 %int_0
3664 OpReturn
3665 OpFunctionEnd
3666 )";
3667 
3668   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3669   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3670   EXPECT_THAT(getDiagnosticString(),
3671               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3672   EXPECT_THAT(
3673       getDiagnosticString(),
3674       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3675 }
3676 
3677 // This test requires that the struct is not id 2.
TEST_F(ValidateMemory,StoreToUniformBlockVulkanArray2)3678 TEST_F(ValidateMemory, StoreToUniformBlockVulkanArray2) {
3679   const std::string spirv = R"(
3680 OpCapability Shader
3681 OpMemoryModel Logical GLSL450
3682 OpEntryPoint GLCompute %main "main" %gid_var
3683 OpExecutionMode %main LocalSize 1 1 1
3684 OpDecorate %struct Block
3685 OpMemberDecorate %struct 0 Offset 0
3686 OpDecorate %var DescriptorSet 0
3687 OpDecorate %var Binding 0
3688 OpDecorate %gid_var BuiltIn GlobalInvocationId
3689 %void = OpTypeVoid
3690 %int = OpTypeInt 32 0
3691 %int_0 = OpConstant %int 0
3692 %int_1 = OpConstant %int 1
3693 %int3 = OpTypeVector %int 3
3694 %int4 = OpTypeVector %int 4
3695 %struct = OpTypeStruct %int4
3696 %array_struct = OpTypeArray %struct %int_1
3697 %ptr_uniform_array = OpTypePointer Uniform %array_struct
3698 %ptr_uniform_struct = OpTypePointer Uniform %struct
3699 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3700 %ptr_uniform_int = OpTypePointer Uniform %int
3701 %var = OpVariable %ptr_uniform_array Uniform
3702 %ptr_input_int3 = OpTypePointer Input %int3
3703 %gid_var = OpVariable %ptr_input_int3 Input
3704 %void_fn = OpTypeFunction %void
3705 %main = OpFunction %void None %void_fn
3706 %entry = OpLabel
3707 %gep1 = OpAccessChain %ptr_uniform_int %var %int_0 %int_0 %int_0
3708 %gep2 = OpCopyObject %ptr_uniform_int %gep1
3709 OpStore %gep2 %int_0
3710 OpReturn
3711 OpFunctionEnd
3712 )";
3713 
3714   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3715   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3716   EXPECT_THAT(getDiagnosticString(),
3717               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3718   EXPECT_THAT(
3719       getDiagnosticString(),
3720       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3721 }
3722 
TEST_F(ValidateMemory,StoreToUniformBlockVulkanRuntimeArray)3723 TEST_F(ValidateMemory, StoreToUniformBlockVulkanRuntimeArray) {
3724   const std::string spirv = R"(
3725 OpCapability Shader
3726 OpCapability RuntimeDescriptorArrayEXT
3727 OpExtension "SPV_EXT_descriptor_indexing"
3728 OpMemoryModel Logical GLSL450
3729 OpEntryPoint GLCompute %main "main"
3730 OpExecutionMode %main LocalSize 1 1 1
3731 OpDecorate %struct Block
3732 OpMemberDecorate %struct 0 Offset 0
3733 OpDecorate %var DescriptorSet 0
3734 OpDecorate %var Binding 0
3735 %void = OpTypeVoid
3736 %int = OpTypeInt 32 0
3737 %int_0 = OpConstant %int 0
3738 %int4 = OpTypeVector %int 4
3739 %struct = OpTypeStruct %int4
3740 %array_struct = OpTypeRuntimeArray %struct
3741 %ptr_uniform_array = OpTypePointer Uniform %array_struct
3742 %ptr_uniform_struct = OpTypePointer Uniform %struct
3743 %ptr_uniform_int4 = OpTypePointer Uniform %int4
3744 %ptr_uniform_int = OpTypePointer Uniform %int
3745 %var = OpVariable %ptr_uniform_array Uniform
3746 %void_fn = OpTypeFunction %void
3747 %main = OpFunction %void None %void_fn
3748 %entry = OpLabel
3749 %gep1 = OpAccessChain %ptr_uniform_int4 %var %int_0 %int_0
3750 %gep2 = OpInBoundsAccessChain %ptr_uniform_int %gep1 %int_0
3751 OpStore %gep2 %int_0
3752 OpReturn
3753 OpFunctionEnd
3754 )";
3755 
3756   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
3757   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1));
3758   EXPECT_THAT(getDiagnosticString(),
3759               AnyVUID("VUID-StandaloneSpirv-Uniform-06925"));
3760   EXPECT_THAT(
3761       getDiagnosticString(),
3762       HasSubstr("In the Vulkan environment, cannot store to Uniform Blocks"));
3763 }
3764 
3765 using ValidateSizedVariable =
3766     spvtest::ValidateBase<std::tuple<std::string, std::string,
3767                                      std::string, spv_target_env>>;
3768 
GetSizedVariableCodeGenerator(bool is_8bit,bool buffer_block)3769 CodeGenerator GetSizedVariableCodeGenerator(bool is_8bit, bool buffer_block) {
3770   CodeGenerator generator;
3771   generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n";
3772   generator.extensions_ =
3773       "OpExtension \"SPV_KHR_16bit_storage\"\nOpExtension "
3774       "\"SPV_KHR_8bit_storage\"\n";
3775   generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
3776   if (is_8bit) {
3777     generator.before_types_ = "OpMemberDecorate %char_buffer_block 0 Offset 0\n";
3778     if (buffer_block)
3779       generator.before_types_ += "OpDecorate %char_buffer_block BufferBlock\n";
3780 
3781     generator.types_ = R"(%void = OpTypeVoid
3782 %char = OpTypeInt 8 0
3783 %char4 = OpTypeVector %char 4
3784 %char_buffer_block = OpTypeStruct %char
3785 )";
3786   } else {
3787     generator.before_types_ =
3788         "OpMemberDecorate %half_buffer_block 0 Offset 0\n"
3789         "OpMemberDecorate %short_buffer_block 0 Offset 0\n";
3790     if (buffer_block) {
3791       generator.before_types_ +=
3792           "OpDecorate %half_buffer_block BufferBlock\n"
3793           "OpDecorate %short_buffer_block BufferBlock\n";
3794     }
3795 
3796     generator.types_ = R"(%void = OpTypeVoid
3797 %short = OpTypeInt 16 0
3798 %half = OpTypeFloat 16
3799 %short4 = OpTypeVector %short 4
3800 %half4 = OpTypeVector %half 4
3801 %mat4x4 = OpTypeMatrix %half4 4
3802 %short_buffer_block = OpTypeStruct %short
3803 %half_buffer_block = OpTypeStruct %half
3804 )";
3805   }
3806   generator.after_types_ = R"(%void_fn = OpTypeFunction %void
3807 %func = OpFunction %void None %void_fn
3808 %entry = OpLabel
3809 )";
3810   generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n";
3811   return generator;
3812 }
3813 
TEST_P(ValidateSizedVariable,Capability)3814 TEST_P(ValidateSizedVariable, Capability) {
3815   const std::string storage_class = std::get<0>(GetParam());
3816   const std::string capability = std::get<1>(GetParam());
3817   const std::string var_type = std::get<2>(GetParam());
3818   const spv_target_env target = std::get<3>(GetParam());
3819 
3820   ASSERT_TRUE(target == SPV_ENV_UNIVERSAL_1_3 ||
3821               target == SPV_ENV_UNIVERSAL_1_4);
3822 
3823   bool type_8bit = false;
3824   if (var_type == "%char" || var_type == "%char4" ||
3825       var_type == "%char_buffer_block") {
3826     type_8bit = true;
3827   }
3828 
3829   const bool buffer_block = var_type.find("buffer_block") != std::string::npos;
3830 
3831   auto generator = GetSizedVariableCodeGenerator(type_8bit, buffer_block);
3832 
3833   if (capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR" ||
3834       capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR") {
3835     generator.extensions_ +=
3836         "OpExtension \"SPV_KHR_workgroup_memory_explicit_layout\"\n";
3837   }
3838 
3839   generator.types_ += "%ptr_type = OpTypePointer " + storage_class + " " +
3840                       var_type + "\n%var = OpVariable %ptr_type " +
3841                       storage_class + "\n";
3842   generator.capabilities_ += "OpCapability " + capability + "\n";
3843 
3844   bool capability_ok = false;
3845   bool storage_class_ok = false;
3846   if (storage_class == "Input" || storage_class == "Output") {
3847     if (!type_8bit) {
3848       capability_ok = capability == "StorageInputOutput16";
3849       storage_class_ok = true;
3850     }
3851   } else if (storage_class == "StorageBuffer") {
3852     if (type_8bit) {
3853       capability_ok = capability == "StorageBuffer8BitAccess" ||
3854                       capability == "UniformAndStorageBuffer8BitAccess";
3855     } else {
3856       capability_ok = capability == "StorageBuffer16BitAccess" ||
3857                       capability == "UniformAndStorageBuffer16BitAccess";
3858     }
3859     storage_class_ok = true;
3860   } else if (storage_class == "PushConstant") {
3861     if (type_8bit) {
3862       capability_ok = capability == "StoragePushConstant8";
3863     } else {
3864       capability_ok = capability == "StoragePushConstant16";
3865     }
3866     storage_class_ok = true;
3867   } else if (storage_class == "Uniform") {
3868     if (type_8bit) {
3869       capability_ok = capability == "UniformAndStorageBuffer8BitAccess" ||
3870                       (capability == "StorageBuffer8BitAccess" && buffer_block);
3871     } else {
3872       capability_ok =
3873           capability == "UniformAndStorageBuffer16BitAccess" ||
3874           (capability == "StorageBuffer16BitAccess" && buffer_block);
3875     }
3876     storage_class_ok = true;
3877   } else if (storage_class == "Workgroup") {
3878     if (type_8bit) {
3879       capability_ok =
3880           capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR";
3881     } else {
3882       capability_ok =
3883           capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR";
3884     }
3885     storage_class_ok = true;
3886   }
3887 
3888   CompileSuccessfully(generator.Build(), target);
3889   spv_result_t result = ValidateInstructions(target);
3890   if (target < SPV_ENV_UNIVERSAL_1_4 &&
3891       (capability == "WorkgroupMemoryExplicitLayout8BitAccessKHR" ||
3892        capability == "WorkgroupMemoryExplicitLayout16BitAccessKHR")) {
3893     EXPECT_EQ(SPV_ERROR_WRONG_VERSION, result);
3894     EXPECT_THAT(getDiagnosticString(),
3895                 HasSubstr("requires SPIR-V version 1.4 or later"));
3896   } else if (buffer_block && target > SPV_ENV_UNIVERSAL_1_3) {
3897     EXPECT_EQ(SPV_ERROR_WRONG_VERSION, result);
3898     EXPECT_THAT(getDiagnosticString(),
3899                 HasSubstr("requires SPIR-V version 1.3 or earlier"));
3900   } else if (capability_ok) {
3901     EXPECT_EQ(SPV_SUCCESS, result);
3902   } else {
3903     EXPECT_EQ(SPV_ERROR_INVALID_ID, result);
3904     if (storage_class_ok) {
3905       std::string message = std::string("Allocating a variable containing a ") +
3906                             (type_8bit ? "8" : "16") + "-bit element in " +
3907                             storage_class +
3908                             " storage class requires an additional capability";
3909       EXPECT_THAT(getDiagnosticString(), HasSubstr(message));
3910     } else {
3911       std::string message =
3912           std::string("Cannot allocate a variable containing a ") +
3913           (type_8bit ? "8" : "16") + "-bit type in " + storage_class +
3914           " storage class";
3915       EXPECT_THAT(getDiagnosticString(), HasSubstr(message));
3916     }
3917   }
3918 }
3919 
3920 INSTANTIATE_TEST_SUITE_P(
3921     Storage8, ValidateSizedVariable,
3922     Combine(Values("UniformConstant", "Input", "Output", "Workgroup",
3923                    "CrossWorkgroup", "Private", "StorageBuffer", "Uniform"),
3924             Values("StorageBuffer8BitAccess",
3925                    "UniformAndStorageBuffer8BitAccess", "StoragePushConstant8",
3926                    "WorkgroupMemoryExplicitLayout8BitAccessKHR"),
3927             Values("%char", "%char4", "%char_buffer_block"),
3928             Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4)));
3929 
3930 INSTANTIATE_TEST_SUITE_P(
3931     Storage16, ValidateSizedVariable,
3932     Combine(Values("UniformConstant", "Input", "Output", "Workgroup",
3933                    "CrossWorkgroup", "Private", "StorageBuffer", "Uniform"),
3934             Values("StorageBuffer16BitAccess",
3935                    "UniformAndStorageBuffer16BitAccess",
3936                    "StoragePushConstant16", "StorageInputOutput16",
3937                    "WorkgroupMemoryExplicitLayout16BitAccessKHR"),
3938             Values("%short", "%half", "%short4", "%half4", "%mat4x4",
3939                    "%short_buffer_block", "%half_buffer_block"),
3940             Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_UNIVERSAL_1_4)));
3941 
3942 using ValidateSizedLoadStore =
3943     spvtest::ValidateBase<std::tuple<std::string, uint32_t, std::string>>;
3944 
GetSizedLoadStoreCodeGenerator(const std::string & base_type,uint32_t width)3945 CodeGenerator GetSizedLoadStoreCodeGenerator(const std::string& base_type,
3946                                              uint32_t width) {
3947   CodeGenerator generator;
3948   generator.capabilities_ = "OpCapability Shader\nOpCapability Linkage\n";
3949   if (width == 8) {
3950     generator.capabilities_ +=
3951         "OpCapability UniformAndStorageBuffer8BitAccess\n";
3952     generator.extensions_ = "OpExtension \"SPV_KHR_8bit_storage\"\n";
3953   } else {
3954     generator.capabilities_ +=
3955         "OpCapability UniformAndStorageBuffer16BitAccess\n";
3956     generator.extensions_ = "OpExtension \"SPV_KHR_16bit_storage\"\n";
3957   }
3958   generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
3959   generator.before_types_ = R"(OpDecorate %block Block
3960 OpMemberDecorate %block 0 Offset 0
3961 OpMemberDecorate %struct 0 Offset 0
3962 )";
3963   generator.types_ = R"(%void = OpTypeVoid
3964 %int = OpTypeInt 32 0
3965 %int_0 = OpConstant %int 0
3966 %int_1 = OpConstant %int 1
3967 %int_2 = OpConstant %int 2
3968 %int_3 = OpConstant %int 3
3969 )";
3970 
3971   if (width == 8) {
3972     generator.types_ += R"(%scalar = OpTypeInt 8 0
3973 %vector = OpTypeVector %scalar 4
3974 %struct = OpTypeStruct %vector
3975 )";
3976   } else if (base_type == "int") {
3977     generator.types_ += R"(%scalar = OpTypeInt 16 0
3978 %vector = OpTypeVector %scalar 4
3979 %struct = OpTypeStruct %vector
3980 )";
3981   } else {
3982     generator.types_ += R"(%scalar = OpTypeFloat 16
3983 %vector = OpTypeVector %scalar 4
3984 %matrix = OpTypeMatrix %vector 4
3985 %struct = OpTypeStruct %matrix
3986 %ptr_ssbo_matrix = OpTypePointer StorageBuffer %matrix
3987 )";
3988     generator.before_types_ += R"(OpMemberDecorate %struct 0 RowMajor
3989 OpMemberDecorate %struct 0 MatrixStride 16
3990 )";
3991   }
3992   generator.types_ += R"(%block = OpTypeStruct %struct
3993 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
3994 %ptr_ssbo_struct = OpTypePointer StorageBuffer %struct
3995 %ptr_ssbo_vector = OpTypePointer StorageBuffer %vector
3996 %ptr_ssbo_scalar = OpTypePointer StorageBuffer %scalar
3997 %ld_var = OpVariable %ptr_ssbo_block StorageBuffer
3998 %st_var = OpVariable %ptr_ssbo_block StorageBuffer
3999 )";
4000 
4001   generator.after_types_ = R"(%void_fn = OpTypeFunction %void
4002 %func = OpFunction %void None %void_fn
4003 %entry = OpLabel
4004 )";
4005   generator.add_at_the_end_ = "OpReturn\nOpFunctionEnd\n";
4006   return generator;
4007 }
4008 
TEST_P(ValidateSizedLoadStore,Load)4009 TEST_P(ValidateSizedLoadStore, Load) {
4010   std::string base_type = std::get<0>(GetParam());
4011   uint32_t width = std::get<1>(GetParam());
4012   std::string mem_type = std::get<2>(GetParam());
4013 
4014   CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width);
4015   generator.after_types_ +=
4016       "%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0";
4017   if (mem_type != "struct") {
4018     generator.after_types_ += " %int_0";
4019     if (mem_type != "matrix" && base_type == "float") {
4020       generator.after_types_ += " %int_0";
4021     }
4022     if (mem_type == "scalar") {
4023       generator.after_types_ += " %int_0";
4024     }
4025   }
4026   generator.after_types_ += "\n";
4027   generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n";
4028 
4029   CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
4030   if (mem_type == "struct") {
4031     EXPECT_EQ(SPV_ERROR_INVALID_ID,
4032               ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4033     EXPECT_THAT(
4034         getDiagnosticString(),
4035         HasSubstr(
4036             "8- or 16-bit loads must be a scalar, vector or matrix type"));
4037   } else {
4038     EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4039   }
4040 }
4041 
TEST_P(ValidateSizedLoadStore,Store)4042 TEST_P(ValidateSizedLoadStore, Store) {
4043   std::string base_type = std::get<0>(GetParam());
4044   uint32_t width = std::get<1>(GetParam());
4045   std::string mem_type = std::get<2>(GetParam());
4046 
4047   CodeGenerator generator = GetSizedLoadStoreCodeGenerator(base_type, width);
4048   generator.after_types_ +=
4049       "%ld_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %ld_var %int_0";
4050   if (mem_type != "struct") {
4051     generator.after_types_ += " %int_0";
4052     if (mem_type != "matrix" && base_type == "float") {
4053       generator.after_types_ += " %int_0";
4054     }
4055     if (mem_type == "scalar") {
4056       generator.after_types_ += " %int_0";
4057     }
4058   }
4059   generator.after_types_ += "\n";
4060   generator.after_types_ += "%ld = OpLoad %" + mem_type + " %ld_gep\n";
4061   generator.after_types_ +=
4062       "%st_gep = OpAccessChain %ptr_ssbo_" + mem_type + " %st_var %int_0";
4063   if (mem_type != "struct") {
4064     generator.after_types_ += " %int_0";
4065     if (mem_type != "matrix" && base_type == "float") {
4066       generator.after_types_ += " %int_0";
4067     }
4068     if (mem_type == "scalar") {
4069       generator.after_types_ += " %int_0";
4070     }
4071   }
4072   generator.after_types_ += "\n";
4073   generator.after_types_ += "OpStore %st_gep %ld\n";
4074 
4075   CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
4076   if (mem_type == "struct") {
4077     EXPECT_EQ(SPV_ERROR_INVALID_ID,
4078               ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4079     // Can only catch the load.
4080     EXPECT_THAT(
4081         getDiagnosticString(),
4082         HasSubstr(
4083             "8- or 16-bit loads must be a scalar, vector or matrix type"));
4084   } else {
4085     EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4086   }
4087 }
4088 
4089 INSTANTIATE_TEST_SUITE_P(LoadStoreInt8, ValidateSizedLoadStore,
4090                          Combine(Values("int"), Values(8u),
4091                                  Values("scalar", "vector", "struct")));
4092 INSTANTIATE_TEST_SUITE_P(LoadStoreInt16, ValidateSizedLoadStore,
4093                          Combine(Values("int"), Values(16u),
4094                                  Values("scalar", "vector", "struct")));
4095 INSTANTIATE_TEST_SUITE_P(LoadStoreFloat16, ValidateSizedLoadStore,
4096                          Combine(Values("float"), Values(16u),
4097                                  Values("scalar", "vector", "matrix",
4098                                         "struct")));
4099 
TEST_F(ValidateMemory,SmallStorageCopyMemoryChar)4100 TEST_F(ValidateMemory, SmallStorageCopyMemoryChar) {
4101   const std::string spirv = R"(
4102 OpCapability Shader
4103 OpCapability Linkage
4104 OpCapability UniformAndStorageBuffer8BitAccess
4105 OpExtension "SPV_KHR_8bit_storage"
4106 OpMemoryModel Logical GLSL450
4107 OpDecorate %block Block
4108 OpMemberDecorate %block 0 Offset 0
4109 %void = OpTypeVoid
4110 %int = OpTypeInt 32 0
4111 %int_0 = OpConstant %int 0
4112 %char = OpTypeInt 8 0
4113 %block = OpTypeStruct %char
4114 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
4115 %in = OpVariable %ptr_ssbo_block StorageBuffer
4116 %out = OpVariable %ptr_ssbo_block StorageBuffer
4117 %void_fn = OpTypeFunction %void
4118 %func = OpFunction %void None %void_fn
4119 %entry = OpLabel
4120 OpCopyMemory %out %in
4121 OpReturn
4122 OpFunctionEnd
4123 )";
4124 
4125   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4126   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4127   EXPECT_THAT(
4128       getDiagnosticString(),
4129       HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
4130 }
4131 
TEST_F(ValidateMemory,SmallStorageCopyMemoryShort)4132 TEST_F(ValidateMemory, SmallStorageCopyMemoryShort) {
4133   const std::string spirv = R"(
4134 OpCapability Shader
4135 OpCapability Linkage
4136 OpCapability UniformAndStorageBuffer16BitAccess
4137 OpExtension "SPV_KHR_16bit_storage"
4138 OpMemoryModel Logical GLSL450
4139 OpDecorate %block Block
4140 OpMemberDecorate %block 0 Offset 0
4141 %void = OpTypeVoid
4142 %int = OpTypeInt 32 0
4143 %int_0 = OpConstant %int 0
4144 %short = OpTypeInt 16 0
4145 %block = OpTypeStruct %short
4146 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
4147 %in = OpVariable %ptr_ssbo_block StorageBuffer
4148 %out = OpVariable %ptr_ssbo_block StorageBuffer
4149 %void_fn = OpTypeFunction %void
4150 %func = OpFunction %void None %void_fn
4151 %entry = OpLabel
4152 OpCopyMemory %out %in
4153 OpReturn
4154 OpFunctionEnd
4155 )";
4156 
4157   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4158   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4159   EXPECT_THAT(
4160       getDiagnosticString(),
4161       HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
4162 }
4163 
TEST_F(ValidateMemory,SmallStorageCopyMemoryHalf)4164 TEST_F(ValidateMemory, SmallStorageCopyMemoryHalf) {
4165   const std::string spirv = R"(
4166 OpCapability Shader
4167 OpCapability Linkage
4168 OpCapability UniformAndStorageBuffer16BitAccess
4169 OpExtension "SPV_KHR_16bit_storage"
4170 OpMemoryModel Logical GLSL450
4171 OpDecorate %block Block
4172 OpMemberDecorate %block 0 Offset 0
4173 %void = OpTypeVoid
4174 %int = OpTypeInt 32 0
4175 %int_0 = OpConstant %int 0
4176 %half = OpTypeFloat 16
4177 %block = OpTypeStruct %half
4178 %ptr_ssbo_block = OpTypePointer StorageBuffer %block
4179 %in = OpVariable %ptr_ssbo_block StorageBuffer
4180 %out = OpVariable %ptr_ssbo_block StorageBuffer
4181 %void_fn = OpTypeFunction %void
4182 %func = OpFunction %void None %void_fn
4183 %entry = OpLabel
4184 OpCopyMemory %out %in
4185 OpReturn
4186 OpFunctionEnd
4187 )";
4188 
4189   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4190   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4191   EXPECT_THAT(
4192       getDiagnosticString(),
4193       HasSubstr("Cannot copy memory of objects containing 8- or 16-bit types"));
4194 }
4195 
TEST_F(ValidateMemory,SmallStorageVariableArrayBufferBlockShort)4196 TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockShort) {
4197   const std::string spirv = R"(
4198 OpCapability Shader
4199 OpCapability Linkage
4200 OpCapability StorageBuffer16BitAccess
4201 OpExtension "SPV_KHR_16bit_storage"
4202 OpMemoryModel Logical GLSL450
4203 OpDecorate %block BufferBlock
4204 OpMemberDecorate %block 0 Offset 0
4205 %void = OpTypeVoid
4206 %short = OpTypeInt 16 0
4207 %int = OpTypeInt 32 0
4208 %int_4 = OpConstant %int 4
4209 %block = OpTypeStruct %short
4210 %block_array = OpTypeArray %block %int_4
4211 %ptr_block_array = OpTypePointer Uniform %block_array
4212 %var = OpVariable %ptr_block_array Uniform
4213 )";
4214 
4215   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4216   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4217 }
4218 
TEST_F(ValidateMemory,SmallStorageVariableArrayBufferBlockChar)4219 TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockChar) {
4220   const std::string spirv = R"(
4221 OpCapability Shader
4222 OpCapability Linkage
4223 OpCapability StorageBuffer8BitAccess
4224 OpExtension "SPV_KHR_8bit_storage"
4225 OpMemoryModel Logical GLSL450
4226 OpDecorate %block BufferBlock
4227 OpMemberDecorate %block 0 Offset 0
4228 %void = OpTypeVoid
4229 %char = OpTypeInt 8 0
4230 %int = OpTypeInt 32 0
4231 %int_4 = OpConstant %int 4
4232 %block = OpTypeStruct %char
4233 %block_array = OpTypeArray %block %int_4
4234 %ptr_block_array = OpTypePointer Uniform %block_array
4235 %var = OpVariable %ptr_block_array Uniform
4236 )";
4237 
4238   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4239   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4240 }
4241 
TEST_F(ValidateMemory,SmallStorageVariableArrayBufferBlockHalf)4242 TEST_F(ValidateMemory, SmallStorageVariableArrayBufferBlockHalf) {
4243   const std::string spirv = R"(
4244 OpCapability Shader
4245 OpCapability Linkage
4246 OpCapability StorageBuffer16BitAccess
4247 OpExtension "SPV_KHR_16bit_storage"
4248 OpMemoryModel Logical GLSL450
4249 OpDecorate %block BufferBlock
4250 OpMemberDecorate %block 0 Offset 0
4251 %void = OpTypeVoid
4252 %half = OpTypeFloat 16
4253 %int = OpTypeInt 32 0
4254 %int_4 = OpConstant %int 4
4255 %block = OpTypeStruct %half
4256 %block_array = OpTypeArray %block %int_4
4257 %ptr_block_array = OpTypePointer Uniform %block_array
4258 %var = OpVariable %ptr_block_array Uniform
4259 )";
4260 
4261   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
4262   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
4263 }
4264 
TEST_F(ValidateMemory,VulkanStorageBufferNotAStruct)4265 TEST_F(ValidateMemory, VulkanStorageBufferNotAStruct) {
4266   const std::string spirv = R"(
4267 OpCapability Shader
4268 OpExtension "SPV_KHR_storage_buffer_storage_class"
4269 OpMemoryModel Logical GLSL450
4270 OpEntryPoint GLCompute %main "main"
4271 OpExecutionMode %main LocalSize 1 1 1
4272 %void = OpTypeVoid
4273 %uint = OpTypeInt 32 0
4274 %ptr_ssbo = OpTypePointer StorageBuffer %uint
4275 %var = OpVariable %ptr_ssbo StorageBuffer
4276 %void_fn = OpTypeFunction %void
4277 %main = OpFunction %void None %void_fn
4278 %entry = OpLabel
4279 OpReturn
4280 OpFunctionEnd
4281 )";
4282 
4283   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4284   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4285   EXPECT_THAT(getDiagnosticString(),
4286               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
4287   EXPECT_THAT(
4288       getDiagnosticString(),
4289       HasSubstr("From Vulkan spec:\nVariables identified with "
4290                 "the StorageBuffer storage class are used to access "
4291                 "transparent buffer backed resources. Such variables must be "
4292                 "typed as OpTypeStruct, or an array of this type"));
4293 }
4294 
TEST_F(ValidateMemory,VulkanStorageBufferRuntimeArrayNotAStruct)4295 TEST_F(ValidateMemory, VulkanStorageBufferRuntimeArrayNotAStruct) {
4296   const std::string spirv = R"(
4297 OpCapability Shader
4298 OpCapability RuntimeDescriptorArrayEXT
4299 OpExtension "SPV_KHR_storage_buffer_storage_class"
4300 OpExtension "SPV_EXT_descriptor_indexing"
4301 OpMemoryModel Logical GLSL450
4302 OpEntryPoint GLCompute %main "main"
4303 OpExecutionMode %main LocalSize 1 1 1
4304 %void = OpTypeVoid
4305 %uint = OpTypeInt 32 0
4306 %array = OpTypeRuntimeArray %uint
4307 %ptr_ssbo = OpTypePointer StorageBuffer %array
4308 %var = OpVariable %ptr_ssbo StorageBuffer
4309 %void_fn = OpTypeFunction %void
4310 %main = OpFunction %void None %void_fn
4311 %entry = OpLabel
4312 OpReturn
4313 OpFunctionEnd
4314 )";
4315 
4316   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4317   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4318   EXPECT_THAT(getDiagnosticString(),
4319               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
4320   EXPECT_THAT(
4321       getDiagnosticString(),
4322       HasSubstr("From Vulkan spec:\nVariables identified with "
4323                 "the StorageBuffer storage class are used to access "
4324                 "transparent buffer backed resources. Such variables must be "
4325                 "typed as OpTypeStruct, or an array of this type"));
4326 }
4327 
TEST_F(ValidateMemory,VulkanStorageBufferArrayNotAStruct)4328 TEST_F(ValidateMemory, VulkanStorageBufferArrayNotAStruct) {
4329   const std::string spirv = R"(
4330 OpCapability Shader
4331 OpExtension "SPV_KHR_storage_buffer_storage_class"
4332 OpMemoryModel Logical GLSL450
4333 OpEntryPoint GLCompute %main "main"
4334 OpExecutionMode %main LocalSize 1 1 1
4335 %void = OpTypeVoid
4336 %uint = OpTypeInt 32 0
4337 %uint_4 = OpConstant %uint 4
4338 %array = OpTypeArray %uint %uint_4
4339 %ptr_ssbo = OpTypePointer StorageBuffer %array
4340 %var = OpVariable %ptr_ssbo StorageBuffer
4341 %void_fn = OpTypeFunction %void
4342 %main = OpFunction %void None %void_fn
4343 %entry = OpLabel
4344 OpReturn
4345 OpFunctionEnd
4346 )";
4347 
4348   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4349   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4350   EXPECT_THAT(getDiagnosticString(),
4351               AnyVUID("VUID-StandaloneSpirv-Uniform-06807"));
4352   EXPECT_THAT(
4353       getDiagnosticString(),
4354       HasSubstr("From Vulkan spec:\nVariables identified with "
4355                 "the StorageBuffer storage class are used to access "
4356                 "transparent buffer backed resources. Such variables must be "
4357                 "typed as OpTypeStruct, or an array of this type"));
4358 }
4359 
TEST_F(ValidateMemory,VulkanInvariantOutputSuccess)4360 TEST_F(ValidateMemory, VulkanInvariantOutputSuccess) {
4361   const std::string spirv = R"(
4362 OpCapability Shader
4363 OpMemoryModel Logical GLSL450
4364 OpEntryPoint Vertex %main "main" %var
4365 OpDecorate %var Location 0
4366 OpDecorate %var Invariant
4367 %void = OpTypeVoid
4368 %f32 = OpTypeFloat 32
4369 %ptr_output = OpTypePointer Output %f32
4370 %var = OpVariable %ptr_output Output
4371 %void_fn = OpTypeFunction %void
4372 %main = OpFunction %void None %void_fn
4373 %entry = OpLabel
4374 OpReturn
4375 OpFunctionEnd
4376 )";
4377 
4378   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4379   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4380 }
4381 
TEST_F(ValidateMemory,VulkanInvariantInputStructSuccess)4382 TEST_F(ValidateMemory, VulkanInvariantInputStructSuccess) {
4383   const std::string spirv = R"(
4384 OpCapability Shader
4385 OpMemoryModel Logical GLSL450
4386 OpEntryPoint Fragment %main "main" %var
4387 OpExecutionMode %main OriginUpperLeft
4388 OpDecorate %var Location 0
4389 OpMemberDecorate %struct 1 Invariant
4390 %void = OpTypeVoid
4391 %f32 = OpTypeFloat 32
4392 %struct = OpTypeStruct %f32 %f32
4393 %ptr_input = OpTypePointer Input %struct
4394 %var = OpVariable %ptr_input Input
4395 %void_fn = OpTypeFunction %void
4396 %main = OpFunction %void None %void_fn
4397 %entry = OpLabel
4398 OpReturn
4399 OpFunctionEnd
4400 )";
4401 
4402   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4403   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4404 }
4405 
TEST_F(ValidateMemory,VulkanInvariantWrongStorageClass)4406 TEST_F(ValidateMemory, VulkanInvariantWrongStorageClass) {
4407   const std::string spirv = R"(
4408 OpCapability Shader
4409 OpMemoryModel Logical GLSL450
4410 OpEntryPoint Vertex %main "main"
4411 OpDecorate %var Invariant
4412 %void = OpTypeVoid
4413 %f32 = OpTypeFloat 32
4414 %ptr_private = OpTypePointer Private %f32
4415 %var = OpVariable %ptr_private Private
4416 %void_fn = OpTypeFunction %void
4417 %main = OpFunction %void None %void_fn
4418 %entry = OpLabel
4419 OpReturn
4420 OpFunctionEnd
4421 )";
4422 
4423   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4424   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4425   EXPECT_THAT(getDiagnosticString(),
4426               AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
4427   EXPECT_THAT(
4428       getDiagnosticString(),
4429       HasSubstr(
4430           "Variable decorated with Invariant must only be identified with the "
4431           "Input or Output storage class in Vulkan environment."));
4432 }
4433 
TEST_F(ValidateMemory,VulkanInvariantMemberWrongStorageClass)4434 TEST_F(ValidateMemory, VulkanInvariantMemberWrongStorageClass) {
4435   const std::string spirv = R"(
4436 OpCapability Shader
4437 OpMemoryModel Logical GLSL450
4438 OpEntryPoint Fragment %main "main"
4439 OpExecutionMode %main OriginUpperLeft
4440 OpMemberDecorate %struct 1 Invariant
4441 %void = OpTypeVoid
4442 %f32 = OpTypeFloat 32
4443 %struct = OpTypeStruct %f32 %f32
4444 %ptr_private = OpTypePointer Private %struct
4445 %var = OpVariable %ptr_private Private
4446 %void_fn = OpTypeFunction %void
4447 %main = OpFunction %void None %void_fn
4448 %entry = OpLabel
4449 OpReturn
4450 OpFunctionEnd
4451 )";
4452 
4453   CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_0);
4454   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4455   EXPECT_THAT(getDiagnosticString(),
4456               AnyVUID("VUID-StandaloneSpirv-Invariant-04677"));
4457   EXPECT_THAT(getDiagnosticString(),
4458               HasSubstr("Variable struct member decorated with Invariant must "
4459                         "only be identified with the Input or Output storage "
4460                         "class in Vulkan environment."));
4461 }
4462 
TEST_F(ValidateMemory,PhysicalStorageBufferPtrEqual)4463 TEST_F(ValidateMemory, PhysicalStorageBufferPtrEqual) {
4464   const std::string spirv = R"(
4465 OpCapability Shader
4466 OpCapability Int64
4467 OpCapability PhysicalStorageBufferAddresses
4468 OpMemoryModel PhysicalStorageBuffer64 GLSL450
4469 OpEntryPoint GLCompute %main "main"
4470 OpExecutionMode %main LocalSize 1 1 1
4471 %void = OpTypeVoid
4472 %bool = OpTypeBool
4473 %long = OpTypeInt 64 0
4474 %long_0 = OpConstant %long 0
4475 %ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
4476 %void_fn = OpTypeFunction %void
4477 %main = OpFunction %void None %void_fn
4478 %entry = OpLabel
4479 %conv = OpConvertUToPtr %ptr_pssbo_long %long_0
4480 %eq = OpPtrEqual %bool %conv %conv
4481 OpReturn
4482 OpFunctionEnd
4483 )";
4484 
4485   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4486   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4487   EXPECT_THAT(
4488       getDiagnosticString(),
4489       HasSubstr(
4490           "Cannot use a pointer in the PhysicalStorageBuffer storage class"));
4491 }
4492 
TEST_F(ValidateMemory,PhysicalStorageBufferPtrNotEqual)4493 TEST_F(ValidateMemory, PhysicalStorageBufferPtrNotEqual) {
4494   const std::string spirv = R"(
4495 OpCapability Shader
4496 OpCapability Int64
4497 OpCapability PhysicalStorageBufferAddresses
4498 OpMemoryModel PhysicalStorageBuffer64 GLSL450
4499 OpEntryPoint GLCompute %main "main"
4500 OpExecutionMode %main LocalSize 1 1 1
4501 %void = OpTypeVoid
4502 %bool = OpTypeBool
4503 %long = OpTypeInt 64 0
4504 %long_0 = OpConstant %long 0
4505 %ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
4506 %void_fn = OpTypeFunction %void
4507 %main = OpFunction %void None %void_fn
4508 %entry = OpLabel
4509 %conv = OpConvertUToPtr %ptr_pssbo_long %long_0
4510 %neq = OpPtrNotEqual %bool %conv %conv
4511 OpReturn
4512 OpFunctionEnd
4513 )";
4514 
4515   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4516   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4517   EXPECT_THAT(
4518       getDiagnosticString(),
4519       HasSubstr(
4520           "Cannot use a pointer in the PhysicalStorageBuffer storage class"));
4521 }
4522 
TEST_F(ValidateMemory,PhysicalStorageBufferPtrDiff)4523 TEST_F(ValidateMemory, PhysicalStorageBufferPtrDiff) {
4524   const std::string spirv = R"(
4525 OpCapability Shader
4526 OpCapability Int64
4527 OpCapability PhysicalStorageBufferAddresses
4528 OpCapability VariablePointers
4529 OpMemoryModel PhysicalStorageBuffer64 GLSL450
4530 OpEntryPoint GLCompute %main "main"
4531 OpExecutionMode %main LocalSize 1 1 1
4532 %void = OpTypeVoid
4533 %long = OpTypeInt 64 0
4534 %long_0 = OpConstant %long 0
4535 %ptr_pssbo_long = OpTypePointer PhysicalStorageBuffer %long
4536 %void_fn = OpTypeFunction %void
4537 %main = OpFunction %void None %void_fn
4538 %entry = OpLabel
4539 %conv = OpConvertUToPtr %ptr_pssbo_long %long_0
4540 %diff = OpPtrDiff %long %conv %conv
4541 OpReturn
4542 OpFunctionEnd
4543 )";
4544 
4545   CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_5);
4546   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
4547   EXPECT_THAT(
4548       getDiagnosticString(),
4549       HasSubstr(
4550           "Cannot use a pointer in the PhysicalStorageBuffer storage class"));
4551 }
4552 
TEST_F(ValidateMemory,VulkanInitializerWithWorkgroupStorageClassBad)4553 TEST_F(ValidateMemory, VulkanInitializerWithWorkgroupStorageClassBad) {
4554   std::string spirv = R"(
4555 OpCapability Shader
4556 OpCapability VulkanMemoryModelKHR
4557 OpExtension "SPV_KHR_vulkan_memory_model"
4558 OpMemoryModel Logical VulkanKHR
4559 OpEntryPoint Fragment %func "func"
4560 OpExecutionMode %func OriginUpperLeft
4561 %float = OpTypeFloat 32
4562 %float_ptr = OpTypePointer Workgroup %float
4563 %init_val = OpConstant %float 1.0
4564 %1 = OpVariable %float_ptr Workgroup %init_val
4565 %void = OpTypeVoid
4566 %functy = OpTypeFunction %void
4567 %func = OpFunction %void None %functy
4568 %2 = OpLabel
4569 OpReturn
4570 OpFunctionEnd
4571 )";
4572   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
4573   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4574   EXPECT_THAT(getDiagnosticString(),
4575               AnyVUID(" VUID-StandaloneSpirv-OpVariable-04734"));
4576   EXPECT_THAT(getDiagnosticString(),
4577               HasSubstr("OpVariable, <id> '5[%5]', initializers are limited to "
4578                         "OpConstantNull in Workgroup storage class"));
4579 }
4580 
TEST_F(ValidateMemory,VulkanInitializerWithWorkgroupStorageClassGood)4581 TEST_F(ValidateMemory, VulkanInitializerWithWorkgroupStorageClassGood) {
4582   std::string spirv = R"(
4583 OpCapability Shader
4584 OpCapability VulkanMemoryModelKHR
4585 OpExtension "SPV_KHR_vulkan_memory_model"
4586 OpMemoryModel Logical VulkanKHR
4587 OpEntryPoint Fragment %func "func"
4588 OpExecutionMode %func OriginUpperLeft
4589 %float = OpTypeFloat 32
4590 %float_ptr = OpTypePointer Workgroup %float
4591 %init_val = OpConstantNull %float
4592 %1 = OpVariable %float_ptr Workgroup %init_val
4593 %void = OpTypeVoid
4594 %functy = OpTypeFunction %void
4595 %func = OpFunction %void None %functy
4596 %2 = OpLabel
4597 OpReturn
4598 OpFunctionEnd
4599 )";
4600   CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
4601   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_0));
4602 }
4603 
TEST_F(ValidateMemory,LoadRuntimeArray)4604 TEST_F(ValidateMemory, LoadRuntimeArray) {
4605   const std::string spirv = R"(
4606 OpCapability Shader
4607 OpExtension "SPV_KHR_storage_buffer_storage_class"
4608 OpMemoryModel Logical GLSL450
4609 OpEntryPoint GLCompute %main "main"
4610 %void = OpTypeVoid
4611 %int = OpTypeInt 32 0
4612 %int_0 = OpConstant %int 0
4613 %rta = OpTypeRuntimeArray %int
4614 %block = OpTypeStruct %rta
4615 %ptr_rta = OpTypePointer StorageBuffer %rta
4616 %ptr_block = OpTypePointer StorageBuffer %block
4617 %var = OpVariable %ptr_block StorageBuffer
4618 %void_fn = OpTypeFunction %void
4619 %main = OpFunction %void None %void_fn
4620 %entry = OpLabel
4621 %gep = OpAccessChain %ptr_rta %var %int_0
4622 %ld = OpLoad %rta %gep
4623 OpReturn
4624 OpFunctionEnd
4625 )";
4626 
4627   CompileSuccessfully(spirv);
4628   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4629   EXPECT_THAT(getDiagnosticString(),
4630               HasSubstr("Cannot load a runtime-sized array"));
4631 }
4632 
TEST_F(ValidateMemory,LoadRuntimeArrayInStruct)4633 TEST_F(ValidateMemory, LoadRuntimeArrayInStruct) {
4634   const std::string spirv = R"(
4635 OpCapability Shader
4636 OpExtension "SPV_KHR_storage_buffer_storage_class"
4637 OpMemoryModel Logical GLSL450
4638 OpEntryPoint GLCompute %main "main"
4639 %void = OpTypeVoid
4640 %int = OpTypeInt 32 0
4641 %int_0 = OpConstant %int 0
4642 %rta = OpTypeRuntimeArray %int
4643 %block = OpTypeStruct %rta
4644 %ptr_rta = OpTypePointer StorageBuffer %rta
4645 %ptr_block = OpTypePointer StorageBuffer %block
4646 %var = OpVariable %ptr_block StorageBuffer
4647 %void_fn = OpTypeFunction %void
4648 %main = OpFunction %void None %void_fn
4649 %entry = OpLabel
4650 %ld = OpLoad %block %var
4651 OpReturn
4652 OpFunctionEnd
4653 )";
4654 
4655   CompileSuccessfully(spirv);
4656   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4657   EXPECT_THAT(getDiagnosticString(),
4658               HasSubstr("Cannot load a runtime-sized array"));
4659 }
4660 
TEST_F(ValidateMemory,LoadRuntimeArrayInArray)4661 TEST_F(ValidateMemory, LoadRuntimeArrayInArray) {
4662   const std::string spirv = R"(
4663 OpCapability Shader
4664 OpExtension "SPV_KHR_storage_buffer_storage_class"
4665 OpMemoryModel Logical GLSL450
4666 OpEntryPoint GLCompute %main "main"
4667 %void = OpTypeVoid
4668 %int = OpTypeInt 32 0
4669 %int_0 = OpConstant %int 0
4670 %int_4 = OpConstant %int 4
4671 %rta = OpTypeRuntimeArray %int
4672 %block = OpTypeStruct %rta
4673 %array = OpTypeArray %block %int_4
4674 %ptr_rta = OpTypePointer StorageBuffer %rta
4675 %ptr_block = OpTypePointer StorageBuffer %block
4676 %ptr_array = OpTypePointer StorageBuffer %array
4677 %var = OpVariable %ptr_array StorageBuffer
4678 %void_fn = OpTypeFunction %void
4679 %main = OpFunction %void None %void_fn
4680 %entry = OpLabel
4681 %ld = OpLoad %array %var
4682 OpReturn
4683 OpFunctionEnd
4684 )";
4685 
4686   CompileSuccessfully(spirv);
4687   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4688   EXPECT_THAT(getDiagnosticString(),
4689               HasSubstr("Cannot load a runtime-sized array"));
4690 }
4691 
TEST_F(ValidateMemory,Pre1p4WorkgroupMemoryBadLayoutOk)4692 TEST_F(ValidateMemory, Pre1p4WorkgroupMemoryBadLayoutOk) {
4693   const std::string spirv = R"(
4694 OpCapability Shader
4695 OpMemoryModel Logical GLSL450
4696 OpEntryPoint GLCompute %main "main"
4697 OpDecorate %struct Block
4698 OpMemberDecorate %struct 0 Offset 0
4699 %void = OpTypeVoid
4700 %bool = OpTypeBool
4701 %struct = OpTypeStruct %bool
4702 %ptr = OpTypePointer Workgroup %struct
4703 %var = OpVariable %ptr Workgroup
4704 %void_fn = OpTypeFunction %void
4705 %main = OpFunction %void None %void_fn
4706 %entry = OpLabel
4707 OpReturn
4708 OpFunctionEnd
4709 )";
4710 
4711   CompileSuccessfully(spirv);
4712   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4713 }
4714 
TEST_F(ValidateMemory,AccessChainNegativeStructIndex32)4715 TEST_F(ValidateMemory, AccessChainNegativeStructIndex32) {
4716   const std::string spirv = R"(
4717 OpCapability Shader
4718 OpCapability Linkage
4719 OpMemoryModel Logical GLSL450
4720 %void = OpTypeVoid
4721 %void_fn = OpTypeFunction %void
4722 %int = OpTypeInt 32 1
4723 %_struct_4 = OpTypeStruct %int %int %int
4724 %_ptr_Function__struct_4 = OpTypePointer Function %_struct_4
4725 %_ptr_Function_int = OpTypePointer Function %int
4726 %int_n224 = OpConstant %int -224
4727 %fn = OpFunction %void Inline %void_fn
4728 %entry = OpLabel
4729 %var = OpVariable %_ptr_Function__struct_4 Function
4730 %gep = OpInBoundsAccessChain %_ptr_Function_int %var %int_n224
4731 OpReturn
4732 OpFunctionEnd
4733 )";
4734 
4735   CompileSuccessfully(spirv);
4736   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4737   EXPECT_THAT(getDiagnosticString(), HasSubstr("Index is out of bounds"));
4738   EXPECT_THAT(getDiagnosticString(), HasSubstr("cannot find index -224"));
4739 }
4740 
TEST_F(ValidateMemory,AccessChainNegativeStructIndex64)4741 TEST_F(ValidateMemory, AccessChainNegativeStructIndex64) {
4742   const std::string spirv = R"(
4743 OpCapability Shader
4744 OpCapability Linkage
4745 OpCapability Int64
4746 OpMemoryModel Logical GLSL450
4747 %void = OpTypeVoid
4748 %void_fn = OpTypeFunction %void
4749 %int = OpTypeInt 32 1
4750 %long = OpTypeInt 64 1
4751 %_struct_4 = OpTypeStruct %int %int %int
4752 %_ptr_Function__struct_4 = OpTypePointer Function %_struct_4
4753 %_ptr_Function_int = OpTypePointer Function %int
4754 %long_n224 = OpConstant %long -224
4755 %fn = OpFunction %void Inline %void_fn
4756 %entry = OpLabel
4757 %var = OpVariable %_ptr_Function__struct_4 Function
4758 %gep = OpInBoundsAccessChain %_ptr_Function_int %var %long_n224
4759 OpReturn
4760 OpFunctionEnd
4761 )";
4762 
4763   CompileSuccessfully(spirv);
4764   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4765   EXPECT_THAT(getDiagnosticString(), HasSubstr("Index is out of bounds"));
4766   EXPECT_THAT(getDiagnosticString(), HasSubstr("cannot find index -224"));
4767 }
4768 
4769 
4770 }  // namespace
4771 }  // namespace val
4772 }  // namespace spvtools
4773