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