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