1// Copyright (c) 2019 Google LLC 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 "source/fuzz/fuzzer_pass_donate_modules.h" 16 17#include <algorithm> 18 19#include "gtest/gtest.h" 20#include "source/fuzz/pseudo_random_generator.h" 21#include "test/fuzz/fuzz_test_util.h" 22 23namespace spvtools { 24namespace fuzz { 25namespace { 26 27TEST(FuzzerPassDonateModulesTest, BasicDonation) { 28 std::string recipient_shader = R"( 29 OpCapability Shader 30 %1 = OpExtInstImport "GLSL.std.450" 31 OpMemoryModel Logical GLSL450 32 OpEntryPoint Fragment %4 "main" 33 OpExecutionMode %4 OriginUpperLeft 34 OpSource ESSL 310 35 OpName %4 "main" 36 OpName %10 "m" 37 OpName %16 "v" 38 OpDecorate %16 RelaxedPrecision 39 OpDecorate %20 RelaxedPrecision 40 %2 = OpTypeVoid 41 %3 = OpTypeFunction %2 42 %6 = OpTypeFloat 32 43 %7 = OpTypeVector %6 3 44 %8 = OpTypeMatrix %7 2 45 %9 = OpTypePointer Private %8 46 %10 = OpVariable %9 Private 47 %11 = OpTypeInt 32 1 48 %12 = OpConstant %11 0 49 %13 = OpTypeInt 32 0 50 %14 = OpTypeVector %13 4 51 %15 = OpTypePointer Private %14 52 %16 = OpVariable %15 Private 53 %17 = OpConstant %13 2 54 %18 = OpTypePointer Private %13 55 %22 = OpConstant %13 0 56 %23 = OpTypePointer Private %6 57 %4 = OpFunction %2 None %3 58 %5 = OpLabel 59 %19 = OpAccessChain %18 %16 %17 60 %20 = OpLoad %13 %19 61 %21 = OpConvertUToF %6 %20 62 %24 = OpAccessChain %23 %10 %12 %22 63 OpStore %24 %21 64 OpReturn 65 OpFunctionEnd 66 )"; 67 68 std::string donor_shader = R"( 69 OpCapability Shader 70 %1 = OpExtInstImport "GLSL.std.450" 71 OpMemoryModel Logical GLSL450 72 OpEntryPoint Fragment %4 "main" 73 OpExecutionMode %4 OriginUpperLeft 74 OpSource ESSL 310 75 OpName %4 "main" 76 OpName %12 "bar(mf24;" 77 OpName %11 "m" 78 OpName %20 "foo(vu4;" 79 OpName %19 "v" 80 OpName %23 "x" 81 OpName %26 "param" 82 OpName %29 "result" 83 OpName %31 "i" 84 OpName %81 "param" 85 %2 = OpTypeVoid 86 %3 = OpTypeFunction %2 87 %6 = OpTypeFloat 32 88 %7 = OpTypeVector %6 4 89 %8 = OpTypeMatrix %7 2 90 %9 = OpTypePointer Function %8 91 %10 = OpTypeFunction %6 %9 92 %14 = OpTypeInt 32 0 93 %15 = OpTypeVector %14 4 94 %16 = OpTypePointer Function %15 95 %17 = OpTypeInt 32 1 96 %18 = OpTypeFunction %17 %16 97 %22 = OpTypePointer Function %17 98 %24 = OpConstant %14 2 99 %25 = OpConstantComposite %15 %24 %24 %24 %24 100 %28 = OpTypePointer Function %6 101 %30 = OpConstant %6 0 102 %32 = OpConstant %17 0 103 %39 = OpConstant %17 10 104 %40 = OpTypeBool 105 %43 = OpConstant %17 3 106 %50 = OpConstant %17 1 107 %55 = OpConstant %14 0 108 %56 = OpTypePointer Function %14 109 %59 = OpConstant %14 1 110 %65 = OpConstant %17 2 111 %68 = OpConstant %6 1 112 %69 = OpConstant %6 2 113 %70 = OpConstant %6 3 114 %71 = OpConstant %6 4 115 %72 = OpConstant %14 3 116 %76 = OpConstant %6 6 117 %77 = OpConstant %6 7 118 %4 = OpFunction %2 None %3 119 %5 = OpLabel 120 %23 = OpVariable %22 Function 121 %26 = OpVariable %16 Function 122 OpStore %26 %25 123 %27 = OpFunctionCall %17 %20 %26 124 OpStore %23 %27 125 OpReturn 126 OpFunctionEnd 127 %12 = OpFunction %6 None %10 128 %11 = OpFunctionParameter %9 129 %13 = OpLabel 130 %29 = OpVariable %28 Function 131 %31 = OpVariable %22 Function 132 OpStore %29 %30 133 OpStore %31 %32 134 OpBranch %33 135 %33 = OpLabel 136 OpLoopMerge %35 %36 None 137 OpBranch %37 138 %37 = OpLabel 139 %38 = OpLoad %17 %31 140 %41 = OpSLessThan %40 %38 %39 141 OpBranchConditional %41 %34 %35 142 %34 = OpLabel 143 %42 = OpLoad %17 %31 144 %44 = OpExtInst %17 %1 SClamp %42 %32 %43 145 %45 = OpAccessChain %28 %11 %32 %44 146 %46 = OpLoad %6 %45 147 %47 = OpLoad %6 %29 148 %48 = OpFAdd %6 %47 %46 149 OpStore %29 %48 150 OpBranch %36 151 %36 = OpLabel 152 %49 = OpLoad %17 %31 153 %51 = OpIAdd %17 %49 %50 154 OpStore %31 %51 155 OpBranch %33 156 %35 = OpLabel 157 %52 = OpLoad %6 %29 158 OpReturnValue %52 159 OpFunctionEnd 160 %20 = OpFunction %17 None %18 161 %19 = OpFunctionParameter %16 162 %21 = OpLabel 163 %81 = OpVariable %9 Function 164 %57 = OpAccessChain %56 %19 %55 165 %58 = OpLoad %14 %57 166 %60 = OpAccessChain %56 %19 %59 167 %61 = OpLoad %14 %60 168 %62 = OpUGreaterThan %40 %58 %61 169 OpSelectionMerge %64 None 170 OpBranchConditional %62 %63 %67 171 %63 = OpLabel 172 OpReturnValue %65 173 %67 = OpLabel 174 %73 = OpAccessChain %56 %19 %72 175 %74 = OpLoad %14 %73 176 %75 = OpConvertUToF %6 %74 177 %78 = OpCompositeConstruct %7 %30 %68 %69 %70 178 %79 = OpCompositeConstruct %7 %71 %75 %76 %77 179 %80 = OpCompositeConstruct %8 %78 %79 180 OpStore %81 %80 181 %82 = OpFunctionCall %6 %12 %81 182 %83 = OpConvertFToS %17 %82 183 OpReturnValue %83 184 %64 = OpLabel 185 %85 = OpUndef %17 186 OpReturnValue %85 187 OpFunctionEnd 188 )"; 189 190 const auto env = SPV_ENV_UNIVERSAL_1_3; 191 const auto consumer = nullptr; 192 spvtools::ValidatorOptions validator_options; 193 194 const auto recipient_context = 195 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 196 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 197 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 198 199 const auto donor_context = 200 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 201 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 202 donor_context.get(), validator_options, kConsoleMessageConsumer)); 203 204 TransformationContext transformation_context( 205 MakeUnique<FactManager>(recipient_context.get()), validator_options); 206 207 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 208 false); 209 protobufs::TransformationSequence transformation_sequence; 210 211 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 212 &transformation_context, &fuzzer_context, 213 &transformation_sequence, false, {}); 214 215 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 216 217 // We just check that the result is valid. Checking to what it should be 218 // exactly equal to would be very fragile. 219 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 220 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 221} 222 223TEST(FuzzerPassDonateModulesTest, DonationWithUniforms) { 224 // This test checks that when donating a shader that contains uniforms, 225 // uniform variables and associated pointer types are demoted from having 226 // Uniform storage class to Private storage class. 227 std::string recipient_and_donor_shader = R"( 228 OpCapability Shader 229 %1 = OpExtInstImport "GLSL.std.450" 230 OpMemoryModel Logical GLSL450 231 OpEntryPoint Fragment %4 "main" 232 OpExecutionMode %4 OriginUpperLeft 233 OpSource ESSL 310 234 OpMemberDecorate %9 0 Offset 0 235 OpDecorate %9 Block 236 OpDecorate %11 DescriptorSet 0 237 OpDecorate %11 Binding 0 238 OpMemberDecorate %19 0 Offset 0 239 OpDecorate %19 Block 240 OpDecorate %21 DescriptorSet 0 241 OpDecorate %21 Binding 1 242 %2 = OpTypeVoid 243 %3 = OpTypeFunction %2 244 %6 = OpTypeFloat 32 245 %7 = OpTypePointer Function %6 246 %9 = OpTypeStruct %6 247 %10 = OpTypePointer Uniform %9 248 %11 = OpVariable %10 Uniform 249 %12 = OpTypeInt 32 1 250 %13 = OpConstant %12 0 251 %14 = OpTypePointer Uniform %6 252 %17 = OpTypePointer Function %12 253 %19 = OpTypeStruct %12 254 %20 = OpTypePointer Uniform %19 255 %21 = OpVariable %20 Uniform 256 %22 = OpTypePointer Uniform %12 257 %4 = OpFunction %2 None %3 258 %5 = OpLabel 259 %8 = OpVariable %7 Function 260 %18 = OpVariable %17 Function 261 %15 = OpAccessChain %14 %11 %13 262 %16 = OpLoad %6 %15 263 OpStore %8 %16 264 %23 = OpAccessChain %22 %21 %13 265 %24 = OpLoad %12 %23 266 OpStore %18 %24 267 OpReturn 268 OpFunctionEnd 269 )"; 270 271 const auto env = SPV_ENV_UNIVERSAL_1_3; 272 const auto consumer = nullptr; 273 spvtools::ValidatorOptions validator_options; 274 275 const auto recipient_context = BuildModule( 276 env, consumer, recipient_and_donor_shader, kFuzzAssembleOption); 277 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 278 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 279 280 const auto donor_context = BuildModule( 281 env, consumer, recipient_and_donor_shader, kFuzzAssembleOption); 282 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 283 donor_context.get(), validator_options, kConsoleMessageConsumer)); 284 285 TransformationContext transformation_context( 286 MakeUnique<FactManager>(recipient_context.get()), validator_options); 287 288 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 289 false); 290 protobufs::TransformationSequence transformation_sequence; 291 292 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 293 &transformation_context, &fuzzer_context, 294 &transformation_sequence, false, {}); 295 296 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 297 298 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 299 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 300 301 std::string after_transformation = R"( 302 OpCapability Shader 303 %1 = OpExtInstImport "GLSL.std.450" 304 OpMemoryModel Logical GLSL450 305 OpEntryPoint Fragment %4 "main" 306 OpExecutionMode %4 OriginUpperLeft 307 OpSource ESSL 310 308 OpMemberDecorate %9 0 Offset 0 309 OpDecorate %9 Block 310 OpDecorate %11 DescriptorSet 0 311 OpDecorate %11 Binding 0 312 OpMemberDecorate %19 0 Offset 0 313 OpDecorate %19 Block 314 OpDecorate %21 DescriptorSet 0 315 OpDecorate %21 Binding 1 316 %2 = OpTypeVoid 317 %3 = OpTypeFunction %2 318 %6 = OpTypeFloat 32 319 %7 = OpTypePointer Function %6 320 %9 = OpTypeStruct %6 321 %10 = OpTypePointer Uniform %9 322 %11 = OpVariable %10 Uniform 323 %12 = OpTypeInt 32 1 324 %13 = OpConstant %12 0 325 %14 = OpTypePointer Uniform %6 326 %17 = OpTypePointer Function %12 327 %19 = OpTypeStruct %12 328 %20 = OpTypePointer Uniform %19 329 %21 = OpVariable %20 Uniform 330 %22 = OpTypePointer Uniform %12 331 %100 = OpTypePointer Function %6 332 %101 = OpTypeStruct %6 333 %102 = OpTypePointer Private %101 334 %104 = OpConstant %6 0 335 %105 = OpConstantComposite %101 %104 336 %103 = OpVariable %102 Private %105 337 %106 = OpConstant %12 0 338 %107 = OpTypePointer Private %6 339 %108 = OpTypePointer Function %12 340 %109 = OpTypeStruct %12 341 %110 = OpTypePointer Private %109 342 %112 = OpConstantComposite %109 %13 343 %111 = OpVariable %110 Private %112 344 %113 = OpTypePointer Private %12 345 %4 = OpFunction %2 None %3 346 %5 = OpLabel 347 %8 = OpVariable %7 Function 348 %18 = OpVariable %17 Function 349 %15 = OpAccessChain %14 %11 %13 350 %16 = OpLoad %6 %15 351 OpStore %8 %16 352 %23 = OpAccessChain %22 %21 %13 353 %24 = OpLoad %12 %23 354 OpStore %18 %24 355 OpReturn 356 OpFunctionEnd 357 %114 = OpFunction %2 None %3 358 %115 = OpLabel 359 %116 = OpVariable %100 Function %104 360 %117 = OpVariable %108 Function %13 361 %118 = OpAccessChain %107 %103 %106 362 %119 = OpLoad %6 %118 363 OpStore %116 %119 364 %120 = OpAccessChain %113 %111 %106 365 %121 = OpLoad %12 %120 366 OpStore %117 %121 367 OpReturn 368 OpFunctionEnd 369 )"; 370 ASSERT_TRUE(IsEqual(env, after_transformation, recipient_context.get())); 371} 372 373TEST(FuzzerPassDonateModulesTest, DonationWithInputAndOutputVariables) { 374 // This test checks that when donating a shader that contains input and output 375 // variables, such variables and associated pointer types are demoted to have 376 // the Private storage class. 377 std::string recipient_and_donor_shader = R"( 378 OpCapability Shader 379 %1 = OpExtInstImport "GLSL.std.450" 380 OpMemoryModel Logical GLSL450 381 OpEntryPoint Fragment %4 "main" %9 %11 382 OpExecutionMode %4 OriginUpperLeft 383 OpSource ESSL 310 384 OpDecorate %9 Location 0 385 OpDecorate %11 Location 1 386 %2 = OpTypeVoid 387 %3 = OpTypeFunction %2 388 %6 = OpTypeFloat 32 389 %7 = OpTypeVector %6 4 390 %8 = OpTypePointer Output %7 391 %9 = OpVariable %8 Output 392 %10 = OpTypePointer Input %7 393 %11 = OpVariable %10 Input 394 %4 = OpFunction %2 None %3 395 %5 = OpLabel 396 %12 = OpLoad %7 %11 397 OpStore %9 %12 398 OpReturn 399 OpFunctionEnd 400 )"; 401 402 const auto env = SPV_ENV_UNIVERSAL_1_3; 403 const auto consumer = nullptr; 404 spvtools::ValidatorOptions validator_options; 405 406 const auto recipient_context = BuildModule( 407 env, consumer, recipient_and_donor_shader, kFuzzAssembleOption); 408 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 409 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 410 411 const auto donor_context = BuildModule( 412 env, consumer, recipient_and_donor_shader, kFuzzAssembleOption); 413 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 414 donor_context.get(), validator_options, kConsoleMessageConsumer)); 415 416 TransformationContext transformation_context( 417 MakeUnique<FactManager>(recipient_context.get()), validator_options); 418 419 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 420 false); 421 protobufs::TransformationSequence transformation_sequence; 422 423 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 424 &transformation_context, &fuzzer_context, 425 &transformation_sequence, false, {}); 426 427 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 428 429 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 430 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 431 432 std::string after_transformation = R"( 433 OpCapability Shader 434 %1 = OpExtInstImport "GLSL.std.450" 435 OpMemoryModel Logical GLSL450 436 OpEntryPoint Fragment %4 "main" %9 %11 437 OpExecutionMode %4 OriginUpperLeft 438 OpSource ESSL 310 439 OpDecorate %9 Location 0 440 OpDecorate %11 Location 1 441 %2 = OpTypeVoid 442 %3 = OpTypeFunction %2 443 %6 = OpTypeFloat 32 444 %7 = OpTypeVector %6 4 445 %8 = OpTypePointer Output %7 446 %9 = OpVariable %8 Output 447 %10 = OpTypePointer Input %7 448 %11 = OpVariable %10 Input 449 %100 = OpTypePointer Private %7 450 %102 = OpConstant %6 0 451 %103 = OpConstantComposite %7 %102 %102 %102 %102 452 %101 = OpVariable %100 Private %103 453 %104 = OpTypePointer Private %7 454 %105 = OpVariable %104 Private %103 455 %4 = OpFunction %2 None %3 456 %5 = OpLabel 457 %12 = OpLoad %7 %11 458 OpStore %9 %12 459 OpReturn 460 OpFunctionEnd 461 %106 = OpFunction %2 None %3 462 %107 = OpLabel 463 %108 = OpLoad %7 %105 464 OpStore %101 %108 465 OpReturn 466 OpFunctionEnd 467 )"; 468 ASSERT_TRUE(IsEqual(env, after_transformation, recipient_context.get())); 469} 470 471TEST(FuzzerPassDonateModulesTest, DonateFunctionTypeWithDifferentPointers) { 472 std::string recipient_and_donor_shader = R"( 473 OpCapability Shader 474 %1 = OpExtInstImport "GLSL.std.450" 475 OpMemoryModel Logical GLSL450 476 OpEntryPoint Fragment %4 "main" 477 OpExecutionMode %4 OriginUpperLeft 478 OpSource ESSL 310 479 %2 = OpTypeVoid 480 %3 = OpTypeFunction %2 481 %6 = OpTypeInt 32 0 482 %7 = OpTypePointer Function %6 483 %8 = OpTypeFunction %2 %7 484 %4 = OpFunction %2 None %3 485 %5 = OpLabel 486 %9 = OpVariable %7 Function 487 %10 = OpFunctionCall %2 %11 %9 488 OpReturn 489 OpFunctionEnd 490 %11 = OpFunction %2 None %8 491 %12 = OpFunctionParameter %7 492 %13 = OpLabel 493 OpReturn 494 OpFunctionEnd 495 )"; 496 497 const auto env = SPV_ENV_UNIVERSAL_1_5; 498 const auto consumer = nullptr; 499 spvtools::ValidatorOptions validator_options; 500 501 const auto recipient_context = BuildModule( 502 env, consumer, recipient_and_donor_shader, kFuzzAssembleOption); 503 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 504 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 505 506 const auto donor_context = BuildModule( 507 env, consumer, recipient_and_donor_shader, kFuzzAssembleOption); 508 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 509 donor_context.get(), validator_options, kConsoleMessageConsumer)); 510 511 TransformationContext transformation_context( 512 MakeUnique<FactManager>(recipient_context.get()), validator_options); 513 514 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 515 false); 516 protobufs::TransformationSequence transformation_sequence; 517 518 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 519 &transformation_context, &fuzzer_context, 520 &transformation_sequence, false, {}); 521 522 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 523 524 // We just check that the result is valid. Checking to what it should be 525 // exactly equal to would be very fragile. 526 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 527 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 528} 529 530TEST(FuzzerPassDonateModulesTest, DonateOpConstantNull) { 531 std::string recipient_shader = R"( 532 OpCapability Shader 533 OpCapability ImageQuery 534 OpCapability VariablePointers 535 %1 = OpExtInstImport "GLSL.std.450" 536 OpMemoryModel Logical GLSL450 537 OpEntryPoint Fragment %4 "main" 538 OpExecutionMode %4 OriginUpperLeft 539 OpSource ESSL 320 540 OpSourceExtension "GL_EXT_samplerless_texture_functions" 541 %2 = OpTypeVoid 542 %3 = OpTypeFunction %2 543 %4 = OpFunction %2 None %3 544 %5 = OpLabel 545 OpReturn 546 OpFunctionEnd 547 )"; 548 549 std::string donor_shader = R"( 550 OpCapability Shader 551 OpCapability ImageQuery 552 OpCapability VariablePointers 553 %1 = OpExtInstImport "GLSL.std.450" 554 OpMemoryModel Logical GLSL450 555 OpEntryPoint Fragment %4 "main" 556 OpExecutionMode %4 OriginUpperLeft 557 OpSource ESSL 320 558 %2 = OpTypeVoid 559 %3 = OpTypeFunction %2 560 %6 = OpTypeFloat 32 561 %7 = OpTypePointer Private %6 562 %8 = OpConstantNull %7 563 %4 = OpFunction %2 None %3 564 %5 = OpLabel 565 OpReturn 566 OpFunctionEnd 567 )"; 568 569 const auto env = SPV_ENV_UNIVERSAL_1_3; 570 const auto consumer = nullptr; 571 spvtools::ValidatorOptions validator_options; 572 573 const auto recipient_context = 574 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 575 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 576 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 577 578 const auto donor_context = 579 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 580 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 581 donor_context.get(), validator_options, kConsoleMessageConsumer)); 582 583 TransformationContext transformation_context( 584 MakeUnique<FactManager>(recipient_context.get()), validator_options); 585 586 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 587 false); 588 protobufs::TransformationSequence transformation_sequence; 589 590 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 591 &transformation_context, &fuzzer_context, 592 &transformation_sequence, false, {}); 593 594 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 595 596 // We just check that the result is valid. Checking to what it should be 597 // exactly equal to would be very fragile. 598 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 599 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 600} 601 602TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImages) { 603 std::string recipient_shader = R"( 604 OpCapability Shader 605 OpCapability ImageQuery 606 %1 = OpExtInstImport "GLSL.std.450" 607 OpMemoryModel Logical GLSL450 608 OpEntryPoint Fragment %4 "main" 609 OpExecutionMode %4 OriginUpperLeft 610 OpSource ESSL 320 611 OpSourceExtension "GL_EXT_samplerless_texture_functions" 612 %2 = OpTypeVoid 613 %3 = OpTypeFunction %2 614 %4 = OpFunction %2 None %3 615 %5 = OpLabel 616 OpReturn 617 OpFunctionEnd 618 )"; 619 620 std::string donor_shader = R"( 621 OpCapability Shader 622 OpCapability ImageQuery 623 %1 = OpExtInstImport "GLSL.std.450" 624 OpMemoryModel Logical GLSL450 625 OpEntryPoint Fragment %4 "main" 626 OpExecutionMode %4 OriginUpperLeft 627 OpSource ESSL 320 628 OpSourceExtension "GL_EXT_samplerless_texture_functions" 629 OpName %4 "main" 630 OpName %10 "mySampler" 631 OpName %21 "myTexture" 632 OpName %33 "v" 633 OpDecorate %10 RelaxedPrecision 634 OpDecorate %10 DescriptorSet 0 635 OpDecorate %10 Binding 0 636 OpDecorate %11 RelaxedPrecision 637 OpDecorate %21 RelaxedPrecision 638 OpDecorate %21 DescriptorSet 0 639 OpDecorate %21 Binding 1 640 OpDecorate %22 RelaxedPrecision 641 OpDecorate %34 RelaxedPrecision 642 OpDecorate %40 RelaxedPrecision 643 OpDecorate %42 RelaxedPrecision 644 OpDecorate %43 RelaxedPrecision 645 %2 = OpTypeVoid 646 %3 = OpTypeFunction %2 647 %6 = OpTypeFloat 32 648 %7 = OpTypeImage %6 2D 0 0 0 1 Unknown 649 %8 = OpTypeSampledImage %7 650 %9 = OpTypePointer UniformConstant %8 651 %10 = OpVariable %9 UniformConstant 652 %12 = OpTypeInt 32 1 653 %13 = OpConstant %12 2 654 %15 = OpTypeVector %12 2 655 %17 = OpTypeInt 32 0 656 %18 = OpConstant %17 0 657 %20 = OpTypePointer UniformConstant %7 658 %21 = OpVariable %20 UniformConstant 659 %23 = OpConstant %12 1 660 %25 = OpConstant %17 1 661 %27 = OpTypeBool 662 %31 = OpTypeVector %6 4 663 %32 = OpTypePointer Function %31 664 %35 = OpConstantComposite %15 %23 %23 665 %36 = OpConstant %12 3 666 %37 = OpConstant %12 4 667 %38 = OpConstantComposite %15 %36 %37 668 %4 = OpFunction %2 None %3 669 %5 = OpLabel 670 %33 = OpVariable %32 Function 671 %11 = OpLoad %8 %10 672 %14 = OpImage %7 %11 673 %16 = OpImageQuerySizeLod %15 %14 %13 674 %19 = OpCompositeExtract %12 %16 0 675 %22 = OpLoad %7 %21 676 %24 = OpImageQuerySizeLod %15 %22 %23 677 %26 = OpCompositeExtract %12 %24 1 678 %28 = OpSGreaterThan %27 %19 %26 679 OpSelectionMerge %30 None 680 OpBranchConditional %28 %29 %41 681 %29 = OpLabel 682 %34 = OpLoad %8 %10 683 %39 = OpImage %7 %34 684 %40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38 685 OpStore %33 %40 686 OpBranch %30 687 %41 = OpLabel 688 %42 = OpLoad %7 %21 689 %43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38 690 OpStore %33 %43 691 OpBranch %30 692 %30 = OpLabel 693 OpReturn 694 OpFunctionEnd 695 )"; 696 697 const auto env = SPV_ENV_UNIVERSAL_1_3; 698 const auto consumer = nullptr; 699 spvtools::ValidatorOptions validator_options; 700 701 const auto recipient_context = 702 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 703 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 704 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 705 706 const auto donor_context = 707 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 708 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 709 donor_context.get(), validator_options, kConsoleMessageConsumer)); 710 711 TransformationContext transformation_context( 712 MakeUnique<FactManager>(recipient_context.get()), validator_options); 713 714 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 715 false); 716 protobufs::TransformationSequence transformation_sequence; 717 718 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 719 &transformation_context, &fuzzer_context, 720 &transformation_sequence, false, {}); 721 722 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 723 724 // We just check that the result is valid. Checking to what it should be 725 // exactly equal to would be very fragile. 726 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 727 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 728} 729 730TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesSampler) { 731 std::string recipient_shader = R"( 732 OpCapability Shader 733 OpCapability ImageQuery 734 %1 = OpExtInstImport "GLSL.std.450" 735 OpMemoryModel Logical GLSL450 736 OpEntryPoint Fragment %4 "main" 737 OpExecutionMode %4 OriginUpperLeft 738 OpSource ESSL 320 739 OpSourceExtension "GL_EXT_samplerless_texture_functions" 740 %2 = OpTypeVoid 741 %3 = OpTypeFunction %2 742 %4 = OpFunction %2 None %3 743 %5 = OpLabel 744 OpReturn 745 OpFunctionEnd 746 )"; 747 748 std::string donor_shader = R"( 749 OpCapability Shader 750 OpCapability ImageQuery 751 %1 = OpExtInstImport "GLSL.std.450" 752 OpMemoryModel Logical GLSL450 753 OpEntryPoint Fragment %4 "main" 754 OpExecutionMode %4 OriginUpperLeft 755 OpSource ESSL 320 756 OpDecorate %16 DescriptorSet 0 757 OpDecorate %16 Binding 0 758 OpDecorate %12 DescriptorSet 0 759 OpDecorate %12 Binding 64 760 %2 = OpTypeVoid 761 %3 = OpTypeFunction %2 762 %23 = OpTypeFloat 32 763 %6 = OpTypeImage %23 2D 2 0 0 1 Unknown 764 %47 = OpTypePointer UniformConstant %6 765 %12 = OpVariable %47 UniformConstant 766 %15 = OpTypeSampler 767 %55 = OpTypePointer UniformConstant %15 768 %17 = OpTypeSampledImage %6 769 %16 = OpVariable %55 UniformConstant 770 %37 = OpTypeVector %23 4 771 %109 = OpConstant %23 0 772 %66 = OpConstantComposite %37 %109 %109 %109 %109 773 %56 = OpTypeBool 774 %54 = OpConstantTrue %56 775 %4 = OpFunction %2 None %3 776 %5 = OpLabel 777 OpBranch %50 778 %50 = OpLabel 779 %51 = OpPhi %37 %66 %5 %111 %53 780 OpLoopMerge %52 %53 None 781 OpBranchConditional %54 %53 %52 782 %53 = OpLabel 783 %106 = OpLoad %6 %12 784 %107 = OpLoad %15 %16 785 %110 = OpSampledImage %17 %106 %107 786 %111 = OpImageSampleImplicitLod %37 %110 %66 Bias %109 787 OpBranch %50 788 %52 = OpLabel 789 OpReturn 790 OpFunctionEnd 791 )"; 792 793 const auto env = SPV_ENV_UNIVERSAL_1_3; 794 const auto consumer = nullptr; 795 spvtools::ValidatorOptions validator_options; 796 797 const auto recipient_context = 798 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 799 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 800 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 801 802 const auto donor_context = 803 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 804 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 805 donor_context.get(), validator_options, kConsoleMessageConsumer)); 806 807 TransformationContext transformation_context( 808 MakeUnique<FactManager>(recipient_context.get()), validator_options); 809 810 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 811 false); 812 protobufs::TransformationSequence transformation_sequence; 813 814 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 815 &transformation_context, &fuzzer_context, 816 &transformation_sequence, false, {}); 817 818 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 819 820 // We just check that the result is valid. Checking to what it should be 821 // exactly equal to would be very fragile. 822 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 823 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 824} 825 826TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageStructField) { 827 std::string recipient_shader = R"( 828 OpCapability Shader 829 OpCapability ImageQuery 830 %1 = OpExtInstImport "GLSL.std.450" 831 OpMemoryModel Logical GLSL450 832 OpEntryPoint Fragment %4 "main" 833 OpExecutionMode %4 OriginUpperLeft 834 OpSource ESSL 320 835 OpSourceExtension "GL_EXT_samplerless_texture_functions" 836 %2 = OpTypeVoid 837 %3 = OpTypeFunction %2 838 %4 = OpFunction %2 None %3 839 %5 = OpLabel 840 OpReturn 841 OpFunctionEnd 842 )"; 843 844 std::string donor_shader = R"( 845 OpCapability Shader 846 OpCapability ImageQuery 847 %1 = OpExtInstImport "GLSL.std.450" 848 OpMemoryModel Logical GLSL450 849 OpEntryPoint Fragment %4 "main" 850 OpExecutionMode %4 OriginUpperLeft 851 OpSource ESSL 320 852 OpSourceExtension "GL_EXT_samplerless_texture_functions" 853 OpName %4 "main" 854 OpName %10 "mySampler" 855 OpName %21 "myTexture" 856 OpName %33 "v" 857 OpDecorate %10 RelaxedPrecision 858 OpDecorate %10 DescriptorSet 0 859 OpDecorate %10 Binding 0 860 OpDecorate %11 RelaxedPrecision 861 OpDecorate %21 RelaxedPrecision 862 OpDecorate %21 DescriptorSet 0 863 OpDecorate %21 Binding 1 864 OpDecorate %22 RelaxedPrecision 865 OpDecorate %34 RelaxedPrecision 866 OpDecorate %40 RelaxedPrecision 867 OpDecorate %42 RelaxedPrecision 868 OpDecorate %43 RelaxedPrecision 869 %2 = OpTypeVoid 870 %3 = OpTypeFunction %2 871 %6 = OpTypeFloat 32 872 %7 = OpTypeImage %6 2D 0 0 0 1 Unknown 873 %8 = OpTypeSampledImage %7 874 %9 = OpTypePointer UniformConstant %8 875 %10 = OpVariable %9 UniformConstant 876 %12 = OpTypeInt 32 1 877 %13 = OpConstant %12 2 878 %15 = OpTypeVector %12 2 879 %17 = OpTypeInt 32 0 880 %18 = OpConstant %17 0 881 %20 = OpTypePointer UniformConstant %7 882 %21 = OpVariable %20 UniformConstant 883 %23 = OpConstant %12 1 884 %25 = OpConstant %17 1 885 %27 = OpTypeBool 886 %31 = OpTypeVector %6 4 887 %32 = OpTypePointer Function %31 888 %35 = OpConstantComposite %15 %23 %23 889 %36 = OpConstant %12 3 890 %37 = OpConstant %12 4 891 %38 = OpConstantComposite %15 %36 %37 892 %201 = OpTypeStruct %7 %7 893 %4 = OpFunction %2 None %3 894 %5 = OpLabel 895 %33 = OpVariable %32 Function 896 %11 = OpLoad %8 %10 897 %14 = OpImage %7 %11 898 %22 = OpLoad %7 %21 899 %200 = OpCompositeConstruct %201 %14 %22 900 %202 = OpCompositeExtract %7 %200 0 901 %203 = OpCompositeExtract %7 %200 1 902 %24 = OpImageQuerySizeLod %15 %203 %23 903 %16 = OpImageQuerySizeLod %15 %202 %13 904 %26 = OpCompositeExtract %12 %24 1 905 %19 = OpCompositeExtract %12 %16 0 906 %28 = OpSGreaterThan %27 %19 %26 907 OpSelectionMerge %30 None 908 OpBranchConditional %28 %29 %41 909 %29 = OpLabel 910 %34 = OpLoad %8 %10 911 %39 = OpImage %7 %34 912 %40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38 913 OpStore %33 %40 914 OpBranch %30 915 %41 = OpLabel 916 %42 = OpLoad %7 %21 917 %43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38 918 OpStore %33 %43 919 OpBranch %30 920 %30 = OpLabel 921 OpReturn 922 OpFunctionEnd 923 )"; 924 925 const auto env = SPV_ENV_UNIVERSAL_1_3; 926 const auto consumer = nullptr; 927 spvtools::ValidatorOptions validator_options; 928 929 const auto recipient_context = 930 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 931 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 932 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 933 934 const auto donor_context = 935 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 936 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 937 donor_context.get(), validator_options, kConsoleMessageConsumer)); 938 939 TransformationContext transformation_context( 940 MakeUnique<FactManager>(recipient_context.get()), validator_options); 941 942 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 943 false); 944 protobufs::TransformationSequence transformation_sequence; 945 946 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 947 &transformation_context, &fuzzer_context, 948 &transformation_sequence, false, {}); 949 950 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 951 952 // We just check that the result is valid. Checking to what it should be 953 // exactly equal to would be very fragile. 954 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 955 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 956} 957 958TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageFunctionParameter) { 959 std::string recipient_shader = R"( 960 OpCapability Shader 961 OpCapability ImageQuery 962 %1 = OpExtInstImport "GLSL.std.450" 963 OpMemoryModel Logical GLSL450 964 OpEntryPoint Fragment %4 "main" 965 OpExecutionMode %4 OriginUpperLeft 966 OpSource ESSL 320 967 OpSourceExtension "GL_EXT_samplerless_texture_functions" 968 %2 = OpTypeVoid 969 %3 = OpTypeFunction %2 970 %4 = OpFunction %2 None %3 971 %5 = OpLabel 972 OpReturn 973 OpFunctionEnd 974 )"; 975 976 std::string donor_shader = R"( 977 OpCapability Shader 978 OpCapability ImageQuery 979 %1 = OpExtInstImport "GLSL.std.450" 980 OpMemoryModel Logical GLSL450 981 OpEntryPoint Fragment %4 "main" 982 OpExecutionMode %4 OriginUpperLeft 983 OpSource ESSL 320 984 OpSourceExtension "GL_EXT_samplerless_texture_functions" 985 OpName %4 "main" 986 OpName %10 "mySampler" 987 OpName %21 "myTexture" 988 OpName %33 "v" 989 OpDecorate %10 RelaxedPrecision 990 OpDecorate %10 DescriptorSet 0 991 OpDecorate %10 Binding 0 992 OpDecorate %11 RelaxedPrecision 993 OpDecorate %21 RelaxedPrecision 994 OpDecorate %21 DescriptorSet 0 995 OpDecorate %21 Binding 1 996 OpDecorate %22 RelaxedPrecision 997 OpDecorate %34 RelaxedPrecision 998 OpDecorate %40 RelaxedPrecision 999 OpDecorate %42 RelaxedPrecision 1000 OpDecorate %43 RelaxedPrecision 1001 %2 = OpTypeVoid 1002 %3 = OpTypeFunction %2 1003 %6 = OpTypeFloat 32 1004 %7 = OpTypeImage %6 2D 0 0 0 1 Unknown 1005 %8 = OpTypeSampledImage %7 1006 %9 = OpTypePointer UniformConstant %8 1007 %10 = OpVariable %9 UniformConstant 1008 %12 = OpTypeInt 32 1 1009 %13 = OpConstant %12 2 1010 %15 = OpTypeVector %12 2 1011 %17 = OpTypeInt 32 0 1012 %18 = OpConstant %17 0 1013 %20 = OpTypePointer UniformConstant %7 1014 %21 = OpVariable %20 UniformConstant 1015 %23 = OpConstant %12 1 1016 %25 = OpConstant %17 1 1017 %27 = OpTypeBool 1018 %31 = OpTypeVector %6 4 1019 %32 = OpTypePointer Function %31 1020 %35 = OpConstantComposite %15 %23 %23 1021 %36 = OpConstant %12 3 1022 %37 = OpConstant %12 4 1023 %38 = OpConstantComposite %15 %36 %37 1024 %201 = OpTypeFunction %15 %7 %12 1025 %4 = OpFunction %2 None %3 1026 %5 = OpLabel 1027 %33 = OpVariable %32 Function 1028 %11 = OpLoad %8 %10 1029 %14 = OpImage %7 %11 1030 %16 = OpFunctionCall %15 %200 %14 %13 1031 %19 = OpCompositeExtract %12 %16 0 1032 %22 = OpLoad %7 %21 1033 %24 = OpImageQuerySizeLod %15 %22 %23 1034 %26 = OpCompositeExtract %12 %24 1 1035 %28 = OpSGreaterThan %27 %19 %26 1036 OpSelectionMerge %30 None 1037 OpBranchConditional %28 %29 %41 1038 %29 = OpLabel 1039 %34 = OpLoad %8 %10 1040 %39 = OpImage %7 %34 1041 %40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38 1042 OpStore %33 %40 1043 OpBranch %30 1044 %41 = OpLabel 1045 %42 = OpLoad %7 %21 1046 %43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38 1047 OpStore %33 %43 1048 OpBranch %30 1049 %30 = OpLabel 1050 OpReturn 1051 OpFunctionEnd 1052 %200 = OpFunction %15 None %201 1053 %202 = OpFunctionParameter %7 1054 %203 = OpFunctionParameter %12 1055 %204 = OpLabel 1056 %205 = OpImageQuerySizeLod %15 %202 %203 1057 OpReturnValue %205 1058 OpFunctionEnd 1059 )"; 1060 1061 const auto env = SPV_ENV_UNIVERSAL_1_3; 1062 const auto consumer = nullptr; 1063 spvtools::ValidatorOptions validator_options; 1064 1065 const auto recipient_context = 1066 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1067 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1068 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1069 1070 const auto donor_context = 1071 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1072 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1073 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1074 1075 TransformationContext transformation_context( 1076 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1077 1078 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1079 false); 1080 protobufs::TransformationSequence transformation_sequence; 1081 1082 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1083 &transformation_context, &fuzzer_context, 1084 &transformation_sequence, false, {}); 1085 1086 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 1087 1088 // We just check that the result is valid. Checking to what it should be 1089 // exactly equal to would be very fragile. 1090 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1091 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1092} 1093 1094TEST(FuzzerPassDonateModulesTest, DonateShaderWithImageStorageClass) { 1095 std::string recipient_shader = R"( 1096 OpCapability Shader 1097 OpCapability ImageQuery 1098 %1 = OpExtInstImport "GLSL.std.450" 1099 OpMemoryModel Logical GLSL450 1100 OpEntryPoint Fragment %4 "main" 1101 OpExecutionMode %4 OriginUpperLeft 1102 OpSource ESSL 320 1103 OpSourceExtension "GL_EXT_samplerless_texture_functions" 1104 %2 = OpTypeVoid 1105 %3 = OpTypeFunction %2 1106 %4 = OpFunction %2 None %3 1107 %5 = OpLabel 1108 OpReturn 1109 OpFunctionEnd 1110 )"; 1111 1112 std::string donor_shader = R"( 1113 OpCapability Shader 1114 OpCapability SampledBuffer 1115 OpCapability ImageBuffer 1116 %1 = OpExtInstImport "GLSL.std.450" 1117 OpMemoryModel Logical GLSL450 1118 OpEntryPoint Fragment %2 "MainPSPacked" 1119 OpExecutionMode %2 OriginUpperLeft 1120 OpDecorate %18 DescriptorSet 0 1121 OpDecorate %18 Binding 128 1122 %49 = OpTypeInt 32 0 1123 %50 = OpTypeFloat 32 1124 %58 = OpConstant %50 1 1125 %66 = OpConstant %49 0 1126 %87 = OpTypeVector %50 2 1127 %88 = OpConstantComposite %87 %58 %58 1128 %17 = OpTypeImage %49 2D 2 0 0 2 R32ui 1129 %118 = OpTypePointer UniformConstant %17 1130 %123 = OpTypeVector %49 2 1131 %132 = OpTypeVoid 1132 %133 = OpTypeFunction %132 1133 %142 = OpTypePointer Image %49 1134 %18 = OpVariable %118 UniformConstant 1135 %2 = OpFunction %132 None %133 1136 %153 = OpLabel 1137 %495 = OpConvertFToU %123 %88 1138 %501 = OpImageTexelPointer %142 %18 %495 %66 1139 OpReturn 1140 OpFunctionEnd 1141 )"; 1142 1143 const auto env = SPV_ENV_UNIVERSAL_1_3; 1144 const auto consumer = nullptr; 1145 spvtools::ValidatorOptions validator_options; 1146 1147 const auto recipient_context = 1148 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1149 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1150 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1151 1152 const auto donor_context = 1153 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1154 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1155 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1156 1157 TransformationContext transformation_context( 1158 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1159 1160 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1161 false); 1162 protobufs::TransformationSequence transformation_sequence; 1163 1164 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1165 &transformation_context, &fuzzer_context, 1166 &transformation_sequence, false, {}); 1167 1168 fuzzer_pass.DonateSingleModule(donor_context.get(), true); 1169 1170 // We just check that the result is valid. Checking to what it should be 1171 // exactly equal to would be very fragile. 1172 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1173 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1174} 1175 1176TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArray) { 1177 std::string recipient_shader = R"( 1178 OpCapability Shader 1179 %1 = OpExtInstImport "GLSL.std.450" 1180 OpMemoryModel Logical GLSL450 1181 OpEntryPoint GLCompute %4 "main" 1182 OpExecutionMode %4 LocalSize 1 1 1 1183 OpSource ESSL 310 1184 %2 = OpTypeVoid 1185 %3 = OpTypeFunction %2 1186 %4 = OpFunction %2 None %3 1187 %5 = OpLabel 1188 OpReturn 1189 OpFunctionEnd 1190 )"; 1191 1192 std::string donor_shader = R"( 1193 OpCapability Shader 1194 %1 = OpExtInstImport "GLSL.std.450" 1195 OpMemoryModel Logical GLSL450 1196 OpEntryPoint GLCompute %4 "main" 1197 OpExecutionMode %4 LocalSize 1 1 1 1198 OpSource ESSL 310 1199 OpDecorate %9 ArrayStride 4 1200 OpMemberDecorate %10 0 Offset 0 1201 OpDecorate %10 BufferBlock 1202 OpDecorate %12 DescriptorSet 0 1203 OpDecorate %12 Binding 0 1204 %2 = OpTypeVoid 1205 %3 = OpTypeFunction %2 1206 %6 = OpTypeInt 32 1 1207 %7 = OpTypePointer Function %6 1208 %9 = OpTypeRuntimeArray %6 1209 %10 = OpTypeStruct %9 1210 %11 = OpTypePointer Uniform %10 1211 %12 = OpVariable %11 Uniform 1212 %13 = OpTypeInt 32 0 1213 %16 = OpConstant %6 0 1214 %18 = OpConstant %6 1 1215 %20 = OpTypePointer Uniform %6 1216 %4 = OpFunction %2 None %3 1217 %5 = OpLabel 1218 %8 = OpVariable %7 Function 1219 %14 = OpArrayLength %13 %12 0 1220 %15 = OpBitcast %6 %14 1221 OpStore %8 %15 1222 %17 = OpLoad %6 %8 1223 %19 = OpISub %6 %17 %18 1224 %21 = OpAccessChain %20 %12 %16 %19 1225 OpStore %21 %16 1226 OpReturn 1227 OpFunctionEnd 1228 )"; 1229 1230 const auto env = SPV_ENV_UNIVERSAL_1_3; 1231 const auto consumer = nullptr; 1232 spvtools::ValidatorOptions validator_options; 1233 1234 const auto recipient_context = 1235 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1236 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1237 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1238 1239 const auto donor_context = 1240 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1241 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1242 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1243 1244 TransformationContext transformation_context( 1245 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1246 1247 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1248 false); 1249 protobufs::TransformationSequence transformation_sequence; 1250 1251 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1252 &transformation_context, &fuzzer_context, 1253 &transformation_sequence, false, {}); 1254 1255 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 1256 1257 // We just check that the result is valid. Checking to what it should be 1258 // exactly equal to would be very fragile. 1259 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1260 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1261} 1262 1263TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArrayLivesafe) { 1264 std::string recipient_shader = R"( 1265 OpCapability Shader 1266 %1 = OpExtInstImport "GLSL.std.450" 1267 OpMemoryModel Logical GLSL450 1268 OpEntryPoint GLCompute %4 "main" 1269 OpExecutionMode %4 LocalSize 1 1 1 1270 OpSource ESSL 310 1271 %2 = OpTypeVoid 1272 %3 = OpTypeFunction %2 1273 %4 = OpFunction %2 None %3 1274 %5 = OpLabel 1275 OpReturn 1276 OpFunctionEnd 1277 )"; 1278 1279 std::string donor_shader = R"( 1280 OpCapability Shader 1281 %1 = OpExtInstImport "GLSL.std.450" 1282 OpMemoryModel Logical GLSL450 1283 OpEntryPoint GLCompute %4 "main" 1284 OpExecutionMode %4 LocalSize 1 1 1 1285 OpSource ESSL 310 1286 OpDecorate %16 ArrayStride 4 1287 OpMemberDecorate %17 0 Offset 0 1288 OpDecorate %17 BufferBlock 1289 OpDecorate %19 DescriptorSet 0 1290 OpDecorate %19 Binding 0 1291 %2 = OpTypeVoid 1292 %3 = OpTypeFunction %2 1293 %6 = OpTypeInt 32 1 1294 %7 = OpTypePointer Function %6 1295 %9 = OpConstant %6 0 1296 %16 = OpTypeRuntimeArray %6 1297 %17 = OpTypeStruct %16 1298 %18 = OpTypePointer Uniform %17 1299 %19 = OpVariable %18 Uniform 1300 %20 = OpTypeInt 32 0 1301 %23 = OpTypeBool 1302 %26 = OpConstant %6 32 1303 %27 = OpTypePointer Uniform %6 1304 %30 = OpConstant %6 1 1305 %4 = OpFunction %2 None %3 1306 %5 = OpLabel 1307 %8 = OpVariable %7 Function 1308 OpStore %8 %9 1309 OpBranch %10 1310 %10 = OpLabel 1311 OpLoopMerge %12 %13 None 1312 OpBranch %14 1313 %14 = OpLabel 1314 %15 = OpLoad %6 %8 1315 %21 = OpArrayLength %20 %19 0 1316 %22 = OpBitcast %6 %21 1317 %24 = OpSLessThan %23 %15 %22 1318 OpBranchConditional %24 %11 %12 1319 %11 = OpLabel 1320 %25 = OpLoad %6 %8 1321 %28 = OpAccessChain %27 %19 %9 %25 1322 OpStore %28 %26 1323 OpBranch %13 1324 %13 = OpLabel 1325 %29 = OpLoad %6 %8 1326 %31 = OpIAdd %6 %29 %30 1327 OpStore %8 %31 1328 OpBranch %10 1329 %12 = OpLabel 1330 OpReturn 1331 OpFunctionEnd 1332 )"; 1333 1334 const auto env = SPV_ENV_UNIVERSAL_1_3; 1335 const auto consumer = nullptr; 1336 spvtools::ValidatorOptions validator_options; 1337 1338 const auto recipient_context = 1339 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1340 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1341 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1342 1343 const auto donor_context = 1344 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1345 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1346 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1347 1348 TransformationContext transformation_context( 1349 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1350 1351 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1352 false); 1353 protobufs::TransformationSequence transformation_sequence; 1354 1355 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1356 &transformation_context, &fuzzer_context, 1357 &transformation_sequence, false, {}); 1358 1359 fuzzer_pass.DonateSingleModule(donor_context.get(), true); 1360 1361 // We just check that the result is valid. Checking to what it should be 1362 // exactly equal to would be very fragile. 1363 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1364 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1365} 1366 1367TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithWorkgroupVariables) { 1368 std::string recipient_shader = R"( 1369 OpCapability Shader 1370 %1 = OpExtInstImport "GLSL.std.450" 1371 OpMemoryModel Logical GLSL450 1372 OpEntryPoint GLCompute %4 "main" 1373 OpExecutionMode %4 LocalSize 1 1 1 1374 OpSource ESSL 310 1375 %2 = OpTypeVoid 1376 %3 = OpTypeFunction %2 1377 %4 = OpFunction %2 None %3 1378 %5 = OpLabel 1379 OpReturn 1380 OpFunctionEnd 1381 )"; 1382 1383 std::string donor_shader = R"( 1384 OpCapability Shader 1385 %1 = OpExtInstImport "GLSL.std.450" 1386 OpMemoryModel Logical GLSL450 1387 OpEntryPoint GLCompute %4 "main" 1388 OpExecutionMode %4 LocalSize 1 1 1 1389 OpSource ESSL 310 1390 %2 = OpTypeVoid 1391 %3 = OpTypeFunction %2 1392 %6 = OpTypeInt 32 1 1393 %7 = OpTypePointer Workgroup %6 1394 %8 = OpVariable %7 Workgroup 1395 %9 = OpConstant %6 2 1396 %10 = OpVariable %7 Workgroup 1397 %4 = OpFunction %2 None %3 1398 %5 = OpLabel 1399 OpStore %8 %9 1400 %11 = OpLoad %6 %8 1401 OpStore %10 %11 1402 OpReturn 1403 OpFunctionEnd 1404 )"; 1405 1406 const auto env = SPV_ENV_UNIVERSAL_1_3; 1407 const auto consumer = nullptr; 1408 spvtools::ValidatorOptions validator_options; 1409 1410 const auto recipient_context = 1411 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1412 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1413 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1414 1415 const auto donor_context = 1416 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1417 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1418 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1419 1420 TransformationContext transformation_context( 1421 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1422 1423 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1424 false); 1425 protobufs::TransformationSequence transformation_sequence; 1426 1427 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1428 &transformation_context, &fuzzer_context, 1429 &transformation_sequence, false, {}); 1430 1431 fuzzer_pass.DonateSingleModule(donor_context.get(), true); 1432 1433 // We just check that the result is valid. Checking to what it should be 1434 // exactly equal to would be very fragile. 1435 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1436 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1437} 1438 1439TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithAtomics) { 1440 std::string recipient_shader = R"( 1441 OpCapability Shader 1442 %1 = OpExtInstImport "GLSL.std.450" 1443 OpMemoryModel Logical GLSL450 1444 OpEntryPoint GLCompute %4 "main" 1445 OpExecutionMode %4 LocalSize 1 1 1 1446 OpSource ESSL 310 1447 %2 = OpTypeVoid 1448 %3 = OpTypeFunction %2 1449 %4 = OpFunction %2 None %3 1450 %5 = OpLabel 1451 OpReturn 1452 OpFunctionEnd 1453 )"; 1454 1455 std::string donor_shader = R"( 1456 OpCapability Shader 1457 %1 = OpExtInstImport "GLSL.std.450" 1458 OpMemoryModel Logical GLSL450 1459 OpEntryPoint GLCompute %4 "main" 1460 OpExecutionMode %4 LocalSize 1 1 1 1461 OpSource ESSL 310 1462 OpMemberDecorate %9 0 Offset 0 1463 OpDecorate %9 BufferBlock 1464 OpDecorate %11 DescriptorSet 0 1465 OpDecorate %11 Binding 0 1466 %2 = OpTypeVoid 1467 %3 = OpTypeFunction %2 1468 %6 = OpTypeInt 32 0 1469 %7 = OpTypePointer Function %6 1470 %9 = OpTypeStruct %6 1471 %10 = OpTypePointer Uniform %9 1472 %11 = OpVariable %10 Uniform 1473 %12 = OpTypeInt 32 1 1474 %13 = OpConstant %12 0 1475 %14 = OpTypePointer Uniform %6 1476 %16 = OpConstant %6 1 1477 %17 = OpConstant %6 0 1478 %4 = OpFunction %2 None %3 1479 %5 = OpLabel 1480 %8 = OpVariable %7 Function 1481 %15 = OpAccessChain %14 %11 %13 1482 %18 = OpAtomicIAdd %6 %15 %16 %17 %16 1483 OpStore %8 %18 1484 %19 = OpAccessChain %14 %11 %13 1485 %20 = OpLoad %6 %8 1486 %21 = OpAtomicUMin %6 %19 %16 %17 %20 1487 OpStore %8 %21 1488 %22 = OpAccessChain %14 %11 %13 1489 %23 = OpLoad %6 %8 1490 %24 = OpAtomicUMax %6 %22 %16 %17 %23 1491 OpStore %8 %24 1492 %25 = OpAccessChain %14 %11 %13 1493 %26 = OpLoad %6 %8 1494 %27 = OpAtomicAnd %6 %25 %16 %17 %26 1495 OpStore %8 %27 1496 %28 = OpAccessChain %14 %11 %13 1497 %29 = OpLoad %6 %8 1498 %30 = OpAtomicOr %6 %28 %16 %17 %29 1499 OpStore %8 %30 1500 %31 = OpAccessChain %14 %11 %13 1501 %32 = OpLoad %6 %8 1502 %33 = OpAtomicXor %6 %31 %16 %17 %32 1503 OpStore %8 %33 1504 %34 = OpAccessChain %14 %11 %13 1505 %35 = OpLoad %6 %8 1506 %36 = OpAtomicExchange %6 %34 %16 %17 %35 1507 OpStore %8 %36 1508 %37 = OpAccessChain %14 %11 %13 1509 %38 = OpLoad %6 %8 1510 %39 = OpAtomicCompareExchange %6 %37 %16 %17 %17 %16 %38 1511 OpStore %8 %39 1512 OpReturn 1513 OpFunctionEnd 1514 )"; 1515 1516 const auto env = SPV_ENV_UNIVERSAL_1_3; 1517 const auto consumer = nullptr; 1518 spvtools::ValidatorOptions validator_options; 1519 1520 const auto recipient_context = 1521 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1522 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1523 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1524 1525 const auto donor_context = 1526 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1527 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1528 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1529 1530 TransformationContext transformation_context( 1531 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1532 1533 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1534 false); 1535 protobufs::TransformationSequence transformation_sequence; 1536 1537 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1538 &transformation_context, &fuzzer_context, 1539 &transformation_sequence, false, {}); 1540 1541 fuzzer_pass.DonateSingleModule(donor_context.get(), true); 1542 1543 // We just check that the result is valid. Checking to what it should be 1544 // exactly equal to would be very fragile. 1545 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1546 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1547} 1548 1549TEST(FuzzerPassDonateModulesTest, Miscellaneous1) { 1550 std::string recipient_shader = R"( 1551 OpCapability Shader 1552 %1 = OpExtInstImport "GLSL.std.450" 1553 OpMemoryModel Logical GLSL450 1554 OpEntryPoint Fragment %4 "main" 1555 OpExecutionMode %4 OriginUpperLeft 1556 OpSource ESSL 310 1557 %2 = OpTypeVoid 1558 %3 = OpTypeFunction %2 1559 %4 = OpFunction %2 None %3 1560 %5 = OpLabel 1561 OpReturn 1562 OpFunctionEnd 1563 )"; 1564 1565 std::string donor_shader = R"( 1566 OpCapability Shader 1567 %1 = OpExtInstImport "GLSL.std.450" 1568 OpMemoryModel Logical GLSL450 1569 OpEntryPoint Fragment %4 "main" 1570 OpExecutionMode %4 OriginUpperLeft 1571 OpSource ESSL 310 1572 OpName %4 "main" 1573 OpName %6 "foo(" 1574 OpName %10 "x" 1575 OpName %12 "i" 1576 OpName %33 "i" 1577 OpName %42 "j" 1578 OpDecorate %10 RelaxedPrecision 1579 OpDecorate %12 RelaxedPrecision 1580 OpDecorate %19 RelaxedPrecision 1581 OpDecorate %23 RelaxedPrecision 1582 OpDecorate %24 RelaxedPrecision 1583 OpDecorate %25 RelaxedPrecision 1584 OpDecorate %26 RelaxedPrecision 1585 OpDecorate %27 RelaxedPrecision 1586 OpDecorate %28 RelaxedPrecision 1587 OpDecorate %30 RelaxedPrecision 1588 OpDecorate %33 RelaxedPrecision 1589 OpDecorate %39 RelaxedPrecision 1590 OpDecorate %42 RelaxedPrecision 1591 OpDecorate %49 RelaxedPrecision 1592 OpDecorate %52 RelaxedPrecision 1593 OpDecorate %53 RelaxedPrecision 1594 OpDecorate %58 RelaxedPrecision 1595 OpDecorate %59 RelaxedPrecision 1596 OpDecorate %60 RelaxedPrecision 1597 OpDecorate %63 RelaxedPrecision 1598 OpDecorate %64 RelaxedPrecision 1599 %2 = OpTypeVoid 1600 %3 = OpTypeFunction %2 1601 %8 = OpTypeInt 32 1 1602 %9 = OpTypePointer Function %8 1603 %11 = OpConstant %8 2 1604 %13 = OpConstant %8 0 1605 %20 = OpConstant %8 100 1606 %21 = OpTypeBool 1607 %29 = OpConstant %8 1 1608 %40 = OpConstant %8 10 1609 %43 = OpConstant %8 20 1610 %61 = OpConstant %8 4 1611 %4 = OpFunction %2 None %3 1612 %5 = OpLabel 1613 %33 = OpVariable %9 Function 1614 %42 = OpVariable %9 Function 1615 %32 = OpFunctionCall %2 %6 1616 OpStore %33 %13 1617 OpBranch %34 1618 %34 = OpLabel 1619 OpLoopMerge %36 %37 None 1620 OpBranch %38 1621 %38 = OpLabel 1622 %39 = OpLoad %8 %33 1623 %41 = OpSLessThan %21 %39 %40 1624 OpBranchConditional %41 %35 %36 1625 %35 = OpLabel 1626 OpStore %42 %43 1627 OpBranch %44 1628 %44 = OpLabel 1629 OpLoopMerge %46 %47 None 1630 OpBranch %48 1631 %48 = OpLabel 1632 %49 = OpLoad %8 %42 1633 %50 = OpSGreaterThan %21 %49 %13 1634 OpBranchConditional %50 %45 %46 1635 %45 = OpLabel 1636 %51 = OpFunctionCall %2 %6 1637 %52 = OpLoad %8 %42 1638 %53 = OpISub %8 %52 %29 1639 OpStore %42 %53 1640 OpBranch %47 1641 %47 = OpLabel 1642 OpBranch %44 1643 %46 = OpLabel 1644 OpBranch %54 1645 %54 = OpLabel 1646 OpLoopMerge %56 %57 None 1647 OpBranch %55 1648 %55 = OpLabel 1649 %58 = OpLoad %8 %33 1650 %59 = OpIAdd %8 %58 %29 1651 OpStore %33 %59 1652 OpBranch %57 1653 %57 = OpLabel 1654 %60 = OpLoad %8 %33 1655 %62 = OpSLessThan %21 %60 %61 1656 OpBranchConditional %62 %54 %56 1657 %56 = OpLabel 1658 OpBranch %37 1659 %37 = OpLabel 1660 %63 = OpLoad %8 %33 1661 %64 = OpIAdd %8 %63 %29 1662 OpStore %33 %64 1663 OpBranch %34 1664 %36 = OpLabel 1665 OpReturn 1666 OpFunctionEnd 1667 %6 = OpFunction %2 None %3 1668 %7 = OpLabel 1669 %10 = OpVariable %9 Function 1670 %12 = OpVariable %9 Function 1671 OpStore %10 %11 1672 OpStore %12 %13 1673 OpBranch %14 1674 %14 = OpLabel 1675 OpLoopMerge %16 %17 None 1676 OpBranch %18 1677 %18 = OpLabel 1678 %19 = OpLoad %8 %12 1679 %22 = OpSLessThan %21 %19 %20 1680 OpBranchConditional %22 %15 %16 1681 %15 = OpLabel 1682 %23 = OpLoad %8 %12 1683 %24 = OpLoad %8 %10 1684 %25 = OpIAdd %8 %24 %23 1685 OpStore %10 %25 1686 %26 = OpLoad %8 %10 1687 %27 = OpIMul %8 %26 %11 1688 OpStore %10 %27 1689 OpBranch %17 1690 %17 = OpLabel 1691 %28 = OpLoad %8 %12 1692 %30 = OpIAdd %8 %28 %29 1693 OpStore %12 %30 1694 OpBranch %14 1695 %16 = OpLabel 1696 OpReturn 1697 OpFunctionEnd 1698 )"; 1699 1700 const auto env = SPV_ENV_UNIVERSAL_1_5; 1701 const auto consumer = nullptr; 1702 spvtools::ValidatorOptions validator_options; 1703 1704 const auto recipient_context = 1705 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1706 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1707 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1708 1709 const auto donor_context = 1710 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1711 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1712 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1713 1714 TransformationContext transformation_context( 1715 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1716 1717 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1718 false); 1719 protobufs::TransformationSequence transformation_sequence; 1720 1721 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1722 &transformation_context, &fuzzer_context, 1723 &transformation_sequence, false, {}); 1724 1725 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 1726 1727 // We just check that the result is valid. Checking to what it should be 1728 // exactly equal to would be very fragile. 1729 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1730 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1731} 1732 1733TEST(FuzzerPassDonateModulesTest, OpSpecConstantInstructions) { 1734 std::string donor_shader = R"( 1735 OpCapability Shader 1736 %1 = OpExtInstImport "GLSL.std.450" 1737 OpMemoryModel Logical GLSL450 1738 OpEntryPoint Fragment %4 "main" 1739 OpExecutionMode %4 OriginUpperLeft 1740 OpSource ESSL 310 1741 %2 = OpTypeVoid 1742 %3 = OpTypeFunction %2 1743 %6 = OpTypeBool 1744 %7 = OpTypeInt 32 1 1745 %8 = OpTypeStruct %6 %6 %7 1746 %9 = OpSpecConstantTrue %6 1747 %10 = OpSpecConstantFalse %6 1748 %11 = OpSpecConstant %7 2 1749 %12 = OpSpecConstantComposite %8 %9 %10 %11 1750 %13 = OpSpecConstantOp %6 LogicalEqual %9 %10 1751 %4 = OpFunction %2 None %3 1752 %5 = OpLabel 1753 OpReturn 1754 OpFunctionEnd 1755 )"; 1756 1757 std::string recipient_shader = R"( 1758 OpCapability Shader 1759 %1 = OpExtInstImport "GLSL.std.450" 1760 OpMemoryModel Logical GLSL450 1761 OpEntryPoint Fragment %4 "main" 1762 OpExecutionMode %4 OriginUpperLeft 1763 OpSource ESSL 310 1764 %2 = OpTypeVoid 1765 %3 = OpTypeFunction %2 1766 %4 = OpFunction %2 None %3 1767 %5 = OpLabel 1768 OpReturn 1769 OpFunctionEnd 1770 )"; 1771 1772 const auto env = SPV_ENV_UNIVERSAL_1_3; 1773 const auto consumer = nullptr; 1774 spvtools::ValidatorOptions validator_options; 1775 1776 const auto recipient_context = 1777 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1778 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1779 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1780 1781 const auto donor_context = 1782 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1783 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1784 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1785 1786 TransformationContext transformation_context( 1787 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1788 1789 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1790 false); 1791 protobufs::TransformationSequence transformation_sequence; 1792 1793 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1794 &transformation_context, &fuzzer_context, 1795 &transformation_sequence, false, {}); 1796 1797 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 1798 1799 // Check that the module is valid first. 1800 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1801 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1802 1803 std::string expected_shader = R"( 1804 OpCapability Shader 1805 %1 = OpExtInstImport "GLSL.std.450" 1806 OpMemoryModel Logical GLSL450 1807 OpEntryPoint Fragment %4 "main" 1808 OpExecutionMode %4 OriginUpperLeft 1809 OpSource ESSL 310 1810 %2 = OpTypeVoid 1811 %3 = OpTypeFunction %2 1812 %100 = OpTypeBool 1813 %101 = OpTypeInt 32 1 1814 %102 = OpTypeStruct %100 %100 %101 1815 %103 = OpConstantTrue %100 1816 %104 = OpConstantFalse %100 1817 %105 = OpConstant %101 2 1818 %106 = OpConstantComposite %102 %103 %104 %105 1819 %107 = OpSpecConstantOp %100 LogicalEqual %103 %104 1820 %4 = OpFunction %2 None %3 1821 %5 = OpLabel 1822 OpReturn 1823 OpFunctionEnd 1824 %108 = OpFunction %2 None %3 1825 %109 = OpLabel 1826 OpReturn 1827 OpFunctionEnd 1828 )"; 1829 1830 // Now check that the transformation has produced the expected result. 1831 ASSERT_TRUE(IsEqual(env, expected_shader, recipient_context.get())); 1832} 1833 1834TEST(FuzzerPassDonateModulesTest, DonationSupportsOpTypeRuntimeArray) { 1835 std::string donor_shader = R"( 1836 OpCapability Shader 1837 OpExtension "SPV_KHR_storage_buffer_storage_class" 1838 OpMemoryModel Logical GLSL450 1839 OpEntryPoint GLCompute %29 "kernel_1" 1840 OpEntryPoint GLCompute %37 "kernel_2" 1841 OpSource OpenCL_C 120 1842 OpDecorate %2 ArrayStride 4 1843 OpMemberDecorate %3 0 Offset 0 1844 OpDecorate %3 Block 1845 OpMemberDecorate %5 0 Offset 0 1846 OpMemberDecorate %6 0 Offset 0 1847 OpDecorate %6 Block 1848 OpDecorate %21 BuiltIn WorkgroupSize 1849 OpDecorate %23 DescriptorSet 0 1850 OpDecorate %23 Binding 0 1851 OpDecorate %25 SpecId 3 1852 OpDecorate %18 SpecId 0 1853 OpDecorate %19 SpecId 1 1854 OpDecorate %20 SpecId 2 1855 %1 = OpTypeInt 32 0 1856 %2 = OpTypeRuntimeArray %1 1857 %3 = OpTypeStruct %2 1858 %4 = OpTypePointer StorageBuffer %3 1859 %5 = OpTypeStruct %1 1860 %6 = OpTypeStruct %5 1861 %7 = OpTypePointer PushConstant %6 1862 %8 = OpTypeFloat 32 1863 %9 = OpTypeVoid 1864 %10 = OpTypeFunction %9 1865 %11 = OpTypePointer Workgroup %1 1866 %12 = OpTypePointer PushConstant %5 1867 %13 = OpTypePointer StorageBuffer %1 1868 %14 = OpTypeFunction %1 %1 1869 %15 = OpTypeVector %1 3 1870 %16 = OpTypePointer Private %15 1871 %17 = OpConstant %1 0 1872 %18 = OpSpecConstant %1 1 1873 %19 = OpSpecConstant %1 1 1874 %20 = OpSpecConstant %1 1 1875 %21 = OpSpecConstantComposite %15 %18 %19 %20 1876 %25 = OpSpecConstant %1 1 1877 %26 = OpTypeArray %1 %25 1878 %27 = OpTypePointer Workgroup %26 1879 %22 = OpVariable %16 Private %21 1880 %23 = OpVariable %4 StorageBuffer 1881 %24 = OpVariable %7 PushConstant 1882 %28 = OpVariable %27 Workgroup 1883 %29 = OpFunction %9 None %10 1884 %30 = OpLabel 1885 %31 = OpAccessChain %11 %28 %17 1886 %32 = OpAccessChain %12 %24 %17 1887 %33 = OpLoad %5 %32 1888 %34 = OpCompositeExtract %1 %33 0 1889 %35 = OpFunctionCall %1 %45 %34 1890 %36 = OpAccessChain %13 %23 %17 %34 1891 OpStore %36 %35 1892 OpReturn 1893 OpFunctionEnd 1894 %37 = OpFunction %9 None %10 1895 %38 = OpLabel 1896 %39 = OpAccessChain %11 %28 %17 1897 %40 = OpAccessChain %12 %24 %17 1898 %41 = OpLoad %5 %40 1899 %42 = OpCompositeExtract %1 %41 0 1900 %43 = OpFunctionCall %1 %45 %42 1901 %44 = OpAccessChain %13 %23 %17 %42 1902 OpStore %44 %43 1903 OpReturn 1904 OpFunctionEnd 1905 %45 = OpFunction %1 Pure %14 1906 %46 = OpFunctionParameter %1 1907 %47 = OpLabel 1908 %48 = OpAccessChain %11 %28 %46 1909 %49 = OpLoad %1 %48 1910 OpReturnValue %49 1911 OpFunctionEnd 1912 )"; 1913 1914 std::string recipient_shader = R"( 1915 OpCapability Shader 1916 %1 = OpExtInstImport "GLSL.std.450" 1917 OpMemoryModel Logical GLSL450 1918 OpEntryPoint Fragment %4 "main" 1919 OpExecutionMode %4 OriginUpperLeft 1920 OpSource ESSL 310 1921 %2 = OpTypeVoid 1922 %3 = OpTypeFunction %2 1923 %4 = OpFunction %2 None %3 1924 %5 = OpLabel 1925 OpReturn 1926 OpFunctionEnd 1927 )"; 1928 1929 const auto env = SPV_ENV_UNIVERSAL_1_0; 1930 const auto consumer = nullptr; 1931 spvtools::ValidatorOptions validator_options; 1932 1933 const auto recipient_context = 1934 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 1935 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1936 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1937 1938 const auto donor_context = 1939 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 1940 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1941 donor_context.get(), validator_options, kConsoleMessageConsumer)); 1942 1943 TransformationContext transformation_context( 1944 MakeUnique<FactManager>(recipient_context.get()), validator_options); 1945 1946 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 1947 false); 1948 protobufs::TransformationSequence transformation_sequence; 1949 1950 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 1951 &transformation_context, &fuzzer_context, 1952 &transformation_sequence, false, {}); 1953 1954 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 1955 1956 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 1957 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 1958} 1959 1960TEST(FuzzerPassDonateModulesTest, HandlesCapabilities) { 1961 std::string donor_shader = R"( 1962 OpCapability VariablePointersStorageBuffer 1963 %1 = OpExtInstImport "GLSL.std.450" 1964 OpMemoryModel Logical GLSL450 1965 OpEntryPoint Fragment %4 "main" 1966 OpExecutionMode %4 OriginUpperLeft 1967 OpSource ESSL 310 1968 %2 = OpTypeVoid 1969 %3 = OpTypeFunction %2 1970 %6 = OpTypeFloat 32 1971 %11 = OpConstant %6 23 1972 %7 = OpTypePointer Function %6 1973 %4 = OpFunction %2 None %3 1974 1975 %5 = OpLabel 1976 %8 = OpVariable %7 Function 1977 OpBranch %9 1978 1979 %9 = OpLabel 1980 %10 = OpPhi %7 %8 %5 1981 OpStore %10 %11 1982 OpReturn 1983 1984 OpFunctionEnd 1985 )"; 1986 1987 std::string recipient_shader = R"( 1988 OpCapability Shader 1989 %1 = OpExtInstImport "GLSL.std.450" 1990 OpMemoryModel Logical GLSL450 1991 OpEntryPoint Fragment %4 "main" 1992 OpExecutionMode %4 OriginUpperLeft 1993 OpSource ESSL 310 1994 %2 = OpTypeVoid 1995 %3 = OpTypeFunction %2 1996 %4 = OpFunction %2 None %3 1997 %5 = OpLabel 1998 OpReturn 1999 OpFunctionEnd 2000 )"; 2001 2002 const auto env = SPV_ENV_UNIVERSAL_1_3; 2003 const auto consumer = nullptr; 2004 spvtools::ValidatorOptions validator_options; 2005 2006 const auto recipient_context = 2007 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 2008 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2009 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 2010 2011 const auto donor_context = 2012 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 2013 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2014 donor_context.get(), validator_options, kConsoleMessageConsumer)); 2015 2016 TransformationContext transformation_context( 2017 MakeUnique<FactManager>(recipient_context.get()), validator_options); 2018 2019 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 2020 false); 2021 protobufs::TransformationSequence transformation_sequence; 2022 2023 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 2024 &transformation_context, &fuzzer_context, 2025 &transformation_sequence, false, {}); 2026 2027 ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability( 2028 spv::Capability::VariablePointersStorageBuffer)); 2029 ASSERT_FALSE(recipient_context->get_feature_mgr()->HasCapability( 2030 spv::Capability::VariablePointersStorageBuffer)); 2031 2032 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 2033 2034 // Check that recipient module hasn't changed. 2035 ASSERT_TRUE(IsEqual(env, recipient_shader, recipient_context.get())); 2036 2037 // Add the missing capability. 2038 // 2039 // We are adding VariablePointers to test the case when donor and recipient 2040 // have different OpCapability instructions but the same capabilities. In our 2041 // example, VariablePointers implicitly declares 2042 // VariablePointersStorageBuffer. Thus, two modules must be compatible. 2043 recipient_context->AddCapability(spv::Capability::VariablePointers); 2044 2045 ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability( 2046 spv::Capability::VariablePointersStorageBuffer)); 2047 ASSERT_TRUE(recipient_context->get_feature_mgr()->HasCapability( 2048 spv::Capability::VariablePointersStorageBuffer)); 2049 2050 fuzzer_pass.DonateSingleModule(donor_context.get(), false); 2051 2052 // Check that donation was successful. 2053 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2054 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 2055 2056 std::string after_transformation = R"( 2057 OpCapability Shader 2058 OpCapability VariablePointers 2059 %1 = OpExtInstImport "GLSL.std.450" 2060 OpMemoryModel Logical GLSL450 2061 OpEntryPoint Fragment %4 "main" 2062 OpExecutionMode %4 OriginUpperLeft 2063 OpSource ESSL 310 2064 %2 = OpTypeVoid 2065 %3 = OpTypeFunction %2 2066 %100 = OpTypeFloat 32 2067 %101 = OpConstant %100 23 2068 %102 = OpTypePointer Function %100 2069 %105 = OpConstant %100 0 2070 %4 = OpFunction %2 None %3 2071 %5 = OpLabel 2072 OpReturn 2073 OpFunctionEnd 2074 %103 = OpFunction %2 None %3 2075 %104 = OpLabel 2076 %106 = OpVariable %102 Function %105 2077 OpBranch %107 2078 %107 = OpLabel 2079 %108 = OpPhi %102 %106 %104 2080 OpStore %108 %101 2081 OpReturn 2082 OpFunctionEnd 2083 )"; 2084 2085 ASSERT_TRUE(IsEqual(env, after_transformation, recipient_context.get())); 2086} 2087 2088TEST(FuzzerPassDonateModulesTest, HandlesOpPhisInMergeBlock) { 2089 std::string donor_shader = R"( 2090 ; OpPhis don't support pointers without this capability 2091 ; and we need pointers to test some of the functionality 2092 OpCapability VariablePointers 2093 OpCapability Shader 2094 %1 = OpExtInstImport "GLSL.std.450" 2095 OpMemoryModel Logical GLSL450 2096 OpEntryPoint Fragment %4 "main" 2097 OpExecutionMode %4 OriginUpperLeft 2098 OpSource ESSL 310 2099 %2 = OpTypeVoid 2100 %3 = OpTypeFunction %2 2101 %14 = OpTypeBool 2102 %15 = OpConstantTrue %14 2103 %42 = OpTypePointer Function %14 2104 2105 ; back-edge block is unreachable in the CFG 2106 %4 = OpFunction %2 None %3 2107 %5 = OpLabel 2108 OpBranch %6 2109 %6 = OpLabel 2110 OpLoopMerge %8 %7 None 2111 OpBranch %8 2112 %7 = OpLabel 2113 OpBranch %6 2114 %8 = OpLabel 2115 OpReturn 2116 OpFunctionEnd 2117 2118 ; back-edge block already has an edge to the merge block 2119 %9 = OpFunction %2 None %3 2120 %10 = OpLabel 2121 OpBranch %11 2122 %11 = OpLabel 2123 OpLoopMerge %13 %12 None 2124 OpBranch %12 2125 %12 = OpLabel 2126 OpBranchConditional %15 %11 %13 2127 %13 = OpLabel 2128 OpReturn 2129 OpFunctionEnd 2130 2131 ; merge block has no OpPhis 2132 %16 = OpFunction %2 None %3 2133 %17 = OpLabel 2134 OpBranch %18 2135 %18 = OpLabel 2136 OpLoopMerge %20 %19 None 2137 OpBranchConditional %15 %19 %20 2138 %19 = OpLabel 2139 OpBranch %18 2140 %20 = OpLabel 2141 OpReturn 2142 OpFunctionEnd 2143 2144 ; merge block has OpPhis and some of their operands are available at 2145 ; the back-edge block 2146 %21 = OpFunction %2 None %3 2147 %22 = OpLabel 2148 OpBranch %23 2149 %23 = OpLabel 2150 %24 = OpCopyObject %14 %15 2151 OpLoopMerge %28 %27 None 2152 OpBranchConditional %15 %25 %28 2153 %25 = OpLabel 2154 %26 = OpCopyObject %14 %15 2155 OpBranchConditional %15 %28 %27 2156 %27 = OpLabel 2157 OpBranch %23 2158 %28 = OpLabel 2159 %29 = OpPhi %14 %24 %23 %26 %25 2160 OpReturn 2161 OpFunctionEnd 2162 2163 ; none of the OpPhis' operands dominate the back-edge block but some of 2164 ; them have basic type 2165 %30 = OpFunction %2 None %3 2166 %31 = OpLabel 2167 OpBranch %32 2168 %32 = OpLabel 2169 OpLoopMerge %40 %39 None 2170 OpBranch %33 2171 %33 = OpLabel 2172 OpSelectionMerge %38 None 2173 OpBranchConditional %15 %34 %36 2174 %34 = OpLabel 2175 %35 = OpCopyObject %14 %15 2176 OpBranchConditional %35 %38 %40 2177 %36 = OpLabel 2178 %37 = OpCopyObject %14 %15 2179 OpBranchConditional %37 %38 %40 2180 %38 = OpLabel 2181 OpBranch %39 2182 %39 = OpLabel 2183 OpBranch %32 2184 %40 = OpLabel 2185 %41 = OpPhi %14 %35 %34 %37 %36 2186 OpReturn 2187 OpFunctionEnd 2188 2189 ; none of the OpPhis' operands dominate the back-edge block and none of 2190 ; them have basic type 2191 %43 = OpFunction %2 None %3 2192 %44 = OpLabel 2193 %45 = OpVariable %42 Function 2194 OpBranch %46 2195 %46 = OpLabel 2196 OpLoopMerge %54 %53 None 2197 OpBranch %47 2198 %47 = OpLabel 2199 OpSelectionMerge %52 None 2200 OpBranchConditional %15 %48 %50 2201 %48 = OpLabel 2202 %49 = OpCopyObject %42 %45 2203 OpBranchConditional %15 %52 %54 2204 %50 = OpLabel 2205 %51 = OpCopyObject %42 %45 2206 OpBranchConditional %15 %52 %54 2207 %52 = OpLabel 2208 OpBranch %53 2209 %53 = OpLabel 2210 OpBranch %46 2211 %54 = OpLabel 2212 %55 = OpPhi %42 %49 %48 %51 %50 2213 OpReturn 2214 OpFunctionEnd 2215 )"; 2216 2217 std::string recipient_shader = R"( 2218 ; OpPhis don't support pointers without this capability 2219 ; and we need pointers to test some of the functionality 2220 OpCapability VariablePointers 2221 OpCapability Shader 2222 %1 = OpExtInstImport "GLSL.std.450" 2223 OpMemoryModel Logical GLSL450 2224 OpEntryPoint Fragment %4 "main" 2225 OpExecutionMode %4 OriginUpperLeft 2226 OpSource ESSL 310 2227 %2 = OpTypeVoid 2228 %3 = OpTypeFunction %2 2229 %4 = OpFunction %2 None %3 2230 %5 = OpLabel 2231 OpReturn 2232 OpFunctionEnd 2233 )"; 2234 2235 const auto env = SPV_ENV_UNIVERSAL_1_3; 2236 const auto consumer = nullptr; 2237 spvtools::ValidatorOptions validator_options; 2238 2239 const auto recipient_context = 2240 BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption); 2241 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2242 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 2243 2244 const auto donor_context = 2245 BuildModule(env, consumer, donor_shader, kFuzzAssembleOption); 2246 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2247 donor_context.get(), validator_options, kConsoleMessageConsumer)); 2248 2249 TransformationContext transformation_context( 2250 MakeUnique<FactManager>(recipient_context.get()), validator_options); 2251 2252 FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 2253 false); 2254 protobufs::TransformationSequence transformation_sequence; 2255 2256 FuzzerPassDonateModules fuzzer_pass(recipient_context.get(), 2257 &transformation_context, &fuzzer_context, 2258 &transformation_sequence, false, {}); 2259 2260 fuzzer_pass.DonateSingleModule(donor_context.get(), true); 2261 2262 // We just check that the result is valid. Checking to what it should be 2263 // exactly equal to would be very fragile. 2264 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed( 2265 recipient_context.get(), validator_options, kConsoleMessageConsumer)); 2266} 2267 2268} // namespace 2269} // namespace fuzz 2270} // namespace spvtools 2271