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