1 // Copyright (c) 2017 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 #include <sstream> 16 #include <string> 17 18 #include "gmock/gmock.h" 19 #include "test/unit_spirv.h" 20 #include "test/val/val_fixtures.h" 21 22 namespace spvtools { 23 namespace val { 24 namespace { 25 26 using ::testing::HasSubstr; 27 using ::testing::Not; 28 29 using ValidateComposites = spvtest::ValidateBase<bool>; 30 31 std::string GenerateShaderCode( 32 const std::string& body, 33 const std::string& capabilities_and_extensions = "", 34 const std::string& execution_model = "Fragment") { 35 std::ostringstream ss; 36 ss << R"( 37 OpCapability Shader 38 OpCapability Float64 39 )"; 40 41 ss << capabilities_and_extensions; 42 ss << "OpMemoryModel Logical GLSL450\n"; 43 ss << "OpEntryPoint " << execution_model << " %main \"main\"\n"; 44 if (execution_model == "Fragment") { 45 ss << "OpExecutionMode %main OriginUpperLeft\n"; 46 } 47 48 ss << R"( 49 %void = OpTypeVoid 50 %func = OpTypeFunction %void 51 %bool = OpTypeBool 52 %f32 = OpTypeFloat 32 53 %f64 = OpTypeFloat 64 54 %u32 = OpTypeInt 32 0 55 %s32 = OpTypeInt 32 1 56 %f32vec2 = OpTypeVector %f32 2 57 %f32vec3 = OpTypeVector %f32 3 58 %f32vec4 = OpTypeVector %f32 4 59 %f64vec2 = OpTypeVector %f64 2 60 %u32vec2 = OpTypeVector %u32 2 61 %u32vec4 = OpTypeVector %u32 4 62 %f64mat22 = OpTypeMatrix %f64vec2 2 63 %f32mat22 = OpTypeMatrix %f32vec2 2 64 %f32mat23 = OpTypeMatrix %f32vec2 3 65 %f32mat32 = OpTypeMatrix %f32vec3 2 66 67 %f32_0 = OpConstant %f32 0 68 %f32_1 = OpConstant %f32 1 69 %f32_2 = OpConstant %f32 2 70 %f32_3 = OpConstant %f32 3 71 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1 72 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2 73 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 74 75 %u32_0 = OpConstant %u32 0 76 %u32_1 = OpConstant %u32 1 77 %u32_2 = OpConstant %u32 2 78 %u32_3 = OpConstant %u32 3 79 80 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1 81 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3 82 83 %f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12 84 %f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12 85 86 %f32vec2arr3 = OpTypeArray %f32vec2 %u32_3 87 %f32vec2rarr = OpTypeRuntimeArray %f32vec2 88 89 %f32u32struct = OpTypeStruct %f32 %u32 90 %big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2rarr %f32u32struct 91 92 %ptr_big_struct = OpTypePointer Uniform %big_struct 93 %var_big_struct = OpVariable %ptr_big_struct Uniform 94 95 %main = OpFunction %void None %func 96 %main_entry = OpLabel 97 )"; 98 99 ss << body; 100 101 ss << R"( 102 OpReturn 103 OpFunctionEnd)"; 104 105 return ss.str(); 106 } 107 108 // Returns header for legacy tests taken from val_id_test.cpp. 109 std::string GetHeaderForTestsFromValId() { 110 return R"( 111 OpCapability Shader 112 OpCapability Linkage 113 OpCapability Addresses 114 OpCapability Pipes 115 OpCapability LiteralSampler 116 OpCapability DeviceEnqueue 117 OpCapability Vector16 118 OpCapability Int8 119 OpCapability Int16 120 OpCapability Int64 121 OpCapability Float64 122 OpMemoryModel Logical GLSL450 123 %void = OpTypeVoid 124 %void_f = OpTypeFunction %void 125 %int = OpTypeInt 32 0 126 %float = OpTypeFloat 32 127 %v3float = OpTypeVector %float 3 128 %mat4x3 = OpTypeMatrix %v3float 4 129 %_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3 130 %_ptr_Private_float = OpTypePointer Private %float 131 %my_matrix = OpVariable %_ptr_Private_mat4x3 Private 132 %my_float_var = OpVariable %_ptr_Private_float Private 133 %_ptr_Function_float = OpTypePointer Function %float 134 %int_0 = OpConstant %int 0 135 %int_1 = OpConstant %int 1 136 %int_2 = OpConstant %int 2 137 %int_3 = OpConstant %int 3 138 %int_5 = OpConstant %int 5 139 140 ; Making the following nested structures. 141 ; 142 ; struct S { 143 ; bool b; 144 ; vec4 v[5]; 145 ; int i; 146 ; mat4x3 m[5]; 147 ; } 148 ; uniform blockName { 149 ; S s; 150 ; bool cond; 151 ; RunTimeArray arr; 152 ; } 153 154 %f32arr = OpTypeRuntimeArray %float 155 %v4float = OpTypeVector %float 4 156 %array5_mat4x3 = OpTypeArray %mat4x3 %int_5 157 %array5_vec4 = OpTypeArray %v4float %int_5 158 %_ptr_Uniform_float = OpTypePointer Uniform %float 159 %_ptr_Function_vec4 = OpTypePointer Function %v4float 160 %_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float 161 %struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3 162 %struct_blockName = OpTypeStruct %struct_s %int %f32arr 163 %_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName 164 %_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s 165 %_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3 166 %_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3 167 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float 168 %blockName_var = OpVariable %_ptr_Uniform_blockName Uniform 169 %spec_int = OpSpecConstant %int 2 170 %func = OpFunction %void None %void_f 171 %my_label = OpLabel 172 )"; 173 } 174 175 TEST_F(ValidateComposites, VectorExtractDynamicSuccess) { 176 const std::string body = R"( 177 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0 178 )"; 179 180 CompileSuccessfully(GenerateShaderCode(body).c_str()); 181 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 182 } 183 184 TEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) { 185 const std::string body = R"( 186 %val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0 187 )"; 188 189 CompileSuccessfully(GenerateShaderCode(body).c_str()); 190 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 191 EXPECT_THAT(getDiagnosticString(), 192 HasSubstr("Expected Result Type to be a scalar type")); 193 } 194 195 TEST_F(ValidateComposites, VectorExtractDynamicNotVector) { 196 const std::string body = R"( 197 %val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0 198 )"; 199 200 CompileSuccessfully(GenerateShaderCode(body).c_str()); 201 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 202 EXPECT_THAT(getDiagnosticString(), 203 HasSubstr("Expected Vector type to be OpTypeVector")); 204 } 205 206 TEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) { 207 const std::string body = R"( 208 %val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0 209 )"; 210 211 CompileSuccessfully(GenerateShaderCode(body).c_str()); 212 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 213 EXPECT_THAT( 214 getDiagnosticString(), 215 HasSubstr("Expected Vector component type to be equal to Result Type")); 216 } 217 218 TEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) { 219 const std::string body = R"( 220 %val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0 221 )"; 222 223 CompileSuccessfully(GenerateShaderCode(body).c_str()); 224 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 225 EXPECT_THAT(getDiagnosticString(), 226 HasSubstr("Expected Index to be int scalar")); 227 } 228 229 TEST_F(ValidateComposites, VectorInsertDynamicSuccess) { 230 const std::string body = R"( 231 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0 232 )"; 233 234 CompileSuccessfully(GenerateShaderCode(body).c_str()); 235 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 236 } 237 238 TEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) { 239 const std::string body = R"( 240 %val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0 241 )"; 242 243 CompileSuccessfully(GenerateShaderCode(body).c_str()); 244 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 245 EXPECT_THAT(getDiagnosticString(), 246 HasSubstr("Expected Result Type to be OpTypeVector")); 247 } 248 249 TEST_F(ValidateComposites, VectorInsertDynamicNotVector) { 250 const std::string body = R"( 251 %val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0 252 )"; 253 254 CompileSuccessfully(GenerateShaderCode(body).c_str()); 255 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 256 EXPECT_THAT(getDiagnosticString(), 257 HasSubstr("Expected Vector type to be equal to Result Type")); 258 } 259 260 TEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) { 261 const std::string body = R"( 262 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0 263 )"; 264 265 CompileSuccessfully(GenerateShaderCode(body).c_str()); 266 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 267 EXPECT_THAT(getDiagnosticString(), 268 HasSubstr("Expected Component type to be equal to Result Type " 269 "component type")); 270 } 271 272 TEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) { 273 const std::string body = R"( 274 %val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0 275 )"; 276 277 CompileSuccessfully(GenerateShaderCode(body).c_str()); 278 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 279 EXPECT_THAT(getDiagnosticString(), 280 HasSubstr("Expected Index to be int scalar")); 281 } 282 283 TEST_F(ValidateComposites, CompositeConstructNotComposite) { 284 const std::string body = R"( 285 %val1 = OpCompositeConstruct %f32 %f32_1 286 )"; 287 288 CompileSuccessfully(GenerateShaderCode(body).c_str()); 289 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 290 EXPECT_THAT(getDiagnosticString(), 291 HasSubstr("Expected Result Type to be a composite type")); 292 } 293 294 TEST_F(ValidateComposites, CompositeConstructVectorSuccess) { 295 const std::string body = R"( 296 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 297 %val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0 298 %val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12 299 %val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3 300 )"; 301 302 CompileSuccessfully(GenerateShaderCode(body).c_str()); 303 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 304 } 305 306 TEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) { 307 const std::string body = R"( 308 %val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123 309 )"; 310 311 CompileSuccessfully(GenerateShaderCode(body).c_str()); 312 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 313 EXPECT_THAT(getDiagnosticString(), 314 HasSubstr("Expected number of constituents to be at least 2")); 315 } 316 317 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) { 318 const std::string body = R"( 319 %val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12 320 )"; 321 322 CompileSuccessfully(GenerateShaderCode(body).c_str()); 323 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 324 EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 5[%float] cannot be a " 325 "type")); 326 } 327 328 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) { 329 const std::string body = R"( 330 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32vec2_01 331 )"; 332 333 CompileSuccessfully(GenerateShaderCode(body).c_str()); 334 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 335 EXPECT_THAT( 336 getDiagnosticString(), 337 HasSubstr("Expected Constituents to be scalars or vectors of the same " 338 "type as Result Type components")); 339 } 340 341 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent3) { 342 const std::string body = R"( 343 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32_0 %f32_0 344 )"; 345 346 CompileSuccessfully(GenerateShaderCode(body).c_str()); 347 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 348 EXPECT_THAT( 349 getDiagnosticString(), 350 HasSubstr("Expected Constituents to be scalars or vectors of the same " 351 "type as Result Type components")); 352 } 353 354 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber1) { 355 const std::string body = R"( 356 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 357 )"; 358 359 CompileSuccessfully(GenerateShaderCode(body).c_str()); 360 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 361 EXPECT_THAT( 362 getDiagnosticString(), 363 HasSubstr("Expected total number of given components to be equal to the " 364 "size of Result Type vector")); 365 } 366 367 TEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber2) { 368 const std::string body = R"( 369 %val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 %f32_0 370 )"; 371 372 CompileSuccessfully(GenerateShaderCode(body).c_str()); 373 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 374 EXPECT_THAT( 375 getDiagnosticString(), 376 HasSubstr("Expected total number of given components to be equal to the " 377 "size of Result Type vector")); 378 } 379 380 TEST_F(ValidateComposites, CompositeConstructMatrixSuccess) { 381 const std::string body = R"( 382 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 383 %val2 = OpCompositeConstruct %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12 384 )"; 385 386 CompileSuccessfully(GenerateShaderCode(body).c_str()); 387 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 388 } 389 390 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber1) { 391 const std::string body = R"( 392 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 393 )"; 394 395 CompileSuccessfully(GenerateShaderCode(body).c_str()); 396 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 397 EXPECT_THAT( 398 getDiagnosticString(), 399 HasSubstr("Expected total number of Constituents to be equal to the " 400 "number of columns of Result Type matrix")); 401 } 402 403 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber2) { 404 const std::string body = R"( 405 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 %f32vec2_12 406 )"; 407 408 CompileSuccessfully(GenerateShaderCode(body).c_str()); 409 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 410 EXPECT_THAT( 411 getDiagnosticString(), 412 HasSubstr("Expected total number of Constituents to be equal to the " 413 "number of columns of Result Type matrix")); 414 } 415 416 TEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent) { 417 const std::string body = R"( 418 %val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %u32vec2_01 419 )"; 420 421 CompileSuccessfully(GenerateShaderCode(body).c_str()); 422 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 423 EXPECT_THAT( 424 getDiagnosticString(), 425 HasSubstr("Expected Constituent type to be equal to the column type " 426 "Result Type matrix")); 427 } 428 429 TEST_F(ValidateComposites, CompositeConstructArraySuccess) { 430 const std::string body = R"( 431 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 432 )"; 433 434 CompileSuccessfully(GenerateShaderCode(body).c_str()); 435 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 436 } 437 438 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber1) { 439 const std::string body = R"( 440 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 441 )"; 442 443 CompileSuccessfully(GenerateShaderCode(body).c_str()); 444 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 445 EXPECT_THAT( 446 getDiagnosticString(), 447 HasSubstr("Expected total number of Constituents to be equal to the " 448 "number of elements of Result Type array")); 449 } 450 451 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber2) { 452 const std::string body = R"( 453 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 %f32vec2_12 454 )"; 455 456 CompileSuccessfully(GenerateShaderCode(body).c_str()); 457 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 458 EXPECT_THAT( 459 getDiagnosticString(), 460 HasSubstr("Expected total number of Constituents to be equal to the " 461 "number of elements of Result Type array")); 462 } 463 464 TEST_F(ValidateComposites, CompositeConstructArrayWrongConsituent) { 465 const std::string body = R"( 466 %val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %u32vec2_01 %f32vec2_12 467 )"; 468 469 CompileSuccessfully(GenerateShaderCode(body).c_str()); 470 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 471 EXPECT_THAT( 472 getDiagnosticString(), 473 HasSubstr("Expected Constituent type to be equal to the column type " 474 "Result Type array")); 475 } 476 477 TEST_F(ValidateComposites, CompositeConstructStructSuccess) { 478 const std::string body = R"( 479 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 480 )"; 481 482 CompileSuccessfully(GenerateShaderCode(body).c_str()); 483 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 484 } 485 486 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber1) { 487 const std::string body = R"( 488 %val1 = OpCompositeConstruct %f32u32struct %f32_0 489 )"; 490 491 CompileSuccessfully(GenerateShaderCode(body).c_str()); 492 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 493 EXPECT_THAT( 494 getDiagnosticString(), 495 HasSubstr("Expected total number of Constituents to be equal to the " 496 "number of members of Result Type struct")); 497 } 498 499 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber2) { 500 const std::string body = R"( 501 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 %u32_1 502 )"; 503 504 CompileSuccessfully(GenerateShaderCode(body).c_str()); 505 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 506 EXPECT_THAT( 507 getDiagnosticString(), 508 HasSubstr("Expected total number of Constituents to be equal to the " 509 "number of members of Result Type struct")); 510 } 511 512 TEST_F(ValidateComposites, CompositeConstructStructWrongConstituent) { 513 const std::string body = R"( 514 %val1 = OpCompositeConstruct %f32u32struct %f32_0 %f32_1 515 )"; 516 517 CompileSuccessfully(GenerateShaderCode(body).c_str()); 518 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 519 EXPECT_THAT(getDiagnosticString(), 520 HasSubstr("Expected Constituent type to be equal to the " 521 "corresponding member type of Result Type struct")); 522 } 523 524 TEST_F(ValidateComposites, CopyObjectSuccess) { 525 const std::string body = R"( 526 %val1 = OpCopyObject %f32 %f32_0 527 %val2 = OpCopyObject %f32vec4 %f32vec4_0123 528 )"; 529 530 CompileSuccessfully(GenerateShaderCode(body).c_str()); 531 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 532 } 533 534 TEST_F(ValidateComposites, CopyObjectResultTypeNotType) { 535 const std::string body = R"( 536 %val1 = OpCopyObject %f32_0 %f32_0 537 )"; 538 539 CompileSuccessfully(GenerateShaderCode(body).c_str()); 540 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 541 EXPECT_THAT(getDiagnosticString(), 542 HasSubstr("ID 19[%float_0] is not a type id")); 543 } 544 545 TEST_F(ValidateComposites, CopyObjectWrongOperandType) { 546 const std::string body = R"( 547 %val1 = OpCopyObject %f32 %u32_0 548 )"; 549 550 CompileSuccessfully(GenerateShaderCode(body).c_str()); 551 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 552 EXPECT_THAT( 553 getDiagnosticString(), 554 HasSubstr("Expected Result Type and Operand type to be the same")); 555 } 556 557 TEST_F(ValidateComposites, TransposeSuccess) { 558 const std::string body = R"( 559 %val1 = OpTranspose %f32mat32 %f32mat23_121212 560 %val2 = OpTranspose %f32mat22 %f32mat22_1212 561 )"; 562 563 CompileSuccessfully(GenerateShaderCode(body).c_str()); 564 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 565 } 566 567 TEST_F(ValidateComposites, TransposeResultTypeNotMatrix) { 568 const std::string body = R"( 569 %val1 = OpTranspose %f32vec4 %f32mat22_1212 570 )"; 571 572 CompileSuccessfully(GenerateShaderCode(body).c_str()); 573 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 574 EXPECT_THAT(getDiagnosticString(), 575 HasSubstr("Expected Result Type to be a matrix type")); 576 } 577 578 TEST_F(ValidateComposites, TransposeDifferentComponentTypes) { 579 const std::string body = R"( 580 %val1 = OpTranspose %f64mat22 %f32mat22_1212 581 )"; 582 583 CompileSuccessfully(GenerateShaderCode(body).c_str()); 584 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 585 EXPECT_THAT( 586 getDiagnosticString(), 587 HasSubstr("Expected component types of Matrix and Result Type to be " 588 "identical")); 589 } 590 591 TEST_F(ValidateComposites, TransposeIncompatibleDimensions1) { 592 const std::string body = R"( 593 %val1 = OpTranspose %f32mat23 %f32mat22_1212 594 )"; 595 596 CompileSuccessfully(GenerateShaderCode(body).c_str()); 597 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 598 EXPECT_THAT(getDiagnosticString(), 599 HasSubstr("Expected number of columns and the column size " 600 "of Matrix to be the reverse of those of Result Type")); 601 } 602 603 TEST_F(ValidateComposites, TransposeIncompatibleDimensions2) { 604 const std::string body = R"( 605 %val1 = OpTranspose %f32mat32 %f32mat22_1212 606 )"; 607 608 CompileSuccessfully(GenerateShaderCode(body).c_str()); 609 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 610 EXPECT_THAT(getDiagnosticString(), 611 HasSubstr("Expected number of columns and the column size " 612 "of Matrix to be the reverse of those of Result Type")); 613 } 614 615 TEST_F(ValidateComposites, TransposeIncompatibleDimensions3) { 616 const std::string body = R"( 617 %val1 = OpTranspose %f32mat23 %f32mat23_121212 618 )"; 619 620 CompileSuccessfully(GenerateShaderCode(body).c_str()); 621 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 622 EXPECT_THAT(getDiagnosticString(), 623 HasSubstr("Expected number of columns and the column size " 624 "of Matrix to be the reverse of those of Result Type")); 625 } 626 627 TEST_F(ValidateComposites, CompositeExtractSuccess) { 628 const std::string body = R"( 629 %val1 = OpCompositeExtract %f32 %f32vec4_0123 1 630 %val2 = OpCompositeExtract %u32 %u32vec4_0123 0 631 %val3 = OpCompositeExtract %f32 %f32mat22_1212 0 1 632 %val4 = OpCompositeExtract %f32vec2 %f32mat22_1212 0 633 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 634 %val5 = OpCompositeExtract %f32vec2 %array 2 635 %val6 = OpCompositeExtract %f32 %array 2 1 636 %struct = OpLoad %big_struct %var_big_struct 637 %val7 = OpCompositeExtract %f32 %struct 0 638 %val8 = OpCompositeExtract %f32vec4 %struct 1 639 %val9 = OpCompositeExtract %f32 %struct 1 2 640 %val10 = OpCompositeExtract %f32mat23 %struct 2 641 %val11 = OpCompositeExtract %f32vec2 %struct 2 2 642 %val12 = OpCompositeExtract %f32 %struct 2 2 1 643 %val13 = OpCompositeExtract %f32vec2 %struct 3 2 644 %val14 = OpCompositeExtract %f32 %struct 3 2 1 645 %val15 = OpCompositeExtract %f32vec2 %struct 4 100 646 %val16 = OpCompositeExtract %f32 %struct 4 1000 1 647 %val17 = OpCompositeExtract %f32 %struct 5 0 648 %val18 = OpCompositeExtract %u32 %struct 5 1 649 %val19 = OpCompositeExtract %big_struct %struct 650 )"; 651 652 CompileSuccessfully(GenerateShaderCode(body)); 653 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 654 } 655 656 TEST_F(ValidateComposites, CompositeExtractNotObject) { 657 const std::string body = R"( 658 %val1 = OpCompositeExtract %f32 %f32vec4 1 659 )"; 660 661 CompileSuccessfully(GenerateShaderCode(body)); 662 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 663 EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand 11[%v4float] cannot " 664 "be a type")); 665 } 666 667 TEST_F(ValidateComposites, CompositeExtractNotComposite) { 668 const std::string body = R"( 669 %val1 = OpCompositeExtract %f32 %f32_1 0 670 )"; 671 672 CompileSuccessfully(GenerateShaderCode(body)); 673 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 674 EXPECT_THAT(getDiagnosticString(), 675 HasSubstr("Reached non-composite type while indexes still remain " 676 "to be traversed.")); 677 } 678 679 TEST_F(ValidateComposites, CompositeExtractVectorOutOfBounds) { 680 const std::string body = R"( 681 %val1 = OpCompositeExtract %f32 %f32vec4_0123 4 682 )"; 683 684 CompileSuccessfully(GenerateShaderCode(body)); 685 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 686 EXPECT_THAT(getDiagnosticString(), 687 HasSubstr("Vector access is out of bounds, " 688 "vector size is 4, but access index is 4")); 689 } 690 691 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfCols) { 692 const std::string body = R"( 693 %val1 = OpCompositeExtract %f32 %f32mat23_121212 3 1 694 )"; 695 696 CompileSuccessfully(GenerateShaderCode(body)); 697 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 698 EXPECT_THAT(getDiagnosticString(), 699 HasSubstr("Matrix access is out of bounds, " 700 "matrix has 3 columns, but access index is 3")); 701 } 702 703 TEST_F(ValidateComposites, CompositeExtractMatrixOutOfRows) { 704 const std::string body = R"( 705 %val1 = OpCompositeExtract %f32 %f32mat23_121212 2 5 706 )"; 707 708 CompileSuccessfully(GenerateShaderCode(body)); 709 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 710 EXPECT_THAT(getDiagnosticString(), 711 HasSubstr("Vector access is out of bounds, " 712 "vector size is 2, but access index is 5")); 713 } 714 715 TEST_F(ValidateComposites, CompositeExtractArrayOutOfBounds) { 716 const std::string body = R"( 717 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 718 %val1 = OpCompositeExtract %f32vec2 %array 3 719 )"; 720 721 CompileSuccessfully(GenerateShaderCode(body)); 722 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 723 EXPECT_THAT(getDiagnosticString(), 724 HasSubstr("Array access is out of bounds, " 725 "array size is 3, but access index is 3")); 726 } 727 728 TEST_F(ValidateComposites, CompositeExtractStructOutOfBounds) { 729 const std::string body = R"( 730 %struct = OpLoad %big_struct %var_big_struct 731 %val1 = OpCompositeExtract %f32 %struct 6 732 )"; 733 734 CompileSuccessfully(GenerateShaderCode(body)); 735 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 736 EXPECT_THAT(getDiagnosticString(), 737 HasSubstr("Index is out of bounds, can not find index 6 in the " 738 "structure <id> '37'. This structure has 6 members. " 739 "Largest valid index is 5.")); 740 } 741 742 TEST_F(ValidateComposites, CompositeExtractNestedVectorOutOfBounds) { 743 const std::string body = R"( 744 %struct = OpLoad %big_struct %var_big_struct 745 %val1 = OpCompositeExtract %f32 %struct 3 1 5 746 )"; 747 748 CompileSuccessfully(GenerateShaderCode(body)); 749 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 750 EXPECT_THAT(getDiagnosticString(), 751 HasSubstr("Vector access is out of bounds, " 752 "vector size is 2, but access index is 5")); 753 } 754 755 TEST_F(ValidateComposites, CompositeExtractTooManyIndices) { 756 const std::string body = R"( 757 %struct = OpLoad %big_struct %var_big_struct 758 %val1 = OpCompositeExtract %f32 %struct 3 1 1 2 759 )"; 760 761 CompileSuccessfully(GenerateShaderCode(body)); 762 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 763 EXPECT_THAT(getDiagnosticString(), 764 HasSubstr("Reached non-composite type while " 765 "indexes still remain to be traversed.")); 766 } 767 768 TEST_F(ValidateComposites, CompositeExtractWrongType1) { 769 const std::string body = R"( 770 %struct = OpLoad %big_struct %var_big_struct 771 %val1 = OpCompositeExtract %f32vec2 %struct 3 1 1 772 )"; 773 774 CompileSuccessfully(GenerateShaderCode(body)); 775 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 776 EXPECT_THAT( 777 getDiagnosticString(), 778 HasSubstr( 779 "Result type (OpTypeVector) does not match the type that results " 780 "from indexing into the composite (OpTypeFloat).")); 781 } 782 783 TEST_F(ValidateComposites, CompositeExtractWrongType2) { 784 const std::string body = R"( 785 %struct = OpLoad %big_struct %var_big_struct 786 %val1 = OpCompositeExtract %f32 %struct 3 1 787 )"; 788 789 CompileSuccessfully(GenerateShaderCode(body)); 790 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 791 EXPECT_THAT(getDiagnosticString(), 792 HasSubstr("Result type (OpTypeFloat) does not match the type " 793 "that results from indexing into the composite " 794 "(OpTypeVector).")); 795 } 796 797 TEST_F(ValidateComposites, CompositeExtractWrongType3) { 798 const std::string body = R"( 799 %struct = OpLoad %big_struct %var_big_struct 800 %val1 = OpCompositeExtract %f32 %struct 2 1 801 )"; 802 803 CompileSuccessfully(GenerateShaderCode(body)); 804 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 805 EXPECT_THAT(getDiagnosticString(), 806 HasSubstr("Result type (OpTypeFloat) does not match the type " 807 "that results from indexing into the composite " 808 "(OpTypeVector).")); 809 } 810 811 TEST_F(ValidateComposites, CompositeExtractWrongType4) { 812 const std::string body = R"( 813 %struct = OpLoad %big_struct %var_big_struct 814 %val1 = OpCompositeExtract %f32 %struct 4 1 815 )"; 816 817 CompileSuccessfully(GenerateShaderCode(body)); 818 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 819 EXPECT_THAT(getDiagnosticString(), 820 HasSubstr("Result type (OpTypeFloat) does not match the type " 821 "that results from indexing into the composite " 822 "(OpTypeVector).")); 823 } 824 825 TEST_F(ValidateComposites, CompositeExtractWrongType5) { 826 const std::string body = R"( 827 %struct = OpLoad %big_struct %var_big_struct 828 %val1 = OpCompositeExtract %f32 %struct 5 1 829 )"; 830 831 CompileSuccessfully(GenerateShaderCode(body)); 832 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 833 EXPECT_THAT( 834 getDiagnosticString(), 835 HasSubstr( 836 "Result type (OpTypeFloat) does not match the " 837 "type that results from indexing into the composite (OpTypeInt).")); 838 } 839 840 TEST_F(ValidateComposites, CompositeInsertSuccess) { 841 const std::string body = R"( 842 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 0 843 %val2 = OpCompositeInsert %u32vec4 %u32_1 %u32vec4_0123 0 844 %val3 = OpCompositeInsert %f32mat22 %f32_2 %f32mat22_1212 0 1 845 %val4 = OpCompositeInsert %f32mat22 %f32vec2_01 %f32mat22_1212 0 846 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 847 %val5 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 2 848 %val6 = OpCompositeInsert %f32vec2arr3 %f32_3 %array 2 1 849 %struct = OpLoad %big_struct %var_big_struct 850 %val7 = OpCompositeInsert %big_struct %f32_3 %struct 0 851 %val8 = OpCompositeInsert %big_struct %f32vec4_0123 %struct 1 852 %val9 = OpCompositeInsert %big_struct %f32_3 %struct 1 2 853 %val10 = OpCompositeInsert %big_struct %f32mat23_121212 %struct 2 854 %val11 = OpCompositeInsert %big_struct %f32vec2_01 %struct 2 2 855 %val12 = OpCompositeInsert %big_struct %f32_3 %struct 2 2 1 856 %val13 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 2 857 %val14 = OpCompositeInsert %big_struct %f32_3 %struct 3 2 1 858 %val15 = OpCompositeInsert %big_struct %f32vec2_01 %struct 4 100 859 %val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 1000 1 860 %val17 = OpCompositeInsert %big_struct %f32_3 %struct 5 0 861 %val18 = OpCompositeInsert %big_struct %u32_3 %struct 5 1 862 %val19 = OpCompositeInsert %big_struct %struct %struct 863 )"; 864 865 CompileSuccessfully(GenerateShaderCode(body)); 866 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 867 } 868 869 TEST_F(ValidateComposites, CompositeInsertResultTypeDifferentFromComposite) { 870 const std::string body = R"( 871 %val1 = OpCompositeInsert %f32 %f32_1 %f32vec4_0123 0 872 )"; 873 874 CompileSuccessfully(GenerateShaderCode(body)); 875 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 876 EXPECT_THAT(getDiagnosticString(), 877 HasSubstr("The Result Type must be the same as Composite type in " 878 "OpCompositeInsert yielding Result Id 5.")); 879 } 880 881 TEST_F(ValidateComposites, CompositeInsertNotComposite) { 882 const std::string body = R"( 883 %val1 = OpCompositeInsert %f32 %f32_1 %f32_0 0 884 )"; 885 886 CompileSuccessfully(GenerateShaderCode(body)); 887 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 888 EXPECT_THAT(getDiagnosticString(), 889 HasSubstr("Reached non-composite type while indexes still remain " 890 "to be traversed.")); 891 } 892 893 TEST_F(ValidateComposites, CompositeInsertVectorOutOfBounds) { 894 const std::string body = R"( 895 %val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 4 896 )"; 897 898 CompileSuccessfully(GenerateShaderCode(body)); 899 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 900 EXPECT_THAT(getDiagnosticString(), 901 HasSubstr("Vector access is out of bounds, " 902 "vector size is 4, but access index is 4")); 903 } 904 905 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfCols) { 906 const std::string body = R"( 907 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 3 1 908 )"; 909 910 CompileSuccessfully(GenerateShaderCode(body)); 911 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 912 EXPECT_THAT(getDiagnosticString(), 913 HasSubstr("Matrix access is out of bounds, " 914 "matrix has 3 columns, but access index is 3")); 915 } 916 917 TEST_F(ValidateComposites, CompositeInsertMatrixOutOfRows) { 918 const std::string body = R"( 919 %val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 2 5 920 )"; 921 922 CompileSuccessfully(GenerateShaderCode(body)); 923 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 924 EXPECT_THAT(getDiagnosticString(), 925 HasSubstr("Vector access is out of bounds, " 926 "vector size is 2, but access index is 5")); 927 } 928 929 TEST_F(ValidateComposites, CompositeInsertArrayOutOfBounds) { 930 const std::string body = R"( 931 %array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 932 %val1 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 3 933 )"; 934 935 CompileSuccessfully(GenerateShaderCode(body)); 936 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 937 EXPECT_THAT(getDiagnosticString(), 938 HasSubstr("Array access is out of bounds, array " 939 "size is 3, but access index is 3")); 940 } 941 942 TEST_F(ValidateComposites, CompositeInsertStructOutOfBounds) { 943 const std::string body = R"( 944 %struct = OpLoad %big_struct %var_big_struct 945 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 6 946 )"; 947 948 CompileSuccessfully(GenerateShaderCode(body)); 949 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 950 EXPECT_THAT(getDiagnosticString(), 951 HasSubstr("Index is out of bounds, can not find index 6 in the " 952 "structure <id> '37'. This structure has 6 members. " 953 "Largest valid index is 5.")); 954 } 955 956 TEST_F(ValidateComposites, CompositeInsertNestedVectorOutOfBounds) { 957 const std::string body = R"( 958 %struct = OpLoad %big_struct %var_big_struct 959 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 5 960 )"; 961 962 CompileSuccessfully(GenerateShaderCode(body)); 963 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 964 EXPECT_THAT(getDiagnosticString(), 965 HasSubstr("Vector access is out of bounds, " 966 "vector size is 2, but access index is 5")); 967 } 968 969 TEST_F(ValidateComposites, CompositeInsertTooManyIndices) { 970 const std::string body = R"( 971 %struct = OpLoad %big_struct %var_big_struct 972 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1 2 973 )"; 974 975 CompileSuccessfully(GenerateShaderCode(body)); 976 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 977 EXPECT_THAT(getDiagnosticString(), 978 HasSubstr("Reached non-composite type while indexes still remain " 979 "to be traversed.")); 980 } 981 982 TEST_F(ValidateComposites, CompositeInsertWrongType1) { 983 const std::string body = R"( 984 %struct = OpLoad %big_struct %var_big_struct 985 %val1 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 1 1 986 )"; 987 988 CompileSuccessfully(GenerateShaderCode(body)); 989 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 990 EXPECT_THAT(getDiagnosticString(), 991 HasSubstr("The Object type (OpTypeVector) does not match the " 992 "type that results from indexing into the Composite " 993 "(OpTypeFloat).")); 994 } 995 996 TEST_F(ValidateComposites, CompositeInsertWrongType2) { 997 const std::string body = R"( 998 %struct = OpLoad %big_struct %var_big_struct 999 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1000 )"; 1001 1002 CompileSuccessfully(GenerateShaderCode(body)); 1003 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1004 EXPECT_THAT(getDiagnosticString(), 1005 HasSubstr("The Object type (OpTypeFloat) does not match the type " 1006 "that results from indexing into the Composite " 1007 "(OpTypeVector).")); 1008 } 1009 1010 TEST_F(ValidateComposites, CompositeInsertWrongType3) { 1011 const std::string body = R"( 1012 %struct = OpLoad %big_struct %var_big_struct 1013 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 2 1 1014 )"; 1015 1016 CompileSuccessfully(GenerateShaderCode(body)); 1017 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1018 EXPECT_THAT(getDiagnosticString(), 1019 HasSubstr("The Object type (OpTypeFloat) does not match the type " 1020 "that results from indexing into the Composite " 1021 "(OpTypeVector).")); 1022 } 1023 1024 TEST_F(ValidateComposites, CompositeInsertWrongType4) { 1025 const std::string body = R"( 1026 %struct = OpLoad %big_struct %var_big_struct 1027 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 4 1 1028 )"; 1029 1030 CompileSuccessfully(GenerateShaderCode(body)); 1031 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1032 EXPECT_THAT(getDiagnosticString(), 1033 HasSubstr("The Object type (OpTypeFloat) does not match the type " 1034 "that results from indexing into the Composite " 1035 "(OpTypeVector).")); 1036 } 1037 1038 TEST_F(ValidateComposites, CompositeInsertWrongType5) { 1039 const std::string body = R"( 1040 %struct = OpLoad %big_struct %var_big_struct 1041 %val1 = OpCompositeInsert %big_struct %f32_1 %struct 5 1 1042 )"; 1043 1044 CompileSuccessfully(GenerateShaderCode(body)); 1045 ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1046 EXPECT_THAT(getDiagnosticString(), 1047 HasSubstr("The Object type (OpTypeFloat) does not match the type " 1048 "that results from indexing into the Composite " 1049 "(OpTypeInt).")); 1050 } 1051 1052 // Tests ported from val_id_test.cpp. 1053 1054 // Valid. Tests both CompositeExtract and CompositeInsert with 255 indexes. 1055 TEST_F(ValidateComposites, CompositeExtractInsertLimitsGood) { 1056 int depth = 255; 1057 std::string header = GetHeaderForTestsFromValId(); 1058 header.erase(header.find("%func")); 1059 std::ostringstream spirv; 1060 spirv << header << std::endl; 1061 1062 // Build nested structures. Struct 'i' contains struct 'i-1' 1063 spirv << "%s_depth_1 = OpTypeStruct %float\n"; 1064 for (int i = 2; i <= depth; ++i) { 1065 spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n"; 1066 } 1067 1068 // Define Pointer and Variable to use for CompositeExtract/Insert. 1069 spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_" 1070 << depth << "\n"; 1071 spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n"; 1072 1073 // Function Start 1074 spirv << R"( 1075 %func = OpFunction %void None %void_f 1076 %my_label = OpLabel 1077 )"; 1078 1079 // OpCompositeExtract/Insert with 'n' indexes (n = depth) 1080 spirv << "%deep = OpLoad %s_depth_" << depth << " %deep_var" << std::endl; 1081 spirv << "%entry = OpCompositeExtract %float %deep"; 1082 for (int i = 0; i < depth; ++i) { 1083 spirv << " 0"; 1084 } 1085 spirv << std::endl; 1086 spirv << "%new_composite = OpCompositeInsert %s_depth_" << depth 1087 << " %entry %deep"; 1088 for (int i = 0; i < depth; ++i) { 1089 spirv << " 0"; 1090 } 1091 spirv << std::endl; 1092 1093 // Function end 1094 spirv << R"( 1095 OpReturn 1096 OpFunctionEnd 1097 )"; 1098 CompileSuccessfully(spirv.str()); 1099 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 1100 } 1101 1102 // Invalid: 256 indexes passed to OpCompositeExtract. Limit is 255. 1103 TEST_F(ValidateComposites, CompositeExtractArgCountExceededLimitBad) { 1104 std::ostringstream spirv; 1105 spirv << GetHeaderForTestsFromValId() << std::endl; 1106 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; 1107 spirv << "%entry = OpCompositeExtract %float %matrix"; 1108 for (int i = 0; i < 256; ++i) { 1109 spirv << " 0"; 1110 } 1111 spirv << R"( 1112 OpReturn 1113 OpFunctionEnd 1114 )"; 1115 CompileSuccessfully(spirv.str()); 1116 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1117 EXPECT_THAT(getDiagnosticString(), 1118 HasSubstr("The number of indexes in OpCompositeExtract may not " 1119 "exceed 255. Found 256 indexes.")); 1120 } 1121 1122 // Invalid: 256 indexes passed to OpCompositeInsert. Limit is 255. 1123 TEST_F(ValidateComposites, CompositeInsertArgCountExceededLimitBad) { 1124 std::ostringstream spirv; 1125 spirv << GetHeaderForTestsFromValId() << std::endl; 1126 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; 1127 spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix"; 1128 for (int i = 0; i < 256; ++i) { 1129 spirv << " 0"; 1130 } 1131 spirv << R"( 1132 OpReturn 1133 OpFunctionEnd 1134 )"; 1135 CompileSuccessfully(spirv.str()); 1136 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1137 EXPECT_THAT(getDiagnosticString(), 1138 HasSubstr("The number of indexes in OpCompositeInsert may not " 1139 "exceed 255. Found 256 indexes.")); 1140 } 1141 1142 // Invalid: In OpCompositeInsert, result type must be the same as composite type 1143 TEST_F(ValidateComposites, CompositeInsertWrongResultTypeBad) { 1144 std::ostringstream spirv; 1145 spirv << GetHeaderForTestsFromValId() << std::endl; 1146 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; 1147 spirv << "%float_entry = OpCompositeExtract %float %matrix 0 1" << std::endl; 1148 spirv << "%new_composite = OpCompositeInsert %float %float_entry %matrix 0 1" 1149 << std::endl; 1150 spirv << R"(OpReturn 1151 OpFunctionEnd)"; 1152 CompileSuccessfully(spirv.str()); 1153 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1154 EXPECT_THAT(getDiagnosticString(), 1155 HasSubstr("The Result Type must be the same as Composite type")); 1156 } 1157 1158 // Valid: No Indexes were passed to OpCompositeExtract, and the Result Type is 1159 // the same as the Base Composite type. 1160 TEST_F(ValidateComposites, CompositeExtractNoIndexesGood) { 1161 std::ostringstream spirv; 1162 spirv << GetHeaderForTestsFromValId() << std::endl; 1163 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; 1164 spirv << "%float_entry = OpCompositeExtract %mat4x3 %matrix" << std::endl; 1165 spirv << R"(OpReturn 1166 OpFunctionEnd)"; 1167 CompileSuccessfully(spirv.str()); 1168 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 1169 } 1170 1171 // Invalid: No Indexes were passed to OpCompositeExtract, but the Result Type is 1172 // different from the Base Composite type. 1173 TEST_F(ValidateComposites, CompositeExtractNoIndexesBad) { 1174 std::ostringstream spirv; 1175 spirv << GetHeaderForTestsFromValId() << std::endl; 1176 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; 1177 spirv << "%float_entry = OpCompositeExtract %float %matrix" << std::endl; 1178 spirv << R"(OpReturn 1179 OpFunctionEnd)"; 1180 CompileSuccessfully(spirv.str()); 1181 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1182 EXPECT_THAT(getDiagnosticString(), 1183 HasSubstr("Result type (OpTypeFloat) does not match the type " 1184 "that results from indexing into the composite " 1185 "(OpTypeMatrix).")); 1186 } 1187 1188 // Valid: No Indexes were passed to OpCompositeInsert, and the type of the 1189 // Object<id> argument matches the Composite type. 1190 TEST_F(ValidateComposites, CompositeInsertMissingIndexesGood) { 1191 std::ostringstream spirv; 1192 spirv << GetHeaderForTestsFromValId() << std::endl; 1193 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; 1194 spirv << "%matrix_2 = OpLoad %mat4x3 %my_matrix" << std::endl; 1195 spirv << "%new_composite = OpCompositeInsert %mat4x3 %matrix_2 %matrix"; 1196 spirv << R"( 1197 OpReturn 1198 OpFunctionEnd)"; 1199 CompileSuccessfully(spirv.str()); 1200 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 1201 } 1202 1203 // Invalid: No Indexes were passed to OpCompositeInsert, but the type of the 1204 // Object<id> argument does not match the Composite type. 1205 TEST_F(ValidateComposites, CompositeInsertMissingIndexesBad) { 1206 std::ostringstream spirv; 1207 spirv << GetHeaderForTestsFromValId() << std::endl; 1208 spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl; 1209 spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix"; 1210 spirv << R"( 1211 OpReturn 1212 OpFunctionEnd)"; 1213 CompileSuccessfully(spirv.str()); 1214 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1215 EXPECT_THAT(getDiagnosticString(), 1216 HasSubstr("The Object type (OpTypeInt) does not match the type " 1217 "that results from indexing into the Composite " 1218 "(OpTypeMatrix).")); 1219 } 1220 1221 // Valid: Tests that we can index into Struct, Array, Matrix, and Vector! 1222 TEST_F(ValidateComposites, CompositeExtractInsertIndexIntoAllTypesGood) { 1223 // indexes that we are passing are: 0, 3, 1, 2, 0 1224 // 0 will select the struct_s within the base struct (blockName) 1225 // 3 will select the Array that contains 5 matrices 1226 // 1 will select the Matrix that is at index 1 of the array 1227 // 2 will select the column (which is a vector) within the matrix at index 2 1228 // 0 will select the element at the index 0 of the vector. (which is a float). 1229 std::ostringstream spirv; 1230 spirv << GetHeaderForTestsFromValId() << R"( 1231 %myblock = OpLoad %struct_blockName %blockName_var 1232 %ss = OpCompositeExtract %struct_s %myblock 0 1233 %sa = OpCompositeExtract %array5_mat4x3 %myblock 0 3 1234 %sm = OpCompositeExtract %mat4x3 %myblock 0 3 1 1235 %sc = OpCompositeExtract %v3float %myblock 0 3 1 2 1236 %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1237 ; 1238 ; Now let's insert back at different levels... 1239 ; 1240 %b1 = OpCompositeInsert %struct_blockName %ss %myblock 0 1241 %b2 = OpCompositeInsert %struct_blockName %sa %myblock 0 3 1242 %b3 = OpCompositeInsert %struct_blockName %sm %myblock 0 3 1 1243 %b4 = OpCompositeInsert %struct_blockName %sc %myblock 0 3 1 2 1244 %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1245 OpReturn 1246 OpFunctionEnd 1247 )"; 1248 1249 CompileSuccessfully(spirv.str()); 1250 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 1251 } 1252 1253 // Invalid. More indexes are provided than needed for OpCompositeExtract. 1254 TEST_F(ValidateComposites, CompositeExtractReachedScalarBad) { 1255 // indexes that we are passing are: 0, 3, 1, 2, 0 1256 // 0 will select the struct_s within the base struct (blockName) 1257 // 3 will select the Array that contains 5 matrices 1258 // 1 will select the Matrix that is at index 1 of the array 1259 // 2 will select the column (which is a vector) within the matrix at index 2 1260 // 0 will select the element at the index 0 of the vector. (which is a float). 1261 std::ostringstream spirv; 1262 spirv << GetHeaderForTestsFromValId() << R"( 1263 %myblock = OpLoad %struct_blockName %blockName_var 1264 %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1 1265 OpReturn 1266 OpFunctionEnd 1267 )"; 1268 1269 CompileSuccessfully(spirv.str()); 1270 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1271 EXPECT_THAT(getDiagnosticString(), 1272 HasSubstr("Reached non-composite type while indexes still remain " 1273 "to be traversed.")); 1274 } 1275 1276 // Invalid. More indexes are provided than needed for OpCompositeInsert. 1277 TEST_F(ValidateComposites, CompositeInsertReachedScalarBad) { 1278 // indexes that we are passing are: 0, 3, 1, 2, 0 1279 // 0 will select the struct_s within the base struct (blockName) 1280 // 3 will select the Array that contains 5 matrices 1281 // 1 will select the Matrix that is at index 1 of the array 1282 // 2 will select the column (which is a vector) within the matrix at index 2 1283 // 0 will select the element at the index 0 of the vector. (which is a float). 1284 std::ostringstream spirv; 1285 spirv << GetHeaderForTestsFromValId() << R"( 1286 %myblock = OpLoad %struct_blockName %blockName_var 1287 %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1288 %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1 1289 OpReturn 1290 OpFunctionEnd 1291 )"; 1292 1293 CompileSuccessfully(spirv.str()); 1294 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1295 EXPECT_THAT(getDiagnosticString(), 1296 HasSubstr("Reached non-composite type while indexes still remain " 1297 "to be traversed.")); 1298 } 1299 1300 // Invalid. Result type doesn't match the type we get from indexing into 1301 // the composite. 1302 TEST_F(ValidateComposites, 1303 CompositeExtractResultTypeDoesntMatchIndexedTypeBad) { 1304 // indexes that we are passing are: 0, 3, 1, 2, 0 1305 // 0 will select the struct_s within the base struct (blockName) 1306 // 3 will select the Array that contains 5 matrices 1307 // 1 will select the Matrix that is at index 1 of the array 1308 // 2 will select the column (which is a vector) within the matrix at index 2 1309 // 0 will select the element at the index 0 of the vector. (which is a float). 1310 std::ostringstream spirv; 1311 spirv << GetHeaderForTestsFromValId() << R"( 1312 %myblock = OpLoad %struct_blockName %blockName_var 1313 %fl = OpCompositeExtract %int %myblock 0 3 1 2 0 1314 OpReturn 1315 OpFunctionEnd 1316 )"; 1317 1318 CompileSuccessfully(spirv.str()); 1319 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1320 EXPECT_THAT(getDiagnosticString(), 1321 HasSubstr("Result type (OpTypeInt) does not match the type that " 1322 "results from indexing into the composite " 1323 "(OpTypeFloat).")); 1324 } 1325 1326 // Invalid. Given object type doesn't match the type we get from indexing into 1327 // the composite. 1328 TEST_F(ValidateComposites, CompositeInsertObjectTypeDoesntMatchIndexedTypeBad) { 1329 // indexes that we are passing are: 0, 3, 1, 2, 0 1330 // 0 will select the struct_s within the base struct (blockName) 1331 // 3 will select the Array that contains 5 matrices 1332 // 1 will select the Matrix that is at index 1 of the array 1333 // 2 will select the column (which is a vector) within the matrix at index 2 1334 // 0 will select the element at the index 0 of the vector. (which is a float). 1335 // We are trying to insert an integer where we should be inserting a float. 1336 std::ostringstream spirv; 1337 spirv << GetHeaderForTestsFromValId() << R"( 1338 %myblock = OpLoad %struct_blockName %blockName_var 1339 %b5 = OpCompositeInsert %struct_blockName %int_0 %myblock 0 3 1 2 0 1340 OpReturn 1341 OpFunctionEnd 1342 )"; 1343 1344 CompileSuccessfully(spirv.str()); 1345 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1346 EXPECT_THAT(getDiagnosticString(), 1347 HasSubstr("The Object type (OpTypeInt) does not match the type " 1348 "that results from indexing into the Composite " 1349 "(OpTypeFloat).")); 1350 } 1351 1352 // Invalid. Index into a struct is larger than the number of struct members. 1353 TEST_F(ValidateComposites, CompositeExtractStructIndexOutOfBoundBad) { 1354 // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3. 1355 std::ostringstream spirv; 1356 spirv << GetHeaderForTestsFromValId() << R"( 1357 %myblock = OpLoad %struct_blockName %blockName_var 1358 %ss = OpCompositeExtract %struct_s %myblock 3 1359 OpReturn 1360 OpFunctionEnd 1361 )"; 1362 1363 CompileSuccessfully(spirv.str()); 1364 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1365 EXPECT_THAT(getDiagnosticString(), 1366 HasSubstr("Index is out of bounds, can not find index 3 in the " 1367 "structure <id> '25'. This structure has 3 members. " 1368 "Largest valid index is 2.")); 1369 } 1370 1371 // Invalid. Index into a struct is larger than the number of struct members. 1372 TEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) { 1373 // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3. 1374 std::ostringstream spirv; 1375 spirv << GetHeaderForTestsFromValId() << R"( 1376 %myblock = OpLoad %struct_blockName %blockName_var 1377 %ss = OpCompositeExtract %struct_s %myblock 0 1378 %new_composite = OpCompositeInsert %struct_blockName %ss %myblock 3 1379 OpReturn 1380 OpFunctionEnd 1381 )"; 1382 1383 CompileSuccessfully(spirv.str()); 1384 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1385 EXPECT_THAT( 1386 getDiagnosticString(), 1387 HasSubstr("Index is out of bounds, can not find index 3 in the structure " 1388 "<id> '25'. This structure has 3 members. Largest valid index " 1389 "is 2.")); 1390 } 1391 1392 // #1403: Ensure that the default spec constant value is not used to check the 1393 // extract index. 1394 TEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) { 1395 std::string spirv = R"( 1396 OpCapability Kernel 1397 OpCapability Linkage 1398 OpMemoryModel Logical OpenCL 1399 OpDecorate %spec_const SpecId 1 1400 %void = OpTypeVoid 1401 %uint = OpTypeInt 32 0 1402 %spec_const = OpSpecConstant %uint 3 1403 %uint_array = OpTypeArray %uint %spec_const 1404 %undef = OpUndef %uint_array 1405 %voidf = OpTypeFunction %void 1406 %func = OpFunction %void None %voidf 1407 %1 = OpLabel 1408 %2 = OpCompositeExtract %uint %undef 4 1409 OpReturn 1410 OpFunctionEnd 1411 )"; 1412 1413 CompileSuccessfully(spirv); 1414 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 1415 } 1416 1417 // #1403: Ensure that spec constant ops do not produce false positives. 1418 TEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) { 1419 std::string spirv = R"( 1420 OpCapability Kernel 1421 OpCapability Linkage 1422 OpMemoryModel Logical OpenCL 1423 OpDecorate %spec_const SpecId 1 1424 %void = OpTypeVoid 1425 %uint = OpTypeInt 32 0 1426 %const = OpConstant %uint 1 1427 %spec_const = OpSpecConstant %uint 3 1428 %spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const 1429 %uint_array = OpTypeArray %uint %spec_const_op 1430 %undef = OpUndef %uint_array 1431 %voidf = OpTypeFunction %void 1432 %func = OpFunction %void None %voidf 1433 %1 = OpLabel 1434 %2 = OpCompositeExtract %uint %undef 4 1435 OpReturn 1436 OpFunctionEnd 1437 )"; 1438 1439 CompileSuccessfully(spirv); 1440 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 1441 } 1442 1443 // #1403: Ensure that the default spec constant value is not used to check the 1444 // size of the array for a composite construct. This code has limited actual 1445 // value as it is incorrect unless the specialization constant is assigned the 1446 // value of 2, but it is still a valid module. 1447 TEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) { 1448 std::string spirv = R"( 1449 OpCapability Kernel 1450 OpCapability Linkage 1451 OpMemoryModel Logical OpenCL 1452 OpDecorate %spec_const SpecId 1 1453 %void = OpTypeVoid 1454 %uint = OpTypeInt 32 0 1455 %uint_0 = OpConstant %uint 0 1456 %spec_const = OpSpecConstant %uint 3 1457 %uint_array = OpTypeArray %uint %spec_const 1458 %voidf = OpTypeFunction %void 1459 %func = OpFunction %void None %voidf 1460 %1 = OpLabel 1461 %2 = OpCompositeConstruct %uint_array %uint_0 %uint_0 1462 OpReturn 1463 OpFunctionEnd 1464 )"; 1465 1466 CompileSuccessfully(spirv); 1467 EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()); 1468 } 1469 1470 TEST_F(ValidateComposites, ExtractDynamicLabelIndex) { 1471 const std::string spirv = R"( 1472 OpCapability Shader 1473 OpCapability Linkage 1474 OpMemoryModel Logical GLSL450 1475 %void = OpTypeVoid 1476 %float = OpTypeFloat 32 1477 %v4float = OpTypeVector %float 4 1478 %void_fn = OpTypeFunction %void 1479 %float_0 = OpConstant %float 0 1480 %v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 1481 %func = OpFunction %void None %void_fn 1482 %1 = OpLabel 1483 %ex = OpVectorExtractDynamic %float %v4float_0 %1 1484 OpReturn 1485 OpFunctionEnd 1486 )"; 1487 1488 CompileSuccessfully(spirv); 1489 EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions()); 1490 EXPECT_THAT(getDiagnosticString(), 1491 HasSubstr("Expected Index to be int scalar")); 1492 } 1493 1494 } // namespace 1495 } // namespace val 1496 } // namespace spvtools 1497