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