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