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