mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-22 11:40:05 +00:00
d35a78db57
Fixes #4960 * Switches to using enum classes with an underlying type to avoid undefined behaviour
2271 lines
82 KiB
C++
2271 lines
82 KiB
C++
// Copyright (c) 2019 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "source/fuzz/fuzzer_pass_donate_modules.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "source/fuzz/pseudo_random_generator.h"
|
|
#include "test/fuzz/fuzz_test_util.h"
|
|
|
|
namespace spvtools {
|
|
namespace fuzz {
|
|
namespace {
|
|
|
|
TEST(FuzzerPassDonateModulesTest, BasicDonation) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %10 "m"
|
|
OpName %16 "v"
|
|
OpDecorate %16 RelaxedPrecision
|
|
OpDecorate %20 RelaxedPrecision
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeVector %6 3
|
|
%8 = OpTypeMatrix %7 2
|
|
%9 = OpTypePointer Private %8
|
|
%10 = OpVariable %9 Private
|
|
%11 = OpTypeInt 32 1
|
|
%12 = OpConstant %11 0
|
|
%13 = OpTypeInt 32 0
|
|
%14 = OpTypeVector %13 4
|
|
%15 = OpTypePointer Private %14
|
|
%16 = OpVariable %15 Private
|
|
%17 = OpConstant %13 2
|
|
%18 = OpTypePointer Private %13
|
|
%22 = OpConstant %13 0
|
|
%23 = OpTypePointer Private %6
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%19 = OpAccessChain %18 %16 %17
|
|
%20 = OpLoad %13 %19
|
|
%21 = OpConvertUToF %6 %20
|
|
%24 = OpAccessChain %23 %10 %12 %22
|
|
OpStore %24 %21
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %12 "bar(mf24;"
|
|
OpName %11 "m"
|
|
OpName %20 "foo(vu4;"
|
|
OpName %19 "v"
|
|
OpName %23 "x"
|
|
OpName %26 "param"
|
|
OpName %29 "result"
|
|
OpName %31 "i"
|
|
OpName %81 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeVector %6 4
|
|
%8 = OpTypeMatrix %7 2
|
|
%9 = OpTypePointer Function %8
|
|
%10 = OpTypeFunction %6 %9
|
|
%14 = OpTypeInt 32 0
|
|
%15 = OpTypeVector %14 4
|
|
%16 = OpTypePointer Function %15
|
|
%17 = OpTypeInt 32 1
|
|
%18 = OpTypeFunction %17 %16
|
|
%22 = OpTypePointer Function %17
|
|
%24 = OpConstant %14 2
|
|
%25 = OpConstantComposite %15 %24 %24 %24 %24
|
|
%28 = OpTypePointer Function %6
|
|
%30 = OpConstant %6 0
|
|
%32 = OpConstant %17 0
|
|
%39 = OpConstant %17 10
|
|
%40 = OpTypeBool
|
|
%43 = OpConstant %17 3
|
|
%50 = OpConstant %17 1
|
|
%55 = OpConstant %14 0
|
|
%56 = OpTypePointer Function %14
|
|
%59 = OpConstant %14 1
|
|
%65 = OpConstant %17 2
|
|
%68 = OpConstant %6 1
|
|
%69 = OpConstant %6 2
|
|
%70 = OpConstant %6 3
|
|
%71 = OpConstant %6 4
|
|
%72 = OpConstant %14 3
|
|
%76 = OpConstant %6 6
|
|
%77 = OpConstant %6 7
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%23 = OpVariable %22 Function
|
|
%26 = OpVariable %16 Function
|
|
OpStore %26 %25
|
|
%27 = OpFunctionCall %17 %20 %26
|
|
OpStore %23 %27
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%12 = OpFunction %6 None %10
|
|
%11 = OpFunctionParameter %9
|
|
%13 = OpLabel
|
|
%29 = OpVariable %28 Function
|
|
%31 = OpVariable %22 Function
|
|
OpStore %29 %30
|
|
OpStore %31 %32
|
|
OpBranch %33
|
|
%33 = OpLabel
|
|
OpLoopMerge %35 %36 None
|
|
OpBranch %37
|
|
%37 = OpLabel
|
|
%38 = OpLoad %17 %31
|
|
%41 = OpSLessThan %40 %38 %39
|
|
OpBranchConditional %41 %34 %35
|
|
%34 = OpLabel
|
|
%42 = OpLoad %17 %31
|
|
%44 = OpExtInst %17 %1 SClamp %42 %32 %43
|
|
%45 = OpAccessChain %28 %11 %32 %44
|
|
%46 = OpLoad %6 %45
|
|
%47 = OpLoad %6 %29
|
|
%48 = OpFAdd %6 %47 %46
|
|
OpStore %29 %48
|
|
OpBranch %36
|
|
%36 = OpLabel
|
|
%49 = OpLoad %17 %31
|
|
%51 = OpIAdd %17 %49 %50
|
|
OpStore %31 %51
|
|
OpBranch %33
|
|
%35 = OpLabel
|
|
%52 = OpLoad %6 %29
|
|
OpReturnValue %52
|
|
OpFunctionEnd
|
|
%20 = OpFunction %17 None %18
|
|
%19 = OpFunctionParameter %16
|
|
%21 = OpLabel
|
|
%81 = OpVariable %9 Function
|
|
%57 = OpAccessChain %56 %19 %55
|
|
%58 = OpLoad %14 %57
|
|
%60 = OpAccessChain %56 %19 %59
|
|
%61 = OpLoad %14 %60
|
|
%62 = OpUGreaterThan %40 %58 %61
|
|
OpSelectionMerge %64 None
|
|
OpBranchConditional %62 %63 %67
|
|
%63 = OpLabel
|
|
OpReturnValue %65
|
|
%67 = OpLabel
|
|
%73 = OpAccessChain %56 %19 %72
|
|
%74 = OpLoad %14 %73
|
|
%75 = OpConvertUToF %6 %74
|
|
%78 = OpCompositeConstruct %7 %30 %68 %69 %70
|
|
%79 = OpCompositeConstruct %7 %71 %75 %76 %77
|
|
%80 = OpCompositeConstruct %8 %78 %79
|
|
OpStore %81 %80
|
|
%82 = OpFunctionCall %6 %12 %81
|
|
%83 = OpConvertFToS %17 %82
|
|
OpReturnValue %83
|
|
%64 = OpLabel
|
|
%85 = OpUndef %17
|
|
OpReturnValue %85
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonationWithUniforms) {
|
|
// This test checks that when donating a shader that contains uniforms,
|
|
// uniform variables and associated pointer types are demoted from having
|
|
// Uniform storage class to Private storage class.
|
|
std::string recipient_and_donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpMemberDecorate %9 0 Offset 0
|
|
OpDecorate %9 Block
|
|
OpDecorate %11 DescriptorSet 0
|
|
OpDecorate %11 Binding 0
|
|
OpMemberDecorate %19 0 Offset 0
|
|
OpDecorate %19 Block
|
|
OpDecorate %21 DescriptorSet 0
|
|
OpDecorate %21 Binding 1
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypePointer Function %6
|
|
%9 = OpTypeStruct %6
|
|
%10 = OpTypePointer Uniform %9
|
|
%11 = OpVariable %10 Uniform
|
|
%12 = OpTypeInt 32 1
|
|
%13 = OpConstant %12 0
|
|
%14 = OpTypePointer Uniform %6
|
|
%17 = OpTypePointer Function %12
|
|
%19 = OpTypeStruct %12
|
|
%20 = OpTypePointer Uniform %19
|
|
%21 = OpVariable %20 Uniform
|
|
%22 = OpTypePointer Uniform %12
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%8 = OpVariable %7 Function
|
|
%18 = OpVariable %17 Function
|
|
%15 = OpAccessChain %14 %11 %13
|
|
%16 = OpLoad %6 %15
|
|
OpStore %8 %16
|
|
%23 = OpAccessChain %22 %21 %13
|
|
%24 = OpLoad %12 %23
|
|
OpStore %18 %24
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context = BuildModule(
|
|
env, consumer, recipient_and_donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context = BuildModule(
|
|
env, consumer, recipient_and_donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
std::string after_transformation = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpMemberDecorate %9 0 Offset 0
|
|
OpDecorate %9 Block
|
|
OpDecorate %11 DescriptorSet 0
|
|
OpDecorate %11 Binding 0
|
|
OpMemberDecorate %19 0 Offset 0
|
|
OpDecorate %19 Block
|
|
OpDecorate %21 DescriptorSet 0
|
|
OpDecorate %21 Binding 1
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypePointer Function %6
|
|
%9 = OpTypeStruct %6
|
|
%10 = OpTypePointer Uniform %9
|
|
%11 = OpVariable %10 Uniform
|
|
%12 = OpTypeInt 32 1
|
|
%13 = OpConstant %12 0
|
|
%14 = OpTypePointer Uniform %6
|
|
%17 = OpTypePointer Function %12
|
|
%19 = OpTypeStruct %12
|
|
%20 = OpTypePointer Uniform %19
|
|
%21 = OpVariable %20 Uniform
|
|
%22 = OpTypePointer Uniform %12
|
|
%100 = OpTypePointer Function %6
|
|
%101 = OpTypeStruct %6
|
|
%102 = OpTypePointer Private %101
|
|
%104 = OpConstant %6 0
|
|
%105 = OpConstantComposite %101 %104
|
|
%103 = OpVariable %102 Private %105
|
|
%106 = OpConstant %12 0
|
|
%107 = OpTypePointer Private %6
|
|
%108 = OpTypePointer Function %12
|
|
%109 = OpTypeStruct %12
|
|
%110 = OpTypePointer Private %109
|
|
%112 = OpConstantComposite %109 %13
|
|
%111 = OpVariable %110 Private %112
|
|
%113 = OpTypePointer Private %12
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%8 = OpVariable %7 Function
|
|
%18 = OpVariable %17 Function
|
|
%15 = OpAccessChain %14 %11 %13
|
|
%16 = OpLoad %6 %15
|
|
OpStore %8 %16
|
|
%23 = OpAccessChain %22 %21 %13
|
|
%24 = OpLoad %12 %23
|
|
OpStore %18 %24
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%114 = OpFunction %2 None %3
|
|
%115 = OpLabel
|
|
%116 = OpVariable %100 Function %104
|
|
%117 = OpVariable %108 Function %13
|
|
%118 = OpAccessChain %107 %103 %106
|
|
%119 = OpLoad %6 %118
|
|
OpStore %116 %119
|
|
%120 = OpAccessChain %113 %111 %106
|
|
%121 = OpLoad %12 %120
|
|
OpStore %117 %121
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
ASSERT_TRUE(IsEqual(env, after_transformation, recipient_context.get()));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonationWithInputAndOutputVariables) {
|
|
// This test checks that when donating a shader that contains input and output
|
|
// variables, such variables and associated pointer types are demoted to have
|
|
// the Private storage class.
|
|
std::string recipient_and_donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main" %9 %11
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpDecorate %9 Location 0
|
|
OpDecorate %11 Location 1
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeVector %6 4
|
|
%8 = OpTypePointer Output %7
|
|
%9 = OpVariable %8 Output
|
|
%10 = OpTypePointer Input %7
|
|
%11 = OpVariable %10 Input
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%12 = OpLoad %7 %11
|
|
OpStore %9 %12
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context = BuildModule(
|
|
env, consumer, recipient_and_donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context = BuildModule(
|
|
env, consumer, recipient_and_donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
std::string after_transformation = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main" %9 %11
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpDecorate %9 Location 0
|
|
OpDecorate %11 Location 1
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeVector %6 4
|
|
%8 = OpTypePointer Output %7
|
|
%9 = OpVariable %8 Output
|
|
%10 = OpTypePointer Input %7
|
|
%11 = OpVariable %10 Input
|
|
%100 = OpTypePointer Private %7
|
|
%102 = OpConstant %6 0
|
|
%103 = OpConstantComposite %7 %102 %102 %102 %102
|
|
%101 = OpVariable %100 Private %103
|
|
%104 = OpTypePointer Private %7
|
|
%105 = OpVariable %104 Private %103
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%12 = OpLoad %7 %11
|
|
OpStore %9 %12
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%106 = OpFunction %2 None %3
|
|
%107 = OpLabel
|
|
%108 = OpLoad %7 %105
|
|
OpStore %101 %108
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
ASSERT_TRUE(IsEqual(env, after_transformation, recipient_context.get()));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateFunctionTypeWithDifferentPointers) {
|
|
std::string recipient_and_donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 0
|
|
%7 = OpTypePointer Function %6
|
|
%8 = OpTypeFunction %2 %7
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%9 = OpVariable %7 Function
|
|
%10 = OpFunctionCall %2 %11 %9
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%11 = OpFunction %2 None %8
|
|
%12 = OpFunctionParameter %7
|
|
%13 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_5;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context = BuildModule(
|
|
env, consumer, recipient_and_donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context = BuildModule(
|
|
env, consumer, recipient_and_donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateOpConstantNull) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
OpCapability VariablePointers
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
OpCapability VariablePointers
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypePointer Private %6
|
|
%8 = OpConstantNull %7
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImages) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
OpName %4 "main"
|
|
OpName %10 "mySampler"
|
|
OpName %21 "myTexture"
|
|
OpName %33 "v"
|
|
OpDecorate %10 RelaxedPrecision
|
|
OpDecorate %10 DescriptorSet 0
|
|
OpDecorate %10 Binding 0
|
|
OpDecorate %11 RelaxedPrecision
|
|
OpDecorate %21 RelaxedPrecision
|
|
OpDecorate %21 DescriptorSet 0
|
|
OpDecorate %21 Binding 1
|
|
OpDecorate %22 RelaxedPrecision
|
|
OpDecorate %34 RelaxedPrecision
|
|
OpDecorate %40 RelaxedPrecision
|
|
OpDecorate %42 RelaxedPrecision
|
|
OpDecorate %43 RelaxedPrecision
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeImage %6 2D 0 0 0 1 Unknown
|
|
%8 = OpTypeSampledImage %7
|
|
%9 = OpTypePointer UniformConstant %8
|
|
%10 = OpVariable %9 UniformConstant
|
|
%12 = OpTypeInt 32 1
|
|
%13 = OpConstant %12 2
|
|
%15 = OpTypeVector %12 2
|
|
%17 = OpTypeInt 32 0
|
|
%18 = OpConstant %17 0
|
|
%20 = OpTypePointer UniformConstant %7
|
|
%21 = OpVariable %20 UniformConstant
|
|
%23 = OpConstant %12 1
|
|
%25 = OpConstant %17 1
|
|
%27 = OpTypeBool
|
|
%31 = OpTypeVector %6 4
|
|
%32 = OpTypePointer Function %31
|
|
%35 = OpConstantComposite %15 %23 %23
|
|
%36 = OpConstant %12 3
|
|
%37 = OpConstant %12 4
|
|
%38 = OpConstantComposite %15 %36 %37
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%33 = OpVariable %32 Function
|
|
%11 = OpLoad %8 %10
|
|
%14 = OpImage %7 %11
|
|
%16 = OpImageQuerySizeLod %15 %14 %13
|
|
%19 = OpCompositeExtract %12 %16 0
|
|
%22 = OpLoad %7 %21
|
|
%24 = OpImageQuerySizeLod %15 %22 %23
|
|
%26 = OpCompositeExtract %12 %24 1
|
|
%28 = OpSGreaterThan %27 %19 %26
|
|
OpSelectionMerge %30 None
|
|
OpBranchConditional %28 %29 %41
|
|
%29 = OpLabel
|
|
%34 = OpLoad %8 %10
|
|
%39 = OpImage %7 %34
|
|
%40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38
|
|
OpStore %33 %40
|
|
OpBranch %30
|
|
%41 = OpLabel
|
|
%42 = OpLoad %7 %21
|
|
%43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38
|
|
OpStore %33 %43
|
|
OpBranch %30
|
|
%30 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesSampler) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpDecorate %16 DescriptorSet 0
|
|
OpDecorate %16 Binding 0
|
|
OpDecorate %12 DescriptorSet 0
|
|
OpDecorate %12 Binding 64
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%23 = OpTypeFloat 32
|
|
%6 = OpTypeImage %23 2D 2 0 0 1 Unknown
|
|
%47 = OpTypePointer UniformConstant %6
|
|
%12 = OpVariable %47 UniformConstant
|
|
%15 = OpTypeSampler
|
|
%55 = OpTypePointer UniformConstant %15
|
|
%17 = OpTypeSampledImage %6
|
|
%16 = OpVariable %55 UniformConstant
|
|
%37 = OpTypeVector %23 4
|
|
%109 = OpConstant %23 0
|
|
%66 = OpConstantComposite %37 %109 %109 %109 %109
|
|
%56 = OpTypeBool
|
|
%54 = OpConstantTrue %56
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpBranch %50
|
|
%50 = OpLabel
|
|
%51 = OpPhi %37 %66 %5 %111 %53
|
|
OpLoopMerge %52 %53 None
|
|
OpBranchConditional %54 %53 %52
|
|
%53 = OpLabel
|
|
%106 = OpLoad %6 %12
|
|
%107 = OpLoad %15 %16
|
|
%110 = OpSampledImage %17 %106 %107
|
|
%111 = OpImageSampleImplicitLod %37 %110 %66 Bias %109
|
|
OpBranch %50
|
|
%52 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageStructField) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
OpName %4 "main"
|
|
OpName %10 "mySampler"
|
|
OpName %21 "myTexture"
|
|
OpName %33 "v"
|
|
OpDecorate %10 RelaxedPrecision
|
|
OpDecorate %10 DescriptorSet 0
|
|
OpDecorate %10 Binding 0
|
|
OpDecorate %11 RelaxedPrecision
|
|
OpDecorate %21 RelaxedPrecision
|
|
OpDecorate %21 DescriptorSet 0
|
|
OpDecorate %21 Binding 1
|
|
OpDecorate %22 RelaxedPrecision
|
|
OpDecorate %34 RelaxedPrecision
|
|
OpDecorate %40 RelaxedPrecision
|
|
OpDecorate %42 RelaxedPrecision
|
|
OpDecorate %43 RelaxedPrecision
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeImage %6 2D 0 0 0 1 Unknown
|
|
%8 = OpTypeSampledImage %7
|
|
%9 = OpTypePointer UniformConstant %8
|
|
%10 = OpVariable %9 UniformConstant
|
|
%12 = OpTypeInt 32 1
|
|
%13 = OpConstant %12 2
|
|
%15 = OpTypeVector %12 2
|
|
%17 = OpTypeInt 32 0
|
|
%18 = OpConstant %17 0
|
|
%20 = OpTypePointer UniformConstant %7
|
|
%21 = OpVariable %20 UniformConstant
|
|
%23 = OpConstant %12 1
|
|
%25 = OpConstant %17 1
|
|
%27 = OpTypeBool
|
|
%31 = OpTypeVector %6 4
|
|
%32 = OpTypePointer Function %31
|
|
%35 = OpConstantComposite %15 %23 %23
|
|
%36 = OpConstant %12 3
|
|
%37 = OpConstant %12 4
|
|
%38 = OpConstantComposite %15 %36 %37
|
|
%201 = OpTypeStruct %7 %7
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%33 = OpVariable %32 Function
|
|
%11 = OpLoad %8 %10
|
|
%14 = OpImage %7 %11
|
|
%22 = OpLoad %7 %21
|
|
%200 = OpCompositeConstruct %201 %14 %22
|
|
%202 = OpCompositeExtract %7 %200 0
|
|
%203 = OpCompositeExtract %7 %200 1
|
|
%24 = OpImageQuerySizeLod %15 %203 %23
|
|
%16 = OpImageQuerySizeLod %15 %202 %13
|
|
%26 = OpCompositeExtract %12 %24 1
|
|
%19 = OpCompositeExtract %12 %16 0
|
|
%28 = OpSGreaterThan %27 %19 %26
|
|
OpSelectionMerge %30 None
|
|
OpBranchConditional %28 %29 %41
|
|
%29 = OpLabel
|
|
%34 = OpLoad %8 %10
|
|
%39 = OpImage %7 %34
|
|
%40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38
|
|
OpStore %33 %40
|
|
OpBranch %30
|
|
%41 = OpLabel
|
|
%42 = OpLoad %7 %21
|
|
%43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38
|
|
OpStore %33 %43
|
|
OpBranch %30
|
|
%30 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateCodeThatUsesImageFunctionParameter) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
OpName %4 "main"
|
|
OpName %10 "mySampler"
|
|
OpName %21 "myTexture"
|
|
OpName %33 "v"
|
|
OpDecorate %10 RelaxedPrecision
|
|
OpDecorate %10 DescriptorSet 0
|
|
OpDecorate %10 Binding 0
|
|
OpDecorate %11 RelaxedPrecision
|
|
OpDecorate %21 RelaxedPrecision
|
|
OpDecorate %21 DescriptorSet 0
|
|
OpDecorate %21 Binding 1
|
|
OpDecorate %22 RelaxedPrecision
|
|
OpDecorate %34 RelaxedPrecision
|
|
OpDecorate %40 RelaxedPrecision
|
|
OpDecorate %42 RelaxedPrecision
|
|
OpDecorate %43 RelaxedPrecision
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%7 = OpTypeImage %6 2D 0 0 0 1 Unknown
|
|
%8 = OpTypeSampledImage %7
|
|
%9 = OpTypePointer UniformConstant %8
|
|
%10 = OpVariable %9 UniformConstant
|
|
%12 = OpTypeInt 32 1
|
|
%13 = OpConstant %12 2
|
|
%15 = OpTypeVector %12 2
|
|
%17 = OpTypeInt 32 0
|
|
%18 = OpConstant %17 0
|
|
%20 = OpTypePointer UniformConstant %7
|
|
%21 = OpVariable %20 UniformConstant
|
|
%23 = OpConstant %12 1
|
|
%25 = OpConstant %17 1
|
|
%27 = OpTypeBool
|
|
%31 = OpTypeVector %6 4
|
|
%32 = OpTypePointer Function %31
|
|
%35 = OpConstantComposite %15 %23 %23
|
|
%36 = OpConstant %12 3
|
|
%37 = OpConstant %12 4
|
|
%38 = OpConstantComposite %15 %36 %37
|
|
%201 = OpTypeFunction %15 %7 %12
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%33 = OpVariable %32 Function
|
|
%11 = OpLoad %8 %10
|
|
%14 = OpImage %7 %11
|
|
%16 = OpFunctionCall %15 %200 %14 %13
|
|
%19 = OpCompositeExtract %12 %16 0
|
|
%22 = OpLoad %7 %21
|
|
%24 = OpImageQuerySizeLod %15 %22 %23
|
|
%26 = OpCompositeExtract %12 %24 1
|
|
%28 = OpSGreaterThan %27 %19 %26
|
|
OpSelectionMerge %30 None
|
|
OpBranchConditional %28 %29 %41
|
|
%29 = OpLabel
|
|
%34 = OpLoad %8 %10
|
|
%39 = OpImage %7 %34
|
|
%40 = OpImageFetch %31 %39 %35 Lod|ConstOffset %13 %38
|
|
OpStore %33 %40
|
|
OpBranch %30
|
|
%41 = OpLabel
|
|
%42 = OpLoad %7 %21
|
|
%43 = OpImageFetch %31 %42 %35 Lod|ConstOffset %13 %38
|
|
OpStore %33 %43
|
|
OpBranch %30
|
|
%30 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%200 = OpFunction %15 None %201
|
|
%202 = OpFunctionParameter %7
|
|
%203 = OpFunctionParameter %12
|
|
%204 = OpLabel
|
|
%205 = OpImageQuerySizeLod %15 %202 %203
|
|
OpReturnValue %205
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateShaderWithImageStorageClass) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability ImageQuery
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 320
|
|
OpSourceExtension "GL_EXT_samplerless_texture_functions"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
OpCapability SampledBuffer
|
|
OpCapability ImageBuffer
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %2 "MainPSPacked"
|
|
OpExecutionMode %2 OriginUpperLeft
|
|
OpDecorate %18 DescriptorSet 0
|
|
OpDecorate %18 Binding 128
|
|
%49 = OpTypeInt 32 0
|
|
%50 = OpTypeFloat 32
|
|
%58 = OpConstant %50 1
|
|
%66 = OpConstant %49 0
|
|
%87 = OpTypeVector %50 2
|
|
%88 = OpConstantComposite %87 %58 %58
|
|
%17 = OpTypeImage %49 2D 2 0 0 2 R32ui
|
|
%118 = OpTypePointer UniformConstant %17
|
|
%123 = OpTypeVector %49 2
|
|
%132 = OpTypeVoid
|
|
%133 = OpTypeFunction %132
|
|
%142 = OpTypePointer Image %49
|
|
%18 = OpVariable %118 UniformConstant
|
|
%2 = OpFunction %132 None %133
|
|
%153 = OpLabel
|
|
%495 = OpConvertFToU %123 %88
|
|
%501 = OpImageTexelPointer %142 %18 %495 %66
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), true);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArray) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
OpDecorate %9 ArrayStride 4
|
|
OpMemberDecorate %10 0 Offset 0
|
|
OpDecorate %10 BufferBlock
|
|
OpDecorate %12 DescriptorSet 0
|
|
OpDecorate %12 Binding 0
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 1
|
|
%7 = OpTypePointer Function %6
|
|
%9 = OpTypeRuntimeArray %6
|
|
%10 = OpTypeStruct %9
|
|
%11 = OpTypePointer Uniform %10
|
|
%12 = OpVariable %11 Uniform
|
|
%13 = OpTypeInt 32 0
|
|
%16 = OpConstant %6 0
|
|
%18 = OpConstant %6 1
|
|
%20 = OpTypePointer Uniform %6
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%8 = OpVariable %7 Function
|
|
%14 = OpArrayLength %13 %12 0
|
|
%15 = OpBitcast %6 %14
|
|
OpStore %8 %15
|
|
%17 = OpLoad %6 %8
|
|
%19 = OpISub %6 %17 %18
|
|
%21 = OpAccessChain %20 %12 %16 %19
|
|
OpStore %21 %16
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithRuntimeArrayLivesafe) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
OpDecorate %16 ArrayStride 4
|
|
OpMemberDecorate %17 0 Offset 0
|
|
OpDecorate %17 BufferBlock
|
|
OpDecorate %19 DescriptorSet 0
|
|
OpDecorate %19 Binding 0
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 1
|
|
%7 = OpTypePointer Function %6
|
|
%9 = OpConstant %6 0
|
|
%16 = OpTypeRuntimeArray %6
|
|
%17 = OpTypeStruct %16
|
|
%18 = OpTypePointer Uniform %17
|
|
%19 = OpVariable %18 Uniform
|
|
%20 = OpTypeInt 32 0
|
|
%23 = OpTypeBool
|
|
%26 = OpConstant %6 32
|
|
%27 = OpTypePointer Uniform %6
|
|
%30 = OpConstant %6 1
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%8 = OpVariable %7 Function
|
|
OpStore %8 %9
|
|
OpBranch %10
|
|
%10 = OpLabel
|
|
OpLoopMerge %12 %13 None
|
|
OpBranch %14
|
|
%14 = OpLabel
|
|
%15 = OpLoad %6 %8
|
|
%21 = OpArrayLength %20 %19 0
|
|
%22 = OpBitcast %6 %21
|
|
%24 = OpSLessThan %23 %15 %22
|
|
OpBranchConditional %24 %11 %12
|
|
%11 = OpLabel
|
|
%25 = OpLoad %6 %8
|
|
%28 = OpAccessChain %27 %19 %9 %25
|
|
OpStore %28 %26
|
|
OpBranch %13
|
|
%13 = OpLabel
|
|
%29 = OpLoad %6 %8
|
|
%31 = OpIAdd %6 %29 %30
|
|
OpStore %8 %31
|
|
OpBranch %10
|
|
%12 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), true);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithWorkgroupVariables) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 1
|
|
%7 = OpTypePointer Workgroup %6
|
|
%8 = OpVariable %7 Workgroup
|
|
%9 = OpConstant %6 2
|
|
%10 = OpVariable %7 Workgroup
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpStore %8 %9
|
|
%11 = OpLoad %6 %8
|
|
OpStore %10 %11
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), true);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonateComputeShaderWithAtomics) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %4 "main"
|
|
OpExecutionMode %4 LocalSize 1 1 1
|
|
OpSource ESSL 310
|
|
OpMemberDecorate %9 0 Offset 0
|
|
OpDecorate %9 BufferBlock
|
|
OpDecorate %11 DescriptorSet 0
|
|
OpDecorate %11 Binding 0
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 0
|
|
%7 = OpTypePointer Function %6
|
|
%9 = OpTypeStruct %6
|
|
%10 = OpTypePointer Uniform %9
|
|
%11 = OpVariable %10 Uniform
|
|
%12 = OpTypeInt 32 1
|
|
%13 = OpConstant %12 0
|
|
%14 = OpTypePointer Uniform %6
|
|
%16 = OpConstant %6 1
|
|
%17 = OpConstant %6 0
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%8 = OpVariable %7 Function
|
|
%15 = OpAccessChain %14 %11 %13
|
|
%18 = OpAtomicIAdd %6 %15 %16 %17 %16
|
|
OpStore %8 %18
|
|
%19 = OpAccessChain %14 %11 %13
|
|
%20 = OpLoad %6 %8
|
|
%21 = OpAtomicUMin %6 %19 %16 %17 %20
|
|
OpStore %8 %21
|
|
%22 = OpAccessChain %14 %11 %13
|
|
%23 = OpLoad %6 %8
|
|
%24 = OpAtomicUMax %6 %22 %16 %17 %23
|
|
OpStore %8 %24
|
|
%25 = OpAccessChain %14 %11 %13
|
|
%26 = OpLoad %6 %8
|
|
%27 = OpAtomicAnd %6 %25 %16 %17 %26
|
|
OpStore %8 %27
|
|
%28 = OpAccessChain %14 %11 %13
|
|
%29 = OpLoad %6 %8
|
|
%30 = OpAtomicOr %6 %28 %16 %17 %29
|
|
OpStore %8 %30
|
|
%31 = OpAccessChain %14 %11 %13
|
|
%32 = OpLoad %6 %8
|
|
%33 = OpAtomicXor %6 %31 %16 %17 %32
|
|
OpStore %8 %33
|
|
%34 = OpAccessChain %14 %11 %13
|
|
%35 = OpLoad %6 %8
|
|
%36 = OpAtomicExchange %6 %34 %16 %17 %35
|
|
OpStore %8 %36
|
|
%37 = OpAccessChain %14 %11 %13
|
|
%38 = OpLoad %6 %8
|
|
%39 = OpAtomicCompareExchange %6 %37 %16 %17 %17 %16 %38
|
|
OpStore %8 %39
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), true);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, Miscellaneous1) {
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %6 "foo("
|
|
OpName %10 "x"
|
|
OpName %12 "i"
|
|
OpName %33 "i"
|
|
OpName %42 "j"
|
|
OpDecorate %10 RelaxedPrecision
|
|
OpDecorate %12 RelaxedPrecision
|
|
OpDecorate %19 RelaxedPrecision
|
|
OpDecorate %23 RelaxedPrecision
|
|
OpDecorate %24 RelaxedPrecision
|
|
OpDecorate %25 RelaxedPrecision
|
|
OpDecorate %26 RelaxedPrecision
|
|
OpDecorate %27 RelaxedPrecision
|
|
OpDecorate %28 RelaxedPrecision
|
|
OpDecorate %30 RelaxedPrecision
|
|
OpDecorate %33 RelaxedPrecision
|
|
OpDecorate %39 RelaxedPrecision
|
|
OpDecorate %42 RelaxedPrecision
|
|
OpDecorate %49 RelaxedPrecision
|
|
OpDecorate %52 RelaxedPrecision
|
|
OpDecorate %53 RelaxedPrecision
|
|
OpDecorate %58 RelaxedPrecision
|
|
OpDecorate %59 RelaxedPrecision
|
|
OpDecorate %60 RelaxedPrecision
|
|
OpDecorate %63 RelaxedPrecision
|
|
OpDecorate %64 RelaxedPrecision
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%8 = OpTypeInt 32 1
|
|
%9 = OpTypePointer Function %8
|
|
%11 = OpConstant %8 2
|
|
%13 = OpConstant %8 0
|
|
%20 = OpConstant %8 100
|
|
%21 = OpTypeBool
|
|
%29 = OpConstant %8 1
|
|
%40 = OpConstant %8 10
|
|
%43 = OpConstant %8 20
|
|
%61 = OpConstant %8 4
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%33 = OpVariable %9 Function
|
|
%42 = OpVariable %9 Function
|
|
%32 = OpFunctionCall %2 %6
|
|
OpStore %33 %13
|
|
OpBranch %34
|
|
%34 = OpLabel
|
|
OpLoopMerge %36 %37 None
|
|
OpBranch %38
|
|
%38 = OpLabel
|
|
%39 = OpLoad %8 %33
|
|
%41 = OpSLessThan %21 %39 %40
|
|
OpBranchConditional %41 %35 %36
|
|
%35 = OpLabel
|
|
OpStore %42 %43
|
|
OpBranch %44
|
|
%44 = OpLabel
|
|
OpLoopMerge %46 %47 None
|
|
OpBranch %48
|
|
%48 = OpLabel
|
|
%49 = OpLoad %8 %42
|
|
%50 = OpSGreaterThan %21 %49 %13
|
|
OpBranchConditional %50 %45 %46
|
|
%45 = OpLabel
|
|
%51 = OpFunctionCall %2 %6
|
|
%52 = OpLoad %8 %42
|
|
%53 = OpISub %8 %52 %29
|
|
OpStore %42 %53
|
|
OpBranch %47
|
|
%47 = OpLabel
|
|
OpBranch %44
|
|
%46 = OpLabel
|
|
OpBranch %54
|
|
%54 = OpLabel
|
|
OpLoopMerge %56 %57 None
|
|
OpBranch %55
|
|
%55 = OpLabel
|
|
%58 = OpLoad %8 %33
|
|
%59 = OpIAdd %8 %58 %29
|
|
OpStore %33 %59
|
|
OpBranch %57
|
|
%57 = OpLabel
|
|
%60 = OpLoad %8 %33
|
|
%62 = OpSLessThan %21 %60 %61
|
|
OpBranchConditional %62 %54 %56
|
|
%56 = OpLabel
|
|
OpBranch %37
|
|
%37 = OpLabel
|
|
%63 = OpLoad %8 %33
|
|
%64 = OpIAdd %8 %63 %29
|
|
OpStore %33 %64
|
|
OpBranch %34
|
|
%36 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%6 = OpFunction %2 None %3
|
|
%7 = OpLabel
|
|
%10 = OpVariable %9 Function
|
|
%12 = OpVariable %9 Function
|
|
OpStore %10 %11
|
|
OpStore %12 %13
|
|
OpBranch %14
|
|
%14 = OpLabel
|
|
OpLoopMerge %16 %17 None
|
|
OpBranch %18
|
|
%18 = OpLabel
|
|
%19 = OpLoad %8 %12
|
|
%22 = OpSLessThan %21 %19 %20
|
|
OpBranchConditional %22 %15 %16
|
|
%15 = OpLabel
|
|
%23 = OpLoad %8 %12
|
|
%24 = OpLoad %8 %10
|
|
%25 = OpIAdd %8 %24 %23
|
|
OpStore %10 %25
|
|
%26 = OpLoad %8 %10
|
|
%27 = OpIMul %8 %26 %11
|
|
OpStore %10 %27
|
|
OpBranch %17
|
|
%17 = OpLabel
|
|
%28 = OpLoad %8 %12
|
|
%30 = OpIAdd %8 %28 %29
|
|
OpStore %12 %30
|
|
OpBranch %14
|
|
%16 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_5;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, OpSpecConstantInstructions) {
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeBool
|
|
%7 = OpTypeInt 32 1
|
|
%8 = OpTypeStruct %6 %6 %7
|
|
%9 = OpSpecConstantTrue %6
|
|
%10 = OpSpecConstantFalse %6
|
|
%11 = OpSpecConstant %7 2
|
|
%12 = OpSpecConstantComposite %8 %9 %10 %11
|
|
%13 = OpSpecConstantOp %6 LogicalEqual %9 %10
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// Check that the module is valid first.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
std::string expected_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%100 = OpTypeBool
|
|
%101 = OpTypeInt 32 1
|
|
%102 = OpTypeStruct %100 %100 %101
|
|
%103 = OpConstantTrue %100
|
|
%104 = OpConstantFalse %100
|
|
%105 = OpConstant %101 2
|
|
%106 = OpConstantComposite %102 %103 %104 %105
|
|
%107 = OpSpecConstantOp %100 LogicalEqual %103 %104
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%108 = OpFunction %2 None %3
|
|
%109 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
// Now check that the transformation has produced the expected result.
|
|
ASSERT_TRUE(IsEqual(env, expected_shader, recipient_context.get()));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, DonationSupportsOpTypeRuntimeArray) {
|
|
std::string donor_shader = R"(
|
|
OpCapability Shader
|
|
OpExtension "SPV_KHR_storage_buffer_storage_class"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %29 "kernel_1"
|
|
OpEntryPoint GLCompute %37 "kernel_2"
|
|
OpSource OpenCL_C 120
|
|
OpDecorate %2 ArrayStride 4
|
|
OpMemberDecorate %3 0 Offset 0
|
|
OpDecorate %3 Block
|
|
OpMemberDecorate %5 0 Offset 0
|
|
OpMemberDecorate %6 0 Offset 0
|
|
OpDecorate %6 Block
|
|
OpDecorate %21 BuiltIn WorkgroupSize
|
|
OpDecorate %23 DescriptorSet 0
|
|
OpDecorate %23 Binding 0
|
|
OpDecorate %25 SpecId 3
|
|
OpDecorate %18 SpecId 0
|
|
OpDecorate %19 SpecId 1
|
|
OpDecorate %20 SpecId 2
|
|
%1 = OpTypeInt 32 0
|
|
%2 = OpTypeRuntimeArray %1
|
|
%3 = OpTypeStruct %2
|
|
%4 = OpTypePointer StorageBuffer %3
|
|
%5 = OpTypeStruct %1
|
|
%6 = OpTypeStruct %5
|
|
%7 = OpTypePointer PushConstant %6
|
|
%8 = OpTypeFloat 32
|
|
%9 = OpTypeVoid
|
|
%10 = OpTypeFunction %9
|
|
%11 = OpTypePointer Workgroup %1
|
|
%12 = OpTypePointer PushConstant %5
|
|
%13 = OpTypePointer StorageBuffer %1
|
|
%14 = OpTypeFunction %1 %1
|
|
%15 = OpTypeVector %1 3
|
|
%16 = OpTypePointer Private %15
|
|
%17 = OpConstant %1 0
|
|
%18 = OpSpecConstant %1 1
|
|
%19 = OpSpecConstant %1 1
|
|
%20 = OpSpecConstant %1 1
|
|
%21 = OpSpecConstantComposite %15 %18 %19 %20
|
|
%25 = OpSpecConstant %1 1
|
|
%26 = OpTypeArray %1 %25
|
|
%27 = OpTypePointer Workgroup %26
|
|
%22 = OpVariable %16 Private %21
|
|
%23 = OpVariable %4 StorageBuffer
|
|
%24 = OpVariable %7 PushConstant
|
|
%28 = OpVariable %27 Workgroup
|
|
%29 = OpFunction %9 None %10
|
|
%30 = OpLabel
|
|
%31 = OpAccessChain %11 %28 %17
|
|
%32 = OpAccessChain %12 %24 %17
|
|
%33 = OpLoad %5 %32
|
|
%34 = OpCompositeExtract %1 %33 0
|
|
%35 = OpFunctionCall %1 %45 %34
|
|
%36 = OpAccessChain %13 %23 %17 %34
|
|
OpStore %36 %35
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%37 = OpFunction %9 None %10
|
|
%38 = OpLabel
|
|
%39 = OpAccessChain %11 %28 %17
|
|
%40 = OpAccessChain %12 %24 %17
|
|
%41 = OpLoad %5 %40
|
|
%42 = OpCompositeExtract %1 %41 0
|
|
%43 = OpFunctionCall %1 %45 %42
|
|
%44 = OpAccessChain %13 %23 %17 %42
|
|
OpStore %44 %43
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%45 = OpFunction %1 Pure %14
|
|
%46 = OpFunctionParameter %1
|
|
%47 = OpLabel
|
|
%48 = OpAccessChain %11 %28 %46
|
|
%49 = OpLoad %1 %48
|
|
OpReturnValue %49
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_0;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, HandlesCapabilities) {
|
|
std::string donor_shader = R"(
|
|
OpCapability VariablePointersStorageBuffer
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFloat 32
|
|
%11 = OpConstant %6 23
|
|
%7 = OpTypePointer Function %6
|
|
%4 = OpFunction %2 None %3
|
|
|
|
%5 = OpLabel
|
|
%8 = OpVariable %7 Function
|
|
OpBranch %9
|
|
|
|
%9 = OpLabel
|
|
%10 = OpPhi %7 %8 %5
|
|
OpStore %10 %11
|
|
OpReturn
|
|
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string recipient_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
|
|
spv::Capability::VariablePointersStorageBuffer));
|
|
ASSERT_FALSE(recipient_context->get_feature_mgr()->HasCapability(
|
|
spv::Capability::VariablePointersStorageBuffer));
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// Check that recipient module hasn't changed.
|
|
ASSERT_TRUE(IsEqual(env, recipient_shader, recipient_context.get()));
|
|
|
|
// Add the missing capability.
|
|
//
|
|
// We are adding VariablePointers to test the case when donor and recipient
|
|
// have different OpCapability instructions but the same capabilities. In our
|
|
// example, VariablePointers implicitly declares
|
|
// VariablePointersStorageBuffer. Thus, two modules must be compatible.
|
|
recipient_context->AddCapability(spv::Capability::VariablePointers);
|
|
|
|
ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
|
|
spv::Capability::VariablePointersStorageBuffer));
|
|
ASSERT_TRUE(recipient_context->get_feature_mgr()->HasCapability(
|
|
spv::Capability::VariablePointersStorageBuffer));
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), false);
|
|
|
|
// Check that donation was successful.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
std::string after_transformation = R"(
|
|
OpCapability Shader
|
|
OpCapability VariablePointers
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%100 = OpTypeFloat 32
|
|
%101 = OpConstant %100 23
|
|
%102 = OpTypePointer Function %100
|
|
%105 = OpConstant %100 0
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%103 = OpFunction %2 None %3
|
|
%104 = OpLabel
|
|
%106 = OpVariable %102 Function %105
|
|
OpBranch %107
|
|
%107 = OpLabel
|
|
%108 = OpPhi %102 %106 %104
|
|
OpStore %108 %101
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
ASSERT_TRUE(IsEqual(env, after_transformation, recipient_context.get()));
|
|
}
|
|
|
|
TEST(FuzzerPassDonateModulesTest, HandlesOpPhisInMergeBlock) {
|
|
std::string donor_shader = R"(
|
|
; OpPhis don't support pointers without this capability
|
|
; and we need pointers to test some of the functionality
|
|
OpCapability VariablePointers
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%14 = OpTypeBool
|
|
%15 = OpConstantTrue %14
|
|
%42 = OpTypePointer Function %14
|
|
|
|
; back-edge block is unreachable in the CFG
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpBranch %6
|
|
%6 = OpLabel
|
|
OpLoopMerge %8 %7 None
|
|
OpBranch %8
|
|
%7 = OpLabel
|
|
OpBranch %6
|
|
%8 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; back-edge block already has an edge to the merge block
|
|
%9 = OpFunction %2 None %3
|
|
%10 = OpLabel
|
|
OpBranch %11
|
|
%11 = OpLabel
|
|
OpLoopMerge %13 %12 None
|
|
OpBranch %12
|
|
%12 = OpLabel
|
|
OpBranchConditional %15 %11 %13
|
|
%13 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; merge block has no OpPhis
|
|
%16 = OpFunction %2 None %3
|
|
%17 = OpLabel
|
|
OpBranch %18
|
|
%18 = OpLabel
|
|
OpLoopMerge %20 %19 None
|
|
OpBranchConditional %15 %19 %20
|
|
%19 = OpLabel
|
|
OpBranch %18
|
|
%20 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; merge block has OpPhis and some of their operands are available at
|
|
; the back-edge block
|
|
%21 = OpFunction %2 None %3
|
|
%22 = OpLabel
|
|
OpBranch %23
|
|
%23 = OpLabel
|
|
%24 = OpCopyObject %14 %15
|
|
OpLoopMerge %28 %27 None
|
|
OpBranchConditional %15 %25 %28
|
|
%25 = OpLabel
|
|
%26 = OpCopyObject %14 %15
|
|
OpBranchConditional %15 %28 %27
|
|
%27 = OpLabel
|
|
OpBranch %23
|
|
%28 = OpLabel
|
|
%29 = OpPhi %14 %24 %23 %26 %25
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; none of the OpPhis' operands dominate the back-edge block but some of
|
|
; them have basic type
|
|
%30 = OpFunction %2 None %3
|
|
%31 = OpLabel
|
|
OpBranch %32
|
|
%32 = OpLabel
|
|
OpLoopMerge %40 %39 None
|
|
OpBranch %33
|
|
%33 = OpLabel
|
|
OpSelectionMerge %38 None
|
|
OpBranchConditional %15 %34 %36
|
|
%34 = OpLabel
|
|
%35 = OpCopyObject %14 %15
|
|
OpBranchConditional %35 %38 %40
|
|
%36 = OpLabel
|
|
%37 = OpCopyObject %14 %15
|
|
OpBranchConditional %37 %38 %40
|
|
%38 = OpLabel
|
|
OpBranch %39
|
|
%39 = OpLabel
|
|
OpBranch %32
|
|
%40 = OpLabel
|
|
%41 = OpPhi %14 %35 %34 %37 %36
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; none of the OpPhis' operands dominate the back-edge block and none of
|
|
; them have basic type
|
|
%43 = OpFunction %2 None %3
|
|
%44 = OpLabel
|
|
%45 = OpVariable %42 Function
|
|
OpBranch %46
|
|
%46 = OpLabel
|
|
OpLoopMerge %54 %53 None
|
|
OpBranch %47
|
|
%47 = OpLabel
|
|
OpSelectionMerge %52 None
|
|
OpBranchConditional %15 %48 %50
|
|
%48 = OpLabel
|
|
%49 = OpCopyObject %42 %45
|
|
OpBranchConditional %15 %52 %54
|
|
%50 = OpLabel
|
|
%51 = OpCopyObject %42 %45
|
|
OpBranchConditional %15 %52 %54
|
|
%52 = OpLabel
|
|
OpBranch %53
|
|
%53 = OpLabel
|
|
OpBranch %46
|
|
%54 = OpLabel
|
|
%55 = OpPhi %42 %49 %48 %51 %50
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
std::string recipient_shader = R"(
|
|
; OpPhis don't support pointers without this capability
|
|
; and we need pointers to test some of the functionality
|
|
OpCapability VariablePointers
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
spvtools::ValidatorOptions validator_options;
|
|
|
|
const auto recipient_context =
|
|
BuildModule(env, consumer, recipient_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
const auto donor_context =
|
|
BuildModule(env, consumer, donor_shader, kFuzzAssembleOption);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
donor_context.get(), validator_options, kConsoleMessageConsumer));
|
|
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(recipient_context.get()), validator_options);
|
|
|
|
FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100,
|
|
false);
|
|
protobufs::TransformationSequence transformation_sequence;
|
|
|
|
FuzzerPassDonateModules fuzzer_pass(recipient_context.get(),
|
|
&transformation_context, &fuzzer_context,
|
|
&transformation_sequence, false, {});
|
|
|
|
fuzzer_pass.DonateSingleModule(donor_context.get(), true);
|
|
|
|
// We just check that the result is valid. Checking to what it should be
|
|
// exactly equal to would be very fragile.
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
recipient_context.get(), validator_options, kConsoleMessageConsumer));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace fuzz
|
|
} // namespace spvtools
|