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_fixtures.h" 23 24 namespace spvtools { 25 namespace val { 26 namespace { 27 28 using ::testing::Eq; 29 using ::testing::HasSubstr; 30 31 using ValidateMemory = spvtest::ValidateBase<bool>; 32 33 TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceBad) { 34 std::string spirv = R"( 35 OpCapability Shader 36 OpMemoryModel Logical GLSL450 37 OpEntryPoint Fragment %func "func" 38 OpExecutionMode %func OriginUpperLeft 39 %float = OpTypeFloat 32 40 %float_ptr = OpTypePointer UniformConstant %float 41 %2 = OpVariable %float_ptr UniformConstant 42 %void = OpTypeVoid 43 %functy = OpTypeFunction %void 44 %func = OpFunction %void None %functy 45 %1 = OpLabel 46 OpReturn 47 OpFunctionEnd 48 )"; 49 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 50 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 51 EXPECT_THAT( 52 getDiagnosticString(), 53 HasSubstr("From Vulkan spec, section 14.5.2:\n" 54 "Variables identified with the UniformConstant storage class " 55 "are used only as handles to refer to opaque resources. Such " 56 "variables must be typed as OpTypeImage, OpTypeSampler, " 57 "OpTypeSampledImage, OpTypeAccelerationStructureNV, or an " 58 "array of one of these types.")); 59 } 60 61 TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceGood) { 62 std::string spirv = R"( 63 OpCapability Shader 64 OpMemoryModel Logical GLSL450 65 OpEntryPoint Fragment %func "func" 66 OpExecutionMode %func OriginUpperLeft 67 OpDecorate %2 DescriptorSet 0 68 OpDecorate %2 Binding 0 69 %sampler = OpTypeSampler 70 %sampler_ptr = OpTypePointer UniformConstant %sampler 71 %2 = OpVariable %sampler_ptr UniformConstant 72 %void = OpTypeVoid 73 %functy = OpTypeFunction %void 74 %func = OpFunction %void None %functy 75 %1 = OpLabel 76 OpReturn 77 OpFunctionEnd 78 )"; 79 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 80 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 81 } 82 83 TEST_F(ValidateMemory, VulkanUniformConstantOnNonOpaqueResourceArrayBad) { 84 std::string spirv = R"( 85 OpCapability Shader 86 OpMemoryModel Logical GLSL450 87 OpEntryPoint Fragment %func "func" 88 OpExecutionMode %func OriginUpperLeft 89 %float = OpTypeFloat 32 90 %uint = OpTypeInt 32 0 91 %array_size = OpConstant %uint 5 92 %array = OpTypeArray %float %array_size 93 %array_ptr = OpTypePointer UniformConstant %array 94 %2 = OpVariable %array_ptr UniformConstant 95 %void = OpTypeVoid 96 %functy = OpTypeFunction %void 97 %func = OpFunction %void None %functy 98 %1 = OpLabel 99 OpReturn 100 OpFunctionEnd 101 )"; 102 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 103 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 104 EXPECT_THAT( 105 getDiagnosticString(), 106 HasSubstr("From Vulkan spec, section 14.5.2:\n" 107 "Variables identified with the UniformConstant storage class " 108 "are used only as handles to refer to opaque resources. Such " 109 "variables must be typed as OpTypeImage, OpTypeSampler, " 110 "OpTypeSampledImage, OpTypeAccelerationStructureNV, or an " 111 "array of one of these types.")); 112 } 113 114 TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceArrayGood) { 115 std::string spirv = R"( 116 OpCapability Shader 117 OpMemoryModel Logical GLSL450 118 OpEntryPoint Fragment %func "func" 119 OpExecutionMode %func OriginUpperLeft 120 OpDecorate %2 DescriptorSet 0 121 OpDecorate %2 Binding 0 122 %sampler = OpTypeSampler 123 %uint = OpTypeInt 32 0 124 %array_size = OpConstant %uint 5 125 %array = OpTypeArray %sampler %array_size 126 %array_ptr = OpTypePointer UniformConstant %array 127 %2 = OpVariable %array_ptr UniformConstant 128 %void = OpTypeVoid 129 %functy = OpTypeFunction %void 130 %func = OpFunction %void None %functy 131 %1 = OpLabel 132 OpReturn 133 OpFunctionEnd 134 )"; 135 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 136 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 137 } 138 139 TEST_F(ValidateMemory, VulkanUniformConstantOnOpaqueResourceRuntimeArrayGood) { 140 std::string spirv = R"( 141 OpCapability Shader 142 OpMemoryModel Logical GLSL450 143 OpEntryPoint Fragment %func "func" 144 OpExecutionMode %func OriginUpperLeft 145 OpDecorate %2 DescriptorSet 0 146 OpDecorate %2 Binding 0 147 %sampler = OpTypeSampler 148 %uint = OpTypeInt 32 0 149 %array = OpTypeRuntimeArray %sampler 150 %array_ptr = OpTypePointer UniformConstant %array 151 %2 = OpVariable %array_ptr UniformConstant 152 %void = OpTypeVoid 153 %functy = OpTypeFunction %void 154 %func = OpFunction %void None %functy 155 %1 = OpLabel 156 OpReturn 157 OpFunctionEnd 158 )"; 159 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 160 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 161 } 162 163 TEST_F(ValidateMemory, VulkanUniformOnIntBad) { 164 char src[] = R"( 165 OpCapability Shader 166 OpMemoryModel Logical GLSL450 167 OpEntryPoint GLCompute %kernel "main" 168 OpExecutionMode %kernel LocalSize 1 1 1 169 170 OpDecorate %var DescriptorSet 0 171 OpDecorate %var Binding 0 172 173 %voidty = OpTypeVoid 174 %kernelty = OpTypeFunction %voidty 175 %intty = OpTypeInt 32 0 176 %varty = OpTypePointer Uniform %intty 177 %value = OpConstant %intty 42 178 179 %var = OpVariable %varty Uniform 180 181 %kernel = OpFunction %voidty None %kernelty 182 %label = OpLabel 183 OpStore %var %value 184 OpReturn 185 OpFunctionEnd 186 )"; 187 CompileSuccessfully(src, SPV_ENV_VULKAN_1_1); 188 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 189 EXPECT_THAT( 190 getDiagnosticString(), 191 HasSubstr("From Vulkan spec, section 14.5.2:\n" 192 "Variables identified with the Uniform storage class are used " 193 "to access transparent buffer backed resources. Such variables " 194 "must be typed as OpTypeStruct, or an array of this type")); 195 } 196 197 // #version 440 198 // #extension GL_EXT_nonuniform_qualifier : enable 199 // layout(binding = 1) uniform sampler2D s2d[][2]; 200 // layout(location = 0) in nonuniformEXT int i; 201 // void main() 202 // { 203 // vec4 v = texture(s2d[i][i], vec2(0.3)); 204 // } 205 TEST_F(ValidateMemory, VulkanUniformOnRuntimeArrayOfArrayBad) { 206 char src[] = R"( 207 OpCapability Shader 208 OpCapability ShaderNonUniformEXT 209 OpCapability RuntimeDescriptorArrayEXT 210 OpCapability SampledImageArrayNonUniformIndexingEXT 211 OpExtension "SPV_EXT_descriptor_indexing" 212 %1 = OpExtInstImport "GLSL.std.450" 213 OpMemoryModel Logical GLSL450 214 OpEntryPoint Vertex %main "main" %i 215 OpSource GLSL 440 216 OpSourceExtension "GL_EXT_nonuniform_qualifier" 217 OpName %main "main" 218 OpName %v "v" 219 OpName %s2d "s2d" 220 OpName %i "i" 221 OpDecorate %s2d DescriptorSet 0 222 OpDecorate %s2d Binding 1 223 OpDecorate %i Location 0 224 OpDecorate %i NonUniformEXT 225 OpDecorate %21 NonUniformEXT 226 OpDecorate %22 NonUniformEXT 227 OpDecorate %25 NonUniformEXT 228 %void = OpTypeVoid 229 %3 = OpTypeFunction %void 230 %float = OpTypeFloat 32 231 %v4float = OpTypeVector %float 4 232 %_ptr_Function_v4float = OpTypePointer Function %v4float 233 %10 = OpTypeImage %float 2D 0 0 0 1 Unknown 234 %11 = OpTypeSampledImage %10 235 %uint = OpTypeInt 32 0 236 %uint_2 = OpConstant %uint 2 237 %_arr_11_uint_2 = OpTypeArray %11 %uint_2 238 %_runtimearr__arr_11_uint_2 = OpTypeRuntimeArray %_arr_11_uint_2 239 %_ptr_Uniform__runtimearr__arr_11_uint_2 = OpTypePointer Uniform %_runtimearr__arr_11_uint_2 240 %s2d = OpVariable %_ptr_Uniform__runtimearr__arr_11_uint_2 Uniform 241 %int = OpTypeInt 32 1 242 %_ptr_Input_int = OpTypePointer Input %int 243 %i = OpVariable %_ptr_Input_int Input 244 %_ptr_Uniform_11 = OpTypePointer Uniform %11 245 %v2float = OpTypeVector %float 2 246 %float_0_300000012 = OpConstant %float 0.300000012 247 %28 = OpConstantComposite %v2float %float_0_300000012 %float_0_300000012 248 %float_0 = OpConstant %float 0 249 %main = OpFunction %void None %3 250 %5 = OpLabel 251 %v = OpVariable %_ptr_Function_v4float Function 252 %21 = OpLoad %int %i 253 %22 = OpLoad %int %i 254 %24 = OpAccessChain %_ptr_Uniform_11 %s2d %21 %22 255 %25 = OpLoad %11 %24 256 %30 = OpImageSampleExplicitLod %v4float %25 %28 Lod %float_0 257 OpStore %v %30 258 OpReturn 259 OpFunctionEnd 260 )"; 261 CompileSuccessfully(src, SPV_ENV_VULKAN_1_1); 262 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 263 EXPECT_THAT( 264 getDiagnosticString(), 265 HasSubstr("From Vulkan spec, section 14.5.2:\n" 266 "Variables identified with the Uniform storage class are used " 267 "to access transparent buffer backed resources. Such variables " 268 "must be typed as OpTypeStruct, or an array of this type")); 269 } 270 271 // #version 440 272 // layout (set=1, binding=1) uniform sampler2D variableName[2][2]; 273 // void main() { 274 // } 275 TEST_F(ValidateMemory, VulkanUniformOnArrayOfArrayBad) { 276 char src[] = R"( 277 OpCapability Shader 278 %1 = OpExtInstImport "GLSL.std.450" 279 OpMemoryModel Logical GLSL450 280 OpEntryPoint Vertex %main "main" 281 OpSource GLSL 440 282 OpName %main "main" 283 OpName %variableName "variableName" 284 OpDecorate %variableName DescriptorSet 1 285 OpDecorate %variableName Binding 1 286 %void = OpTypeVoid 287 %3 = OpTypeFunction %void 288 %float = OpTypeFloat 32 289 %7 = OpTypeImage %float 2D 0 0 0 1 Unknown 290 %8 = OpTypeSampledImage %7 291 %uint = OpTypeInt 32 0 292 %uint_2 = OpConstant %uint 2 293 %_arr_8_uint_2 = OpTypeArray %8 %uint_2 294 %_arr__arr_8_uint_2_uint_2 = OpTypeArray %_arr_8_uint_2 %uint_2 295 %_ptr_Uniform__arr__arr_8_uint_2_uint_2 = OpTypePointer Uniform %_arr__arr_8_uint_2_uint_2 296 %variableName = OpVariable %_ptr_Uniform__arr__arr_8_uint_2_uint_2 Uniform 297 %main = OpFunction %void None %3 298 %5 = OpLabel 299 OpReturn 300 OpFunctionEnd 301 )"; 302 CompileSuccessfully(src, SPV_ENV_VULKAN_1_1); 303 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 304 EXPECT_THAT( 305 getDiagnosticString(), 306 HasSubstr("From Vulkan spec, section 14.5.2:\n" 307 "Variables identified with the Uniform storage class are used " 308 "to access transparent buffer backed resources. Such variables " 309 "must be typed as OpTypeStruct, or an array of this type")); 310 } 311 312 TEST_F(ValidateMemory, MismatchingStorageClassesBad) { 313 std::string spirv = R"( 314 OpCapability Shader 315 OpMemoryModel Logical GLSL450 316 OpEntryPoint Fragment %func "func" 317 OpExecutionMode %func OriginUpperLeft 318 %float = OpTypeFloat 32 319 %float_ptr = OpTypePointer Uniform %float 320 %void = OpTypeVoid 321 %functy = OpTypeFunction %void 322 %func = OpFunction %void None %functy 323 %1 = OpLabel 324 %2 = OpVariable %float_ptr Function 325 OpReturn 326 OpFunctionEnd 327 )"; 328 CompileSuccessfully(spirv.c_str()); 329 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 330 EXPECT_THAT( 331 getDiagnosticString(), 332 HasSubstr( 333 "From SPIR-V spec, section 3.32.8 on OpVariable:\n" 334 "Its Storage Class operand must be the same as the Storage Class " 335 "operand of the result type.")); 336 } 337 338 TEST_F(ValidateMemory, MatchingStorageClassesGood) { 339 std::string spirv = R"( 340 OpCapability Shader 341 OpMemoryModel Logical GLSL450 342 OpEntryPoint Fragment %func "func" 343 OpExecutionMode %func OriginUpperLeft 344 %float = OpTypeFloat 32 345 %float_ptr = OpTypePointer Function %float 346 %void = OpTypeVoid 347 %functy = OpTypeFunction %void 348 %func = OpFunction %void None %functy 349 %1 = OpLabel 350 %2 = OpVariable %float_ptr Function 351 OpReturn 352 OpFunctionEnd 353 )"; 354 CompileSuccessfully(spirv.c_str()); 355 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 356 } 357 358 TEST_F(ValidateMemory, WebGPUInitializerWithOutputStorageClassesGood) { 359 std::string spirv = R"( 360 OpCapability Shader 361 OpCapability VulkanMemoryModelKHR 362 OpExtension "SPV_KHR_vulkan_memory_model" 363 OpMemoryModel Logical VulkanKHR 364 OpEntryPoint Fragment %func "func" 365 OpExecutionMode %func OriginUpperLeft 366 %float = OpTypeFloat 32 367 %float_ptr = OpTypePointer Output %float 368 %init_val = OpConstant %float 1.0 369 %1 = OpVariable %float_ptr Output %init_val 370 %void = OpTypeVoid 371 %functy = OpTypeFunction %void 372 %func = OpFunction %void None %functy 373 %2 = OpLabel 374 OpReturn 375 OpFunctionEnd 376 )"; 377 CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); 378 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); 379 } 380 381 TEST_F(ValidateMemory, WebGPUInitializerWithFunctionStorageClassesGood) { 382 std::string spirv = R"( 383 OpCapability Shader 384 OpCapability VulkanMemoryModelKHR 385 OpExtension "SPV_KHR_vulkan_memory_model" 386 OpMemoryModel Logical VulkanKHR 387 OpEntryPoint Fragment %func "func" 388 OpExecutionMode %func OriginUpperLeft 389 %float = OpTypeFloat 32 390 %float_ptr = OpTypePointer Function %float 391 %init_val = OpConstant %float 1.0 392 %void = OpTypeVoid 393 %functy = OpTypeFunction %void 394 %func = OpFunction %void None %functy 395 %1 = OpLabel 396 %2 = OpVariable %float_ptr Function %init_val 397 OpReturn 398 OpFunctionEnd 399 )"; 400 CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); 401 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); 402 } 403 404 TEST_F(ValidateMemory, WebGPUInitializerWithPrivateStorageClassesGood) { 405 std::string spirv = R"( 406 OpCapability Shader 407 OpCapability VulkanMemoryModelKHR 408 OpExtension "SPV_KHR_vulkan_memory_model" 409 OpMemoryModel Logical VulkanKHR 410 OpEntryPoint Fragment %func "func" 411 OpExecutionMode %func OriginUpperLeft 412 %float = OpTypeFloat 32 413 %float_ptr = OpTypePointer Private %float 414 %init_val = OpConstant %float 1.0 415 %1 = OpVariable %float_ptr Private %init_val 416 %void = OpTypeVoid 417 %functy = OpTypeFunction %void 418 %func = OpFunction %void None %functy 419 %2 = OpLabel 420 OpReturn 421 OpFunctionEnd 422 )"; 423 CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); 424 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_WEBGPU_0)); 425 } 426 427 TEST_F(ValidateMemory, WebGPUInitializerWithDisallowedStorageClassesBad) { 428 std::string spirv = R"( 429 OpCapability Shader 430 OpCapability VulkanMemoryModelKHR 431 OpExtension "SPV_KHR_vulkan_memory_model" 432 OpMemoryModel Logical VulkanKHR 433 OpEntryPoint Fragment %func "func" 434 OpExecutionMode %func OriginUpperLeft 435 %float = OpTypeFloat 32 436 %float_ptr = OpTypePointer Uniform %float 437 %init_val = OpConstant %float 1.0 438 %1 = OpVariable %float_ptr Uniform %init_val 439 %void = OpTypeVoid 440 %functy = OpTypeFunction %void 441 %func = OpFunction %void None %functy 442 %2 = OpLabel 443 OpReturn 444 OpFunctionEnd 445 )"; 446 CompileSuccessfully(spirv.c_str(), SPV_ENV_WEBGPU_0); 447 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_WEBGPU_0)); 448 EXPECT_THAT( 449 getDiagnosticString(), 450 HasSubstr( 451 "OpVariable, <id> '5[%5]', has a disallowed initializer & storage " 452 "class combination.\nFrom WebGPU execution environment spec:\n" 453 "Variable declarations that include initializers must have one of " 454 "the following storage classes: Output, Private, or Function\n" 455 " %5 = OpVariable %_ptr_Uniform_float Uniform %float_1\n")); 456 } 457 458 TEST_F(ValidateMemory, VulkanInitializerWithOutputStorageClassesGood) { 459 std::string spirv = R"( 460 OpCapability Shader 461 OpMemoryModel Logical GLSL450 462 OpEntryPoint Fragment %func "func" 463 OpExecutionMode %func OriginUpperLeft 464 %float = OpTypeFloat 32 465 %float_ptr = OpTypePointer Output %float 466 %init_val = OpConstant %float 1.0 467 %1 = OpVariable %float_ptr Output %init_val 468 %void = OpTypeVoid 469 %functy = OpTypeFunction %void 470 %func = OpFunction %void None %functy 471 %2 = OpLabel 472 OpReturn 473 OpFunctionEnd 474 )"; 475 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 476 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 477 } 478 479 TEST_F(ValidateMemory, VulkanInitializerWithFunctionStorageClassesGood) { 480 std::string spirv = R"( 481 OpCapability Shader 482 OpMemoryModel Logical GLSL450 483 OpEntryPoint Fragment %func "func" 484 OpExecutionMode %func OriginUpperLeft 485 %float = OpTypeFloat 32 486 %float_ptr = OpTypePointer Function %float 487 %init_val = OpConstant %float 1.0 488 %void = OpTypeVoid 489 %functy = OpTypeFunction %void 490 %func = OpFunction %void None %functy 491 %1 = OpLabel 492 %2 = OpVariable %float_ptr Function %init_val 493 OpReturn 494 OpFunctionEnd 495 )"; 496 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 497 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 498 } 499 500 TEST_F(ValidateMemory, VulkanInitializerWithPrivateStorageClassesGood) { 501 std::string spirv = R"( 502 OpCapability Shader 503 OpMemoryModel Logical GLSL450 504 OpEntryPoint Fragment %func "func" 505 OpExecutionMode %func OriginUpperLeft 506 %float = OpTypeFloat 32 507 %float_ptr = OpTypePointer Private %float 508 %init_val = OpConstant %float 1.0 509 %1 = OpVariable %float_ptr Private %init_val 510 %void = OpTypeVoid 511 %functy = OpTypeFunction %void 512 %func = OpFunction %void None %functy 513 %2 = OpLabel 514 OpReturn 515 OpFunctionEnd 516 )"; 517 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 518 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 519 } 520 521 TEST_F(ValidateMemory, VulkanInitializerWithDisallowedStorageClassesBad) { 522 std::string spirv = R"( 523 OpCapability Shader 524 OpMemoryModel Logical GLSL450 525 OpEntryPoint Fragment %func "func" 526 OpExecutionMode %func OriginUpperLeft 527 %float = OpTypeFloat 32 528 %float_ptr = OpTypePointer Input %float 529 %init_val = OpConstant %float 1.0 530 %1 = OpVariable %float_ptr Input %init_val 531 %void = OpTypeVoid 532 %functy = OpTypeFunction %void 533 %func = OpFunction %void None %functy 534 %2 = OpLabel 535 OpReturn 536 OpFunctionEnd 537 )"; 538 CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_1); 539 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 540 EXPECT_THAT( 541 getDiagnosticString(), 542 HasSubstr( 543 "OpVariable, <id> '5[%5]', has a disallowed initializer & storage " 544 "class combination.\nFrom Vulkan spec, Appendix A:\n" 545 "Variable declarations that include initializers must have one of " 546 "the following storage classes: Output, Private, or Function\n " 547 "%5 = OpVariable %_ptr_Input_float Input %float_1\n")); 548 } 549 550 TEST_F(ValidateMemory, ArrayLenCorrectResultType) { 551 std::string spirv = R"( 552 OpCapability Shader 553 OpMemoryModel Logical GLSL450 554 OpEntryPoint Fragment %1 "main" 555 OpExecutionMode %1 OriginUpperLeft 556 %void = OpTypeVoid 557 %3 = OpTypeFunction %void 558 %float = OpTypeFloat 32 559 %uint = OpTypeInt 32 0 560 %_runtimearr_float = OpTypeRuntimeArray %float 561 %_struct_7 = OpTypeStruct %_runtimearr_float 562 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 563 %1 = OpFunction %void None %3 564 %9 = OpLabel 565 %10 = OpVariable %_ptr_Function__struct_7 Function 566 %11 = OpArrayLength %uint %10 0 567 OpReturn 568 OpFunctionEnd 569 570 )"; 571 572 CompileSuccessfully(spirv.c_str()); 573 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 574 } 575 576 TEST_F(ValidateMemory, ArrayLenIndexCorrectWith2Members) { 577 std::string spirv = R"( 578 OpCapability Shader 579 OpMemoryModel Logical GLSL450 580 OpEntryPoint Fragment %1 "main" 581 OpExecutionMode %1 OriginUpperLeft 582 %void = OpTypeVoid 583 %3 = OpTypeFunction %void 584 %float = OpTypeFloat 32 585 %uint = OpTypeInt 32 0 586 %_runtimearr_float = OpTypeRuntimeArray %float 587 %_struct_7 = OpTypeStruct %float %_runtimearr_float 588 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 589 %1 = OpFunction %void None %3 590 %9 = OpLabel 591 %10 = OpVariable %_ptr_Function__struct_7 Function 592 %11 = OpArrayLength %uint %10 1 593 OpReturn 594 OpFunctionEnd 595 596 )"; 597 598 CompileSuccessfully(spirv.c_str()); 599 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 600 } 601 602 TEST_F(ValidateMemory, ArrayLenResultNotIntType) { 603 std::string spirv = R"( 604 OpCapability Shader 605 OpMemoryModel Logical GLSL450 606 OpEntryPoint Fragment %1 "main" 607 OpExecutionMode %1 OriginUpperLeft 608 %void = OpTypeVoid 609 %3 = OpTypeFunction %void 610 %float = OpTypeFloat 32 611 %_runtimearr_float = OpTypeRuntimeArray %float 612 %_struct_6 = OpTypeStruct %_runtimearr_float 613 %_ptr_Function__struct_6 = OpTypePointer Function %_struct_6 614 %1 = OpFunction %void None %3 615 %8 = OpLabel 616 %9 = OpVariable %_ptr_Function__struct_6 Function 617 %10 = OpArrayLength %float %9 0 618 OpReturn 619 OpFunctionEnd 620 )"; 621 622 CompileSuccessfully(spirv.c_str()); 623 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 624 EXPECT_THAT( 625 getDiagnosticString(), 626 HasSubstr( 627 "The Result Type of OpArrayLength <id> '10[%10]' must be OpTypeInt " 628 "with width 32 and signedness 0.\n %10 = OpArrayLength %float %9 " 629 "0\n")); 630 } 631 632 TEST_F(ValidateMemory, ArrayLenResultNot32bits) { 633 std::string spirv = R"( 634 OpCapability Shader 635 OpCapability Int16 636 OpMemoryModel Logical GLSL450 637 OpEntryPoint Fragment %1 "main" 638 OpExecutionMode %1 OriginUpperLeft 639 %void = OpTypeVoid 640 %3 = OpTypeFunction %void 641 %float = OpTypeFloat 32 642 %ushort = OpTypeInt 16 0 643 %_runtimearr_float = OpTypeRuntimeArray %float 644 %_struct_7 = OpTypeStruct %_runtimearr_float 645 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 646 %1 = OpFunction %void None %3 647 %9 = OpLabel 648 %10 = OpVariable %_ptr_Function__struct_7 Function 649 %11 = OpArrayLength %ushort %10 0 650 OpReturn 651 OpFunctionEnd 652 653 )"; 654 655 CompileSuccessfully(spirv.c_str()); 656 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 657 EXPECT_THAT( 658 getDiagnosticString(), 659 HasSubstr( 660 "The Result Type of OpArrayLength <id> '11[%11]' must be OpTypeInt " 661 "with width 32 and signedness 0.\n %11 = OpArrayLength %ushort %10 " 662 "0\n")); 663 } 664 665 TEST_F(ValidateMemory, ArrayLenResultSigned) { 666 std::string spirv = R"( 667 OpCapability Shader 668 OpMemoryModel Logical GLSL450 669 OpEntryPoint Fragment %1 "main" 670 OpExecutionMode %1 OriginUpperLeft 671 %void = OpTypeVoid 672 %3 = OpTypeFunction %void 673 %float = OpTypeFloat 32 674 %int = OpTypeInt 32 1 675 %_runtimearr_float = OpTypeRuntimeArray %float 676 %_struct_7 = OpTypeStruct %_runtimearr_float 677 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 678 %1 = OpFunction %void None %3 679 %9 = OpLabel 680 %10 = OpVariable %_ptr_Function__struct_7 Function 681 %11 = OpArrayLength %int %10 0 682 OpReturn 683 OpFunctionEnd 684 685 )"; 686 687 CompileSuccessfully(spirv.c_str()); 688 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 689 EXPECT_THAT( 690 getDiagnosticString(), 691 HasSubstr( 692 "The Result Type of OpArrayLength <id> '11[%11]' must be OpTypeInt " 693 "with width 32 and signedness 0.\n %11 = OpArrayLength %int %10 " 694 "0\n")); 695 } 696 697 TEST_F(ValidateMemory, ArrayLenInputNotStruct) { 698 std::string spirv = R"( 699 OpCapability Shader 700 OpMemoryModel Logical GLSL450 701 OpEntryPoint Fragment %1 "main" 702 OpExecutionMode %1 OriginUpperLeft 703 %void = OpTypeVoid 704 %3 = OpTypeFunction %void 705 %float = OpTypeFloat 32 706 %uint = OpTypeInt 32 0 707 %_runtimearr_float = OpTypeRuntimeArray %float 708 %_struct_7 = OpTypeStruct %_runtimearr_float 709 %_ptr_Function_float = OpTypePointer Function %float 710 %1 = OpFunction %void None %3 711 %9 = OpLabel 712 %10 = OpVariable %_ptr_Function_float Function 713 %11 = OpArrayLength %uint %10 0 714 OpReturn 715 OpFunctionEnd 716 717 )"; 718 719 CompileSuccessfully(spirv.c_str()); 720 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 721 EXPECT_THAT(getDiagnosticString(), 722 HasSubstr("The Struture's type in OpArrayLength <id> '11[%11]' " 723 "must be a pointer to an OpTypeStruct.")); 724 } 725 726 TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA) { 727 std::string spirv = R"( 728 OpCapability Shader 729 OpMemoryModel Logical GLSL450 730 OpEntryPoint Fragment %1 "main" 731 OpExecutionMode %1 OriginUpperLeft 732 %void = OpTypeVoid 733 %3 = OpTypeFunction %void 734 %float = OpTypeFloat 32 735 %uint = OpTypeInt 32 0 736 %_runtimearr_float = OpTypeRuntimeArray %float 737 %_struct_7 = OpTypeStruct %float 738 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 739 %1 = OpFunction %void None %3 740 %9 = OpLabel 741 %10 = OpVariable %_ptr_Function__struct_7 Function 742 %11 = OpArrayLength %uint %10 0 743 OpReturn 744 OpFunctionEnd 745 746 )"; 747 748 CompileSuccessfully(spirv.c_str()); 749 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 750 EXPECT_THAT( 751 getDiagnosticString(), 752 HasSubstr("The Struture's last member in OpArrayLength <id> '11[%11]' " 753 "must be an OpTypeRuntimeArray.\n %11 = OpArrayLength %uint " 754 "%10 0\n")); 755 } 756 757 TEST_F(ValidateMemory, ArrayLenInputLastMemberNoRTA2) { 758 std::string spirv = R"( 759 OpCapability Shader 760 OpMemoryModel Logical GLSL450 761 OpEntryPoint Fragment %1 "main" 762 OpExecutionMode %1 OriginUpperLeft 763 %void = OpTypeVoid 764 %3 = OpTypeFunction %void 765 %float = OpTypeFloat 32 766 %uint = OpTypeInt 32 0 767 %_runtimearr_float = OpTypeRuntimeArray %float 768 %_struct_7 = OpTypeStruct %_runtimearr_float %float 769 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 770 %1 = OpFunction %void None %3 771 %9 = OpLabel 772 %10 = OpVariable %_ptr_Function__struct_7 Function 773 %11 = OpArrayLength %uint %10 1 774 OpReturn 775 OpFunctionEnd 776 777 )"; 778 779 CompileSuccessfully(spirv.c_str()); 780 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 781 EXPECT_THAT( 782 getDiagnosticString(), 783 HasSubstr("The Struture's last member in OpArrayLength <id> '11[%11]' " 784 "must be an OpTypeRuntimeArray.\n %11 = OpArrayLength %uint " 785 "%10 1\n")); 786 } 787 788 TEST_F(ValidateMemory, ArrayLenIndexNotLastMember) { 789 std::string spirv = R"( 790 OpCapability Shader 791 OpMemoryModel Logical GLSL450 792 OpEntryPoint Fragment %1 "main" 793 OpExecutionMode %1 OriginUpperLeft 794 %void = OpTypeVoid 795 %3 = OpTypeFunction %void 796 %float = OpTypeFloat 32 797 %uint = OpTypeInt 32 0 798 %_runtimearr_float = OpTypeRuntimeArray %float 799 %_struct_7 = OpTypeStruct %float %_runtimearr_float 800 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 801 %1 = OpFunction %void None %3 802 %9 = OpLabel 803 %10 = OpVariable %_ptr_Function__struct_7 Function 804 %11 = OpArrayLength %uint %10 0 805 OpReturn 806 OpFunctionEnd 807 808 )"; 809 810 CompileSuccessfully(spirv.c_str()); 811 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 812 EXPECT_THAT( 813 getDiagnosticString(), 814 HasSubstr( 815 "The array member in OpArrayLength <id> '11[%11]' must be an the " 816 "last member of the struct.\n %11 = OpArrayLength %uint %10 0\n")); 817 } 818 819 TEST_F(ValidateMemory, ArrayLenIndexNotPointerToStruct) { 820 std::string spirv = R"( 821 OpCapability Shader 822 OpMemoryModel Logical GLSL450 823 OpEntryPoint Fragment %1 "main" 824 OpExecutionMode %1 OriginUpperLeft 825 %void = OpTypeVoid 826 %3 = OpTypeFunction %void 827 %float = OpTypeFloat 32 828 %uint = OpTypeInt 32 0 829 %_runtimearr_float = OpTypeRuntimeArray %float 830 %_struct_7 = OpTypeStruct %float %_runtimearr_float 831 %_ptr_Function__struct_7 = OpTypePointer Function %_struct_7 832 %1 = OpFunction %void None %3 833 %9 = OpLabel 834 %10 = OpVariable %_ptr_Function__struct_7 Function 835 %11 = OpLoad %_struct_7 %10 836 %12 = OpArrayLength %uint %11 0 837 OpReturn 838 OpFunctionEnd 839 840 )"; 841 842 CompileSuccessfully(spirv.c_str()); 843 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 844 EXPECT_THAT( 845 getDiagnosticString(), 846 HasSubstr( 847 "The Struture's type in OpArrayLength <id> '12[%12]' must be a " 848 "pointer to an OpTypeStruct.\n %12 = OpArrayLength %uint %11 0\n")); 849 } 850 851 TEST_F(ValidateMemory, ArrayLenPointerIsAType) { 852 std::string spirv = R"( 853 OpCapability Shader 854 OpMemoryModel Logical GLSL450 855 OpEntryPoint Fragment %1 "main" 856 OpExecutionMode %1 OriginUpperLeft 857 %void = OpTypeVoid 858 %3 = OpTypeFunction %void 859 %float = OpTypeFloat 32 860 %uint = OpTypeInt 32 0 861 %1 = OpFunction %void None %3 862 %9 = OpLabel 863 %12 = OpArrayLength %uint %float 0 864 OpReturn 865 OpFunctionEnd 866 867 )"; 868 869 CompileSuccessfully(spirv.c_str()); 870 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 871 EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 4[%float] cannot be a " 872 "type")); 873 } 874 875 TEST_F(ValidateMemory, PushConstantNotStructGood) { 876 std::string spirv = R"( 877 OpCapability Shader 878 OpMemoryModel Logical GLSL450 879 OpEntryPoint Fragment %1 "main" 880 OpExecutionMode %1 OriginUpperLeft 881 882 %void = OpTypeVoid 883 %voidfn = OpTypeFunction %void 884 %float = OpTypeFloat 32 885 %ptr = OpTypePointer PushConstant %float 886 %pc = OpVariable %ptr PushConstant 887 888 %1 = OpFunction %void None %voidfn 889 %label = OpLabel 890 OpReturn 891 OpFunctionEnd 892 )"; 893 CompileSuccessfully(spirv); 894 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 895 } 896 897 TEST_F(ValidateMemory, VulkanPushConstantNotStructBad) { 898 std::string spirv = R"( 899 OpCapability Shader 900 OpMemoryModel Logical GLSL450 901 OpEntryPoint Fragment %1 "main" 902 OpExecutionMode %1 OriginUpperLeft 903 904 %void = OpTypeVoid 905 %voidfn = OpTypeFunction %void 906 %float = OpTypeFloat 32 907 %ptr = OpTypePointer PushConstant %float 908 %pc = OpVariable %ptr PushConstant 909 910 %1 = OpFunction %void None %voidfn 911 %label = OpLabel 912 OpReturn 913 OpFunctionEnd 914 )"; 915 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); 916 EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 917 EXPECT_THAT(getDiagnosticString(), 918 HasSubstr("PushConstant OpVariable <id> '6[%6]' has illegal " 919 "type.\nFrom Vulkan spec, section 14.5.1:\n" 920 "Such variables must be typed as OpTypeStruct, " 921 "or an array of this type")); 922 } 923 924 TEST_F(ValidateMemory, VulkanPushConstant) { 925 std::string spirv = R"( 926 OpCapability Shader 927 OpMemoryModel Logical GLSL450 928 OpEntryPoint Fragment %1 "main" 929 OpExecutionMode %1 OriginUpperLeft 930 931 OpDecorate %struct Block 932 OpMemberDecorate %struct 0 Offset 0 933 934 %void = OpTypeVoid 935 %voidfn = OpTypeFunction %void 936 %float = OpTypeFloat 32 937 %struct = OpTypeStruct %float 938 %ptr = OpTypePointer PushConstant %struct 939 %pc = OpVariable %ptr PushConstant 940 941 %1 = OpFunction %void None %voidfn 942 %label = OpLabel 943 OpReturn 944 OpFunctionEnd 945 )"; 946 CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1); 947 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_VULKAN_1_1)); 948 } 949 950 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad1) { 951 const std::string spirv = R"( 952 OpCapability Shader 953 OpCapability VulkanMemoryModelKHR 954 OpCapability Linkage 955 OpExtension "SPV_KHR_vulkan_memory_model" 956 OpMemoryModel Logical VulkanKHR 957 %void = OpTypeVoid 958 %int = OpTypeInt 32 0 959 %device = OpConstant %int 1 960 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 961 %var = OpVariable %int_ptr_ssbo StorageBuffer 962 %voidfn = OpTypeFunction %void 963 %func = OpFunction %void None %voidfn 964 %entry = OpLabel 965 %load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device 966 OpReturn 967 OpFunctionEnd 968 )"; 969 970 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 971 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 972 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 973 EXPECT_THAT( 974 getDiagnosticString(), 975 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 976 "VulkanMemoryModelDeviceScopeKHR capability")); 977 } 978 979 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadBad2) { 980 const std::string spirv = R"( 981 OpCapability Shader 982 OpCapability VulkanMemoryModelKHR 983 OpCapability Linkage 984 OpExtension "SPV_KHR_vulkan_memory_model" 985 OpMemoryModel Logical VulkanKHR 986 %void = OpTypeVoid 987 %int = OpTypeInt 32 0 988 %device = OpConstant %int 1 989 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 990 %var = OpVariable %int_ptr_ssbo StorageBuffer 991 %voidfn = OpTypeFunction %void 992 %func = OpFunction %void None %voidfn 993 %entry = OpLabel 994 %load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device 995 OpReturn 996 OpFunctionEnd 997 )"; 998 999 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1000 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1001 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1002 EXPECT_THAT( 1003 getDiagnosticString(), 1004 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1005 "VulkanMemoryModelDeviceScopeKHR capability")); 1006 } 1007 1008 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood1) { 1009 const std::string spirv = R"( 1010 OpCapability Shader 1011 OpCapability VulkanMemoryModelKHR 1012 OpCapability VulkanMemoryModelDeviceScopeKHR 1013 OpCapability Linkage 1014 OpExtension "SPV_KHR_vulkan_memory_model" 1015 OpMemoryModel Logical VulkanKHR 1016 %void = OpTypeVoid 1017 %int = OpTypeInt 32 0 1018 %device = OpConstant %int 1 1019 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1020 %var = OpVariable %int_ptr_ssbo StorageBuffer 1021 %voidfn = OpTypeFunction %void 1022 %func = OpFunction %void None %voidfn 1023 %entry = OpLabel 1024 %load = OpLoad %int %var MakePointerVisibleKHR|NonPrivatePointerKHR %device 1025 OpReturn 1026 OpFunctionEnd 1027 )"; 1028 1029 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1030 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1031 } 1032 1033 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeLoadGood2) { 1034 const std::string spirv = R"( 1035 OpCapability Shader 1036 OpCapability VulkanMemoryModelKHR 1037 OpCapability VulkanMemoryModelDeviceScopeKHR 1038 OpCapability Linkage 1039 OpExtension "SPV_KHR_vulkan_memory_model" 1040 OpMemoryModel Logical VulkanKHR 1041 %void = OpTypeVoid 1042 %int = OpTypeInt 32 0 1043 %device = OpConstant %int 1 1044 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1045 %var = OpVariable %int_ptr_ssbo StorageBuffer 1046 %voidfn = OpTypeFunction %void 1047 %func = OpFunction %void None %voidfn 1048 %entry = OpLabel 1049 %load = OpLoad %int %var Aligned|MakePointerVisibleKHR|NonPrivatePointerKHR 4 %device 1050 OpReturn 1051 OpFunctionEnd 1052 )"; 1053 1054 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1055 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1056 } 1057 1058 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad1) { 1059 const std::string spirv = R"( 1060 OpCapability Shader 1061 OpCapability VulkanMemoryModelKHR 1062 OpCapability Linkage 1063 OpExtension "SPV_KHR_vulkan_memory_model" 1064 OpMemoryModel Logical VulkanKHR 1065 %void = OpTypeVoid 1066 %int = OpTypeInt 32 0 1067 %device = OpConstant %int 1 1068 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1069 %var = OpVariable %int_ptr_ssbo StorageBuffer 1070 %voidfn = OpTypeFunction %void 1071 %func = OpFunction %void None %voidfn 1072 %entry = OpLabel 1073 OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device 1074 OpReturn 1075 OpFunctionEnd 1076 )"; 1077 1078 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1079 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1080 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1081 EXPECT_THAT( 1082 getDiagnosticString(), 1083 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1084 "VulkanMemoryModelDeviceScopeKHR capability")); 1085 } 1086 1087 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreBad2) { 1088 const std::string spirv = R"( 1089 OpCapability Shader 1090 OpCapability VulkanMemoryModelKHR 1091 OpCapability Linkage 1092 OpExtension "SPV_KHR_vulkan_memory_model" 1093 OpMemoryModel Logical VulkanKHR 1094 %void = OpTypeVoid 1095 %int = OpTypeInt 32 0 1096 %device = OpConstant %int 1 1097 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1098 %var = OpVariable %int_ptr_ssbo StorageBuffer 1099 %voidfn = OpTypeFunction %void 1100 %func = OpFunction %void None %voidfn 1101 %entry = OpLabel 1102 OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device 1103 OpReturn 1104 OpFunctionEnd 1105 )"; 1106 1107 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1108 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1109 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1110 EXPECT_THAT( 1111 getDiagnosticString(), 1112 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1113 "VulkanMemoryModelDeviceScopeKHR capability")); 1114 } 1115 1116 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood1) { 1117 const std::string spirv = R"( 1118 OpCapability Shader 1119 OpCapability VulkanMemoryModelKHR 1120 OpCapability VulkanMemoryModelDeviceScopeKHR 1121 OpCapability Linkage 1122 OpExtension "SPV_KHR_vulkan_memory_model" 1123 OpMemoryModel Logical VulkanKHR 1124 %void = OpTypeVoid 1125 %int = OpTypeInt 32 0 1126 %device = OpConstant %int 1 1127 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1128 %var = OpVariable %int_ptr_ssbo StorageBuffer 1129 %voidfn = OpTypeFunction %void 1130 %func = OpFunction %void None %voidfn 1131 %entry = OpLabel 1132 OpStore %var %device MakePointerAvailableKHR|NonPrivatePointerKHR %device 1133 OpReturn 1134 OpFunctionEnd 1135 )"; 1136 1137 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1138 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1139 } 1140 1141 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeStoreGood2) { 1142 const std::string spirv = R"( 1143 OpCapability Shader 1144 OpCapability VulkanMemoryModelKHR 1145 OpCapability VulkanMemoryModelDeviceScopeKHR 1146 OpCapability Linkage 1147 OpExtension "SPV_KHR_vulkan_memory_model" 1148 OpMemoryModel Logical VulkanKHR 1149 %void = OpTypeVoid 1150 %int = OpTypeInt 32 0 1151 %device = OpConstant %int 1 1152 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1153 %var = OpVariable %int_ptr_ssbo StorageBuffer 1154 %voidfn = OpTypeFunction %void 1155 %func = OpFunction %void None %voidfn 1156 %entry = OpLabel 1157 OpStore %var %device Aligned|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device 1158 OpReturn 1159 OpFunctionEnd 1160 )"; 1161 1162 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1163 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1164 } 1165 1166 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad1) { 1167 const std::string spirv = R"( 1168 OpCapability Shader 1169 OpCapability VulkanMemoryModelKHR 1170 OpCapability Linkage 1171 OpExtension "SPV_KHR_vulkan_memory_model" 1172 OpMemoryModel Logical VulkanKHR 1173 %void = OpTypeVoid 1174 %int = OpTypeInt 32 0 1175 %device = OpConstant %int 1 1176 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1177 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1178 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1179 %voidfn = OpTypeFunction %void 1180 %func = OpFunction %void None %voidfn 1181 %entry = OpLabel 1182 OpCopyMemory %var1 %var2 MakePointerAvailableKHR|NonPrivatePointerKHR %device 1183 OpReturn 1184 OpFunctionEnd 1185 )"; 1186 1187 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1188 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1189 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1190 EXPECT_THAT( 1191 getDiagnosticString(), 1192 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1193 "VulkanMemoryModelDeviceScopeKHR capability")); 1194 } 1195 1196 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad2) { 1197 const std::string spirv = R"( 1198 OpCapability Shader 1199 OpCapability VulkanMemoryModelKHR 1200 OpCapability Linkage 1201 OpExtension "SPV_KHR_vulkan_memory_model" 1202 OpMemoryModel Logical VulkanKHR 1203 %void = OpTypeVoid 1204 %int = OpTypeInt 32 0 1205 %device = OpConstant %int 1 1206 %workgroup = OpConstant %int 1 1207 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1208 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1209 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1210 %voidfn = OpTypeFunction %void 1211 %func = OpFunction %void None %voidfn 1212 %entry = OpLabel 1213 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup 1214 OpReturn 1215 OpFunctionEnd 1216 )"; 1217 1218 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1219 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1220 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1221 EXPECT_THAT( 1222 getDiagnosticString(), 1223 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1224 "VulkanMemoryModelDeviceScopeKHR capability")); 1225 } 1226 1227 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryBad3) { 1228 const std::string spirv = R"( 1229 OpCapability Shader 1230 OpCapability VulkanMemoryModelKHR 1231 OpCapability Linkage 1232 OpExtension "SPV_KHR_vulkan_memory_model" 1233 OpMemoryModel Logical VulkanKHR 1234 %void = OpTypeVoid 1235 %int = OpTypeInt 32 0 1236 %device = OpConstant %int 1 1237 %workgroup = OpConstant %int 1 1238 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1239 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1240 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1241 %voidfn = OpTypeFunction %void 1242 %func = OpFunction %void None %voidfn 1243 %entry = OpLabel 1244 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device 1245 OpReturn 1246 OpFunctionEnd 1247 )"; 1248 1249 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1250 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1251 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1252 EXPECT_THAT( 1253 getDiagnosticString(), 1254 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1255 "VulkanMemoryModelDeviceScopeKHR capability")); 1256 } 1257 1258 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood1) { 1259 const std::string spirv = R"( 1260 OpCapability Shader 1261 OpCapability VulkanMemoryModelKHR 1262 OpCapability VulkanMemoryModelDeviceScopeKHR 1263 OpCapability Linkage 1264 OpExtension "SPV_KHR_vulkan_memory_model" 1265 OpMemoryModel Logical VulkanKHR 1266 %void = OpTypeVoid 1267 %int = OpTypeInt 32 0 1268 %device = OpConstant %int 1 1269 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1270 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1271 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1272 %voidfn = OpTypeFunction %void 1273 %func = OpFunction %void None %voidfn 1274 %entry = OpLabel 1275 OpCopyMemory %var1 %var2 MakePointerAvailableKHR|NonPrivatePointerKHR %device 1276 OpReturn 1277 OpFunctionEnd 1278 )"; 1279 1280 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1281 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1282 } 1283 1284 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood2) { 1285 const std::string spirv = R"( 1286 OpCapability Shader 1287 OpCapability VulkanMemoryModelKHR 1288 OpCapability VulkanMemoryModelDeviceScopeKHR 1289 OpCapability Linkage 1290 OpExtension "SPV_KHR_vulkan_memory_model" 1291 OpMemoryModel Logical VulkanKHR 1292 %void = OpTypeVoid 1293 %int = OpTypeInt 32 0 1294 %device = OpConstant %int 1 1295 %workgroup = OpConstant %int 2 1296 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1297 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1298 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1299 %voidfn = OpTypeFunction %void 1300 %func = OpFunction %void None %voidfn 1301 %entry = OpLabel 1302 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup 1303 OpReturn 1304 OpFunctionEnd 1305 )"; 1306 1307 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1308 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1309 } 1310 1311 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemoryGood3) { 1312 const std::string spirv = R"( 1313 OpCapability Shader 1314 OpCapability VulkanMemoryModelKHR 1315 OpCapability VulkanMemoryModelDeviceScopeKHR 1316 OpCapability Linkage 1317 OpExtension "SPV_KHR_vulkan_memory_model" 1318 OpMemoryModel Logical VulkanKHR 1319 %void = OpTypeVoid 1320 %int = OpTypeInt 32 0 1321 %device = OpConstant %int 1 1322 %workgroup = OpConstant %int 2 1323 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1324 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1325 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1326 %voidfn = OpTypeFunction %void 1327 %func = OpFunction %void None %voidfn 1328 %entry = OpLabel 1329 OpCopyMemory %var1 %var2 Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device 1330 OpReturn 1331 OpFunctionEnd 1332 )"; 1333 1334 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1335 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1336 } 1337 1338 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad1) { 1339 const std::string spirv = R"( 1340 OpCapability Shader 1341 OpCapability VulkanMemoryModelKHR 1342 OpCapability Linkage 1343 OpCapability Addresses 1344 OpExtension "SPV_KHR_vulkan_memory_model" 1345 OpMemoryModel Logical VulkanKHR 1346 %void = OpTypeVoid 1347 %int = OpTypeInt 32 0 1348 %device = OpConstant %int 1 1349 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1350 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1351 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1352 %voidfn = OpTypeFunction %void 1353 %func = OpFunction %void None %voidfn 1354 %entry = OpLabel 1355 OpCopyMemorySized %var1 %var2 %device MakePointerAvailableKHR|NonPrivatePointerKHR %device 1356 OpReturn 1357 OpFunctionEnd 1358 )"; 1359 1360 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1361 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1362 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1363 EXPECT_THAT( 1364 getDiagnosticString(), 1365 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1366 "VulkanMemoryModelDeviceScopeKHR capability")); 1367 } 1368 1369 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad2) { 1370 const std::string spirv = R"( 1371 OpCapability Shader 1372 OpCapability VulkanMemoryModelKHR 1373 OpCapability Linkage 1374 OpCapability Addresses 1375 OpExtension "SPV_KHR_vulkan_memory_model" 1376 OpMemoryModel Logical VulkanKHR 1377 %void = OpTypeVoid 1378 %int = OpTypeInt 32 0 1379 %device = OpConstant %int 1 1380 %workgroup = OpConstant %int 1 1381 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1382 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1383 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1384 %voidfn = OpTypeFunction %void 1385 %func = OpFunction %void None %voidfn 1386 %entry = OpLabel 1387 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup 1388 OpReturn 1389 OpFunctionEnd 1390 )"; 1391 1392 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1393 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1394 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1395 EXPECT_THAT( 1396 getDiagnosticString(), 1397 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1398 "VulkanMemoryModelDeviceScopeKHR capability")); 1399 } 1400 1401 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedBad3) { 1402 const std::string spirv = R"( 1403 OpCapability Shader 1404 OpCapability VulkanMemoryModelKHR 1405 OpCapability Linkage 1406 OpCapability Addresses 1407 OpExtension "SPV_KHR_vulkan_memory_model" 1408 OpMemoryModel Logical VulkanKHR 1409 %void = OpTypeVoid 1410 %int = OpTypeInt 32 0 1411 %device = OpConstant %int 1 1412 %workgroup = OpConstant %int 1 1413 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1414 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1415 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1416 %voidfn = OpTypeFunction %void 1417 %func = OpFunction %void None %voidfn 1418 %entry = OpLabel 1419 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device 1420 OpReturn 1421 OpFunctionEnd 1422 )"; 1423 1424 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1425 EXPECT_EQ(SPV_ERROR_INVALID_DATA, 1426 ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1427 EXPECT_THAT( 1428 getDiagnosticString(), 1429 HasSubstr("Use of device scope with VulkanKHR memory model requires the " 1430 "VulkanMemoryModelDeviceScopeKHR capability")); 1431 } 1432 1433 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood1) { 1434 const std::string spirv = R"( 1435 OpCapability Shader 1436 OpCapability VulkanMemoryModelKHR 1437 OpCapability VulkanMemoryModelDeviceScopeKHR 1438 OpCapability Linkage 1439 OpCapability Addresses 1440 OpExtension "SPV_KHR_vulkan_memory_model" 1441 OpMemoryModel Logical VulkanKHR 1442 %void = OpTypeVoid 1443 %int = OpTypeInt 32 0 1444 %device = OpConstant %int 1 1445 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1446 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1447 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1448 %voidfn = OpTypeFunction %void 1449 %func = OpFunction %void None %voidfn 1450 %entry = OpLabel 1451 OpCopyMemorySized %var1 %var2 %device MakePointerAvailableKHR|NonPrivatePointerKHR %device 1452 OpReturn 1453 OpFunctionEnd 1454 )"; 1455 1456 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1457 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1458 } 1459 1460 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood2) { 1461 const std::string spirv = R"( 1462 OpCapability Shader 1463 OpCapability VulkanMemoryModelKHR 1464 OpCapability VulkanMemoryModelDeviceScopeKHR 1465 OpCapability Linkage 1466 OpCapability Addresses 1467 OpExtension "SPV_KHR_vulkan_memory_model" 1468 OpMemoryModel Logical VulkanKHR 1469 %void = OpTypeVoid 1470 %int = OpTypeInt 32 0 1471 %device = OpConstant %int 1 1472 %workgroup = OpConstant %int 2 1473 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1474 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1475 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1476 %voidfn = OpTypeFunction %void 1477 %func = OpFunction %void None %voidfn 1478 %entry = OpLabel 1479 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %device %workgroup 1480 OpReturn 1481 OpFunctionEnd 1482 )"; 1483 1484 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1485 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1486 } 1487 1488 TEST_F(ValidateMemory, VulkanMemoryModelDeviceScopeCopyMemorySizedGood3) { 1489 const std::string spirv = R"( 1490 OpCapability Shader 1491 OpCapability VulkanMemoryModelKHR 1492 OpCapability VulkanMemoryModelDeviceScopeKHR 1493 OpCapability Linkage 1494 OpCapability Addresses 1495 OpExtension "SPV_KHR_vulkan_memory_model" 1496 OpMemoryModel Logical VulkanKHR 1497 %void = OpTypeVoid 1498 %int = OpTypeInt 32 0 1499 %device = OpConstant %int 1 1500 %workgroup = OpConstant %int 2 1501 %int_ptr_ssbo = OpTypePointer StorageBuffer %int 1502 %var1 = OpVariable %int_ptr_ssbo StorageBuffer 1503 %var2 = OpVariable %int_ptr_ssbo StorageBuffer 1504 %voidfn = OpTypeFunction %void 1505 %func = OpFunction %void None %voidfn 1506 %entry = OpLabel 1507 OpCopyMemorySized %var1 %var2 %device Aligned|MakePointerVisibleKHR|MakePointerAvailableKHR|NonPrivatePointerKHR 4 %workgroup %device 1508 OpReturn 1509 OpFunctionEnd 1510 )"; 1511 1512 CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3); 1513 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3)); 1514 } 1515 1516 } // namespace 1517 } // namespace val 1518 } // namespace spvtools 1519