Fix flaws in minus-prefix optimization.
We had a logic bug when attempting to optimize the following code: const vecN x = vecN(a, b, c); -x; The goal was to replace `-x` with `vecN(-a, -b, -c)` but we accidentally tried to cast the `x` VariableReference to a Constructor. We unfortunately didn't cover this in any of our test cases, but the fuzzer managed to synthesize it by mixing and matching elements from its new corpus. This affected several different constructor types: splat, diagonal- matrix, compound and array. Change-Id: I10dd2460ab26ba3e820b0cff5db091368fb7e648 Bug: oss-fuzz:37764, oss-fuzz:37861 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/443407 Commit-Queue: John Stiles <johnstiles@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com> Auto-Submit: John Stiles <johnstiles@google.com> Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
75bab9249d
commit
f89a8122a4
@ -332,7 +332,7 @@ sksl_shared_tests = [
|
||||
"/sksl/shared/MatrixScalarSplat.sksl",
|
||||
"/sksl/shared/MatrixToVectorCast.sksl",
|
||||
"/sksl/shared/MultipleAssignments.sksl",
|
||||
"/sksl/shared/NegatedVectorLiteral.sksl",
|
||||
"/sksl/shared/Negation.sksl",
|
||||
"/sksl/shared/NoFragCoordsPos.vert",
|
||||
"/sksl/shared/NoFragCoordsPosRT.vert",
|
||||
"/sksl/shared/NormalizationVert.vert",
|
||||
|
@ -1,31 +0,0 @@
|
||||
uniform half4 colorGreen, colorRed;
|
||||
|
||||
bool test_float() {
|
||||
const float one = 1;
|
||||
float two = 2;
|
||||
|
||||
float4 result;
|
||||
result.r = (half4(-1) == -half4(-half2(-1), half2(1))) ? 1 : 0;
|
||||
result.g = (half4(1) != -half4(1)) ? 1 : 0;
|
||||
result.b = (-half4(two) == half4(-two, half3(-two))) ? 1 : 0;
|
||||
result.a = (-half2(-one, one + one) == -half2(one - two, two)) ? 1 : 0;
|
||||
|
||||
return bool(result.r * result.g * result.b * -(-result.a));
|
||||
}
|
||||
|
||||
bool test_int() {
|
||||
int one = 1;
|
||||
const int two = 2;
|
||||
|
||||
int4 result;
|
||||
result.r = (int4(-1) == -int4(-int2(-1), int2(1))) ? 1 : 0;
|
||||
result.g = (int4(1) != -int4(1)) ? 1 : 0;
|
||||
result.b = (-int4(two) == int4(-two, int3(-two))) ? 1 : 0;
|
||||
result.a = (-int2(-one, one + one) == -int2(one - two, two)) ? 1 : 0;
|
||||
|
||||
return bool(-(-result.r) * result.g * result.b * result.a);
|
||||
}
|
||||
|
||||
half4 main(float2 coords) {
|
||||
return test_float() && test_int() ? colorGreen : colorRed;
|
||||
}
|
67
resources/sksl/shared/Negation.sksl
Normal file
67
resources/sksl/shared/Negation.sksl
Normal file
@ -0,0 +1,67 @@
|
||||
uniform half4 colorGreen, colorRed;
|
||||
|
||||
bool test_fvec() {
|
||||
const float one = 1;
|
||||
float two = 2;
|
||||
const half4 one_splat = half4(1);
|
||||
const half4 one_compound = half4(1, 1, 1, 1);
|
||||
|
||||
bool ok = true;
|
||||
ok = ok && (half4(-1) == -one_splat);
|
||||
ok = ok && (half4(-1, -1, -1, -1) == -one_splat);
|
||||
ok = ok && (half4(-1) == -one_compound);
|
||||
ok = ok && (half4(-1, -1, -1, -1) == -one_compound);
|
||||
ok = ok && (-half4(1) == -one_splat);
|
||||
ok = ok && (-half4(1, 1, 1, 1) == -one_splat);
|
||||
ok = ok && (-half4(1) == -one_compound);
|
||||
ok = ok && (-half4(1, 1, 1, 1) == -one_compound);
|
||||
ok = ok && (half4(-1) == -one_compound);
|
||||
ok = ok && (half4(-1) == -half4(-half2(-1), half2(1)));
|
||||
ok = ok && (half4(1) != -half4(1));
|
||||
ok = ok && (-half4(two) == half4(-two, half3(-two)));
|
||||
ok = ok && (-half2(-one, one + one) == -half2(one - two, two));
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool test_ivec() {
|
||||
int one = 1;
|
||||
const int two = 2;
|
||||
const int4 one_splat = int4(1);
|
||||
const int4 one_compound = int4(1, 1, 1, 1);
|
||||
|
||||
bool ok = true;
|
||||
ok = ok && (int4(-1) == -one_splat);
|
||||
ok = ok && (int4(-1, -1, -1, -1) == -one_splat);
|
||||
ok = ok && (int4(-1) == -one_compound);
|
||||
ok = ok && (int4(-1, -1, -1, -1) == -one_compound);
|
||||
ok = ok && (-int4(1) == -one_splat);
|
||||
ok = ok && (-int4(1, 1, 1, 1) == -one_splat);
|
||||
ok = ok && (-int4(1) == -one_compound);
|
||||
ok = ok && (-int4(1, 1, 1, 1) == -one_compound);
|
||||
ok = ok && (int4(-1) == -int4(-int2(-1), int2(1)));
|
||||
ok = ok && (int4(1) != -int4(1));
|
||||
ok = ok && (-int4(two) == int4(-two, int3(-two)));
|
||||
ok = ok && (-int2(-one, one + one) == -int2(one - two, two));
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool test_mat() {
|
||||
const float3x3 one_diagonal = float3x3(1);
|
||||
const float3x3 one_compound = float3x3(1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1);
|
||||
bool ok = true;
|
||||
ok = ok && (float3x3(-1) == -one_diagonal);
|
||||
ok = ok && (float3x3(-1, 0, 0, 0, -1, 0, 0, 0, -1) == -one_diagonal);
|
||||
ok = ok && (float3x3(-1) == -one_compound);
|
||||
ok = ok && (float3x3(-1, 0, 0, 0, -1, 0, 0, 0, -1) == -one_compound);
|
||||
ok = ok && (-float3x3(1) == -one_diagonal);
|
||||
ok = ok && (-float3x3(1, 0, 0, 0, 1, 0, 0, 0, 1) == -one_diagonal);
|
||||
ok = ok && (-float3x3(1) == -one_compound);
|
||||
ok = ok && (-float3x3(1, 0, 0, 0, 1, 0, 0, 0, 1) == -one_compound);
|
||||
return ok;
|
||||
}
|
||||
|
||||
half4 main(float2 coords) {
|
||||
return test_fvec() && test_ivec() && test_mat() ? colorGreen : colorRed;
|
||||
}
|
@ -19,30 +19,30 @@
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
static ExpressionArray negate_operands(const Context& context, ExpressionArray operands);
|
||||
static ExpressionArray negate_operands(const Context& context, const ExpressionArray& operands);
|
||||
|
||||
static std::unique_ptr<Expression> negate_operand(const Context& context,
|
||||
std::unique_ptr<Expression> operand) {
|
||||
const Expression* value = ConstantFolder::GetConstantValueForVariable(*operand);
|
||||
static std::unique_ptr<Expression> simplify_negation(const Context& context,
|
||||
const Expression& originalExpr) {
|
||||
const Expression* value = ConstantFolder::GetConstantValueForVariable(originalExpr);
|
||||
switch (value->kind()) {
|
||||
case Expression::Kind::kFloatLiteral:
|
||||
// Convert -floatLiteral(1) to floatLiteral(-1).
|
||||
return FloatLiteral::Make(operand->fOffset,
|
||||
return FloatLiteral::Make(originalExpr.fOffset,
|
||||
-value->as<FloatLiteral>().value(),
|
||||
&value->type());
|
||||
|
||||
case Expression::Kind::kIntLiteral:
|
||||
// Convert -intLiteral(1) to intLiteral(-1).
|
||||
return IntLiteral::Make(operand->fOffset,
|
||||
return IntLiteral::Make(originalExpr.fOffset,
|
||||
-value->as<IntLiteral>().value(),
|
||||
&value->type());
|
||||
|
||||
case Expression::Kind::kPrefix:
|
||||
if (context.fConfig->fSettings.fOptimize) {
|
||||
// Convert `-(-expression)` into `expression`.
|
||||
PrefixExpression& prefix = operand->as<PrefixExpression>();
|
||||
const PrefixExpression& prefix = value->as<PrefixExpression>();
|
||||
if (prefix.getOperator().kind() == Token::Kind::TK_MINUS) {
|
||||
return std::move(prefix.operand());
|
||||
return prefix.operand()->clone();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -50,55 +50,69 @@ static std::unique_ptr<Expression> negate_operand(const Context& context,
|
||||
case Expression::Kind::kConstructorArray:
|
||||
// Convert `-array[N](literal, ...)` into `array[N](-literal, ...)`.
|
||||
if (context.fConfig->fSettings.fOptimize && value->isCompileTimeConstant()) {
|
||||
ConstructorArray& ctor = operand->as<ConstructorArray>();
|
||||
return ConstructorArray::Make(
|
||||
context, ctor.fOffset, ctor.type(),
|
||||
negate_operands(context, std::move(ctor.arguments())));
|
||||
const ConstructorArray& ctor = value->as<ConstructorArray>();
|
||||
return ConstructorArray::Make(context, originalExpr.fOffset, ctor.type(),
|
||||
negate_operands(context, ctor.arguments()));
|
||||
}
|
||||
break;
|
||||
|
||||
case Expression::Kind::kConstructorDiagonalMatrix:
|
||||
// Convert `-matrix(literal)` into `matrix(-literal)`.
|
||||
if (context.fConfig->fSettings.fOptimize && value->isCompileTimeConstant()) {
|
||||
ConstructorDiagonalMatrix& ctor = operand->as<ConstructorDiagonalMatrix>();
|
||||
return ConstructorDiagonalMatrix::Make(
|
||||
context, ctor.fOffset, ctor.type(),
|
||||
negate_operand(context, std::move(ctor.argument())));
|
||||
const ConstructorDiagonalMatrix& ctor = value->as<ConstructorDiagonalMatrix>();
|
||||
return ConstructorDiagonalMatrix::Make(context, originalExpr.fOffset, ctor.type(),
|
||||
simplify_negation(context, *ctor.argument()));
|
||||
}
|
||||
break;
|
||||
|
||||
case Expression::Kind::kConstructorSplat:
|
||||
// Convert `-vector(literal)` into `vector(-literal)`.
|
||||
if (context.fConfig->fSettings.fOptimize && value->isCompileTimeConstant()) {
|
||||
ConstructorSplat& ctor = operand->as<ConstructorSplat>();
|
||||
return ConstructorSplat::Make(context, ctor.fOffset, ctor.type(),
|
||||
negate_operand(context, std::move(ctor.argument())));
|
||||
const ConstructorSplat& ctor = value->as<ConstructorSplat>();
|
||||
return ConstructorSplat::Make(context, originalExpr.fOffset, ctor.type(),
|
||||
simplify_negation(context, *ctor.argument()));
|
||||
}
|
||||
break;
|
||||
|
||||
case Expression::Kind::kConstructorCompound:
|
||||
// Convert `-vecN(literal, ...)` into `vecN(-literal, ...)`.
|
||||
if (context.fConfig->fSettings.fOptimize && value->isCompileTimeConstant()) {
|
||||
ConstructorCompound& ctor = operand->as<ConstructorCompound>();
|
||||
return ConstructorCompound::Make(
|
||||
context, ctor.fOffset, ctor.type(),
|
||||
negate_operands(context, std::move(ctor.arguments())));
|
||||
const ConstructorCompound& ctor = value->as<ConstructorCompound>();
|
||||
return ConstructorCompound::Make(context, originalExpr.fOffset, ctor.type(),
|
||||
negate_operands(context, ctor.arguments()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// No simplified form; convert expression to Prefix(TK_MINUS, expression).
|
||||
return std::make_unique<PrefixExpression>(Token::Kind::TK_MINUS, std::move(operand));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static ExpressionArray negate_operands(const Context& context, ExpressionArray operands) {
|
||||
for (std::unique_ptr<Expression>& arg : operands) {
|
||||
arg = negate_operand(context, std::move(arg));
|
||||
static ExpressionArray negate_operands(const Context& context, const ExpressionArray& array) {
|
||||
ExpressionArray replacement;
|
||||
replacement.reserve_back(array.size());
|
||||
for (const std::unique_ptr<Expression>& expr : array) {
|
||||
// The logic below is very similar to `negate_operand`, but with different ownership rules.
|
||||
if (std::unique_ptr<Expression> simplified = simplify_negation(context, *expr)) {
|
||||
replacement.push_back(std::move(simplified));
|
||||
} else {
|
||||
replacement.push_back(std::make_unique<PrefixExpression>(Token::Kind::TK_MINUS,
|
||||
expr->clone()));
|
||||
}
|
||||
}
|
||||
return operands;
|
||||
return replacement;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Expression> negate_operand(const Context& context,
|
||||
std::unique_ptr<Expression> value) {
|
||||
// Attempt to simplify this negation (e.g. eliminate double negation, literal values)
|
||||
if (std::unique_ptr<Expression> simplified = simplify_negation(context, *value)) {
|
||||
return simplified;
|
||||
}
|
||||
|
||||
// No simplified form; convert expression to Prefix(TK_MINUS, expression).
|
||||
return std::make_unique<PrefixExpression>(Token::Kind::TK_MINUS, std::move(value));
|
||||
}
|
||||
|
||||
static std::unique_ptr<Expression> logical_not_operand(const Context& context,
|
||||
|
@ -267,7 +267,7 @@ SKSL_TEST(SkSLMatrixEquality, "shared/MatrixEquality.sksl")
|
||||
SKSL_TEST(SkSLMatrixScalarSplat, "shared/MatrixScalarSplat.sksl")
|
||||
SKSL_TEST(SkSLMatrixToVectorCast, "shared/MatrixToVectorCast.sksl")
|
||||
SKSL_TEST(SkSLMultipleAssignments, "shared/MultipleAssignments.sksl")
|
||||
SKSL_TEST(SkSLNegatedVectorLiteral, "shared/NegatedVectorLiteral.sksl")
|
||||
SKSL_TEST(SkSLNegation, "shared/Negation.sksl")
|
||||
SKSL_TEST(SkSLNumberCasts, "shared/NumberCasts.sksl")
|
||||
SKSL_TEST(SkSLOperatorsES2, "shared/OperatorsES2.sksl")
|
||||
SKSL_TEST_ES3(SkSLOperatorsES3, "shared/OperatorsES3.sksl")
|
||||
|
@ -1,211 +0,0 @@
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
|
||||
OpExecutionMode %_entrypoint_v OriginUpperLeft
|
||||
OpName %sk_FragColor "sk_FragColor"
|
||||
OpName %sk_Clockwise "sk_Clockwise"
|
||||
OpName %_UniformBuffer "_UniformBuffer"
|
||||
OpMemberName %_UniformBuffer 0 "colorGreen"
|
||||
OpMemberName %_UniformBuffer 1 "colorRed"
|
||||
OpName %_entrypoint_v "_entrypoint_v"
|
||||
OpName %test_int_b "test_int_b"
|
||||
OpName %one "one"
|
||||
OpName %two "two"
|
||||
OpName %result "result"
|
||||
OpName %main "main"
|
||||
OpName %_0_one "_0_one"
|
||||
OpName %_1_two "_1_two"
|
||||
OpName %_2_result "_2_result"
|
||||
OpDecorate %sk_FragColor RelaxedPrecision
|
||||
OpDecorate %sk_FragColor Location 0
|
||||
OpDecorate %sk_FragColor Index 0
|
||||
OpDecorate %sk_Clockwise BuiltIn FrontFacing
|
||||
OpMemberDecorate %_UniformBuffer 0 Offset 0
|
||||
OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
|
||||
OpMemberDecorate %_UniformBuffer 1 Offset 16
|
||||
OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
|
||||
OpDecorate %_UniformBuffer Block
|
||||
OpDecorate %11 Binding 0
|
||||
OpDecorate %11 DescriptorSet 0
|
||||
OpDecorate %82 RelaxedPrecision
|
||||
OpDecorate %84 RelaxedPrecision
|
||||
OpDecorate %89 RelaxedPrecision
|
||||
OpDecorate %91 RelaxedPrecision
|
||||
OpDecorate %92 RelaxedPrecision
|
||||
OpDecorate %93 RelaxedPrecision
|
||||
OpDecorate %94 RelaxedPrecision
|
||||
OpDecorate %102 RelaxedPrecision
|
||||
OpDecorate %103 RelaxedPrecision
|
||||
OpDecorate %108 RelaxedPrecision
|
||||
OpDecorate %137 RelaxedPrecision
|
||||
OpDecorate %139 RelaxedPrecision
|
||||
OpDecorate %140 RelaxedPrecision
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%sk_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%_UniformBuffer = OpTypeStruct %v4float %v4float
|
||||
%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
|
||||
%11 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
|
||||
%void = OpTypeVoid
|
||||
%16 = OpTypeFunction %void
|
||||
%v2float = OpTypeVector %float 2
|
||||
%float_0 = OpConstant %float 0
|
||||
%20 = OpConstantComposite %v2float %float_0 %float_0
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%24 = OpTypeFunction %bool
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_2 = OpConstant %int 2
|
||||
%v4int = OpTypeVector %int 4
|
||||
%_ptr_Function_v4int = OpTypePointer Function %v4int
|
||||
%int_0 = OpConstant %int 0
|
||||
%v2int = OpTypeVector %int 2
|
||||
%v2bool = OpTypeVector %bool 2
|
||||
%int_3 = OpConstant %int 3
|
||||
%70 = OpTypeFunction %v4float %_ptr_Function_v2float
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%float_1 = OpConstant %float 1
|
||||
%float_2 = OpConstant %float 2
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%v3float = OpTypeVector %float 3
|
||||
%v4bool = OpTypeVector %bool 4
|
||||
%float_n2 = OpConstant %float -2
|
||||
%102 = OpConstantComposite %v2float %float_1 %float_n2
|
||||
%false = OpConstantFalse %bool
|
||||
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
|
||||
%_entrypoint_v = OpFunction %void None %16
|
||||
%17 = OpLabel
|
||||
%21 = OpVariable %_ptr_Function_v2float Function
|
||||
OpStore %21 %20
|
||||
%23 = OpFunctionCall %v4float %main %21
|
||||
OpStore %sk_FragColor %23
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%test_int_b = OpFunction %bool None %24
|
||||
%25 = OpLabel
|
||||
%one = OpVariable %_ptr_Function_int Function
|
||||
%two = OpVariable %_ptr_Function_int Function
|
||||
%result = OpVariable %_ptr_Function_v4int Function
|
||||
OpStore %one %int_1
|
||||
OpStore %two %int_2
|
||||
%35 = OpAccessChain %_ptr_Function_int %result %int_0
|
||||
OpStore %35 %int_1
|
||||
%37 = OpAccessChain %_ptr_Function_int %result %int_1
|
||||
OpStore %37 %int_1
|
||||
%38 = OpAccessChain %_ptr_Function_int %result %int_2
|
||||
OpStore %38 %int_1
|
||||
%42 = OpLoad %int %one
|
||||
%41 = OpSNegate %int %42
|
||||
%43 = OpLoad %int %one
|
||||
%44 = OpLoad %int %one
|
||||
%45 = OpIAdd %int %43 %44
|
||||
%46 = OpCompositeConstruct %v2int %41 %45
|
||||
%39 = OpSNegate %v2int %46
|
||||
%48 = OpLoad %int %one
|
||||
%49 = OpLoad %int %two
|
||||
%50 = OpISub %int %48 %49
|
||||
%51 = OpCompositeConstruct %v2int %50 %int_2
|
||||
%47 = OpSNegate %v2int %51
|
||||
%52 = OpIEqual %v2bool %39 %47
|
||||
%54 = OpAll %bool %52
|
||||
%55 = OpSelect %int %54 %int_1 %int_0
|
||||
%56 = OpAccessChain %_ptr_Function_int %result %int_3
|
||||
OpStore %56 %55
|
||||
%58 = OpLoad %v4int %result
|
||||
%59 = OpCompositeExtract %int %58 0
|
||||
%60 = OpLoad %v4int %result
|
||||
%61 = OpCompositeExtract %int %60 1
|
||||
%62 = OpIMul %int %59 %61
|
||||
%63 = OpLoad %v4int %result
|
||||
%64 = OpCompositeExtract %int %63 2
|
||||
%65 = OpIMul %int %62 %64
|
||||
%66 = OpLoad %v4int %result
|
||||
%67 = OpCompositeExtract %int %66 3
|
||||
%68 = OpIMul %int %65 %67
|
||||
%69 = OpINotEqual %bool %68 %int_0
|
||||
OpReturnValue %69
|
||||
OpFunctionEnd
|
||||
%main = OpFunction %v4float None %70
|
||||
%71 = OpFunctionParameter %_ptr_Function_v2float
|
||||
%72 = OpLabel
|
||||
%_0_one = OpVariable %_ptr_Function_float Function
|
||||
%_1_two = OpVariable %_ptr_Function_float Function
|
||||
%_2_result = OpVariable %_ptr_Function_v4float Function
|
||||
%131 = OpVariable %_ptr_Function_v4float Function
|
||||
OpStore %_0_one %float_1
|
||||
OpStore %_1_two %float_2
|
||||
%80 = OpAccessChain %_ptr_Function_float %_2_result %int_0
|
||||
OpStore %80 %float_1
|
||||
%81 = OpAccessChain %_ptr_Function_float %_2_result %int_1
|
||||
OpStore %81 %float_1
|
||||
%83 = OpLoad %float %_1_two
|
||||
%84 = OpCompositeConstruct %v4float %83 %83 %83 %83
|
||||
%82 = OpFNegate %v4float %84
|
||||
%86 = OpLoad %float %_1_two
|
||||
%85 = OpFNegate %float %86
|
||||
%88 = OpLoad %float %_1_two
|
||||
%87 = OpFNegate %float %88
|
||||
%89 = OpCompositeConstruct %v3float %87 %87 %87
|
||||
%91 = OpCompositeExtract %float %89 0
|
||||
%92 = OpCompositeExtract %float %89 1
|
||||
%93 = OpCompositeExtract %float %89 2
|
||||
%94 = OpCompositeConstruct %v4float %85 %91 %92 %93
|
||||
%95 = OpFOrdEqual %v4bool %82 %94
|
||||
%97 = OpAll %bool %95
|
||||
%98 = OpSelect %int %97 %int_1 %int_0
|
||||
%99 = OpConvertSToF %float %98
|
||||
%100 = OpAccessChain %_ptr_Function_float %_2_result %int_2
|
||||
OpStore %100 %99
|
||||
%104 = OpLoad %float %_0_one
|
||||
%105 = OpLoad %float %_1_two
|
||||
%106 = OpFSub %float %104 %105
|
||||
%107 = OpLoad %float %_1_two
|
||||
%108 = OpCompositeConstruct %v2float %106 %107
|
||||
%103 = OpFNegate %v2float %108
|
||||
%109 = OpFOrdEqual %v2bool %102 %103
|
||||
%110 = OpAll %bool %109
|
||||
%111 = OpSelect %int %110 %int_1 %int_0
|
||||
%112 = OpConvertSToF %float %111
|
||||
%113 = OpAccessChain %_ptr_Function_float %_2_result %int_3
|
||||
OpStore %113 %112
|
||||
%115 = OpLoad %v4float %_2_result
|
||||
%116 = OpCompositeExtract %float %115 0
|
||||
%117 = OpLoad %v4float %_2_result
|
||||
%118 = OpCompositeExtract %float %117 1
|
||||
%119 = OpFMul %float %116 %118
|
||||
%120 = OpLoad %v4float %_2_result
|
||||
%121 = OpCompositeExtract %float %120 2
|
||||
%122 = OpFMul %float %119 %121
|
||||
%123 = OpLoad %v4float %_2_result
|
||||
%124 = OpCompositeExtract %float %123 3
|
||||
%125 = OpFMul %float %122 %124
|
||||
%126 = OpFUnordNotEqual %bool %125 %float_0
|
||||
OpSelectionMerge %128 None
|
||||
OpBranchConditional %126 %127 %128
|
||||
%127 = OpLabel
|
||||
%129 = OpFunctionCall %bool %test_int_b
|
||||
OpBranch %128
|
||||
%128 = OpLabel
|
||||
%130 = OpPhi %bool %false %72 %129 %127
|
||||
OpSelectionMerge %134 None
|
||||
OpBranchConditional %130 %132 %133
|
||||
%132 = OpLabel
|
||||
%135 = OpAccessChain %_ptr_Uniform_v4float %11 %int_0
|
||||
%137 = OpLoad %v4float %135
|
||||
OpStore %131 %137
|
||||
OpBranch %134
|
||||
%133 = OpLabel
|
||||
%138 = OpAccessChain %_ptr_Uniform_v4float %11 %int_1
|
||||
%139 = OpLoad %v4float %138
|
||||
OpStore %131 %139
|
||||
OpBranch %134
|
||||
%134 = OpLabel
|
||||
%140 = OpLoad %v4float %131
|
||||
OpReturnValue %140
|
||||
OpFunctionEnd
|
@ -1,24 +0,0 @@
|
||||
|
||||
out vec4 sk_FragColor;
|
||||
uniform vec4 colorGreen;
|
||||
uniform vec4 colorRed;
|
||||
bool test_int_b() {
|
||||
int one = 1;
|
||||
const int two = 2;
|
||||
ivec4 result;
|
||||
result.x = 1;
|
||||
result.y = 1;
|
||||
result.z = 1;
|
||||
result.w = int(-ivec2(-one, one + one) == -ivec2(one - two, 2) ? 1 : 0);
|
||||
return bool(((result.x * result.y) * result.z) * result.w);
|
||||
}
|
||||
vec4 main() {
|
||||
const float _0_one = 1.0;
|
||||
float _1_two = 2.0;
|
||||
vec4 _2_result;
|
||||
_2_result.x = 1.0;
|
||||
_2_result.y = 1.0;
|
||||
_2_result.z = float(-vec4(_1_two) == vec4(-_1_two, vec3(-_1_two)) ? 1 : 0);
|
||||
_2_result.w = float(vec2(1.0, -2.0) == -vec2(_0_one - _1_two, _1_two) ? 1 : 0);
|
||||
return bool(((_2_result.x * _2_result.y) * _2_result.z) * _2_result.w) && test_int_b() ? colorGreen : colorRed;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
struct Uniforms {
|
||||
float4 colorGreen;
|
||||
float4 colorRed;
|
||||
};
|
||||
struct Inputs {
|
||||
};
|
||||
struct Outputs {
|
||||
float4 sk_FragColor [[color(0)]];
|
||||
};
|
||||
bool test_int_b() {
|
||||
int one = 1;
|
||||
const int two = 2;
|
||||
int4 result;
|
||||
result.x = 1;
|
||||
result.y = 1;
|
||||
result.z = 1;
|
||||
result.w = int(all(-int2(-one, one + one) == -int2(one - two, 2)) ? 1 : 0);
|
||||
return bool(((result.x * result.y) * result.z) * result.w);
|
||||
}
|
||||
fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
|
||||
Outputs _out;
|
||||
(void)_out;
|
||||
const float _0_one = 1.0;
|
||||
float _1_two = 2.0;
|
||||
float4 _2_result;
|
||||
_2_result.x = 1.0;
|
||||
_2_result.y = 1.0;
|
||||
_2_result.z = float(all(-float4(_1_two) == float4(-_1_two, float3(-_1_two))) ? 1 : 0);
|
||||
_2_result.w = float(all(float2(1.0, -2.0) == -float2(_0_one - _1_two, _1_two)) ? 1 : 0);
|
||||
_out.sk_FragColor = bool(((_2_result.x * _2_result.y) * _2_result.z) * _2_result.w) && test_int_b() ? _uniforms.colorGreen : _uniforms.colorRed;
|
||||
return _out;
|
||||
}
|
215
tests/sksl/shared/Negation.asm.frag
Normal file
215
tests/sksl/shared/Negation.asm.frag
Normal file
@ -0,0 +1,215 @@
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %_entrypoint_v "_entrypoint" %sk_FragColor %sk_Clockwise
|
||||
OpExecutionMode %_entrypoint_v OriginUpperLeft
|
||||
OpName %sk_FragColor "sk_FragColor"
|
||||
OpName %sk_Clockwise "sk_Clockwise"
|
||||
OpName %_UniformBuffer "_UniformBuffer"
|
||||
OpMemberName %_UniformBuffer 0 "colorGreen"
|
||||
OpMemberName %_UniformBuffer 1 "colorRed"
|
||||
OpName %_entrypoint_v "_entrypoint_v"
|
||||
OpName %test_ivec_b "test_ivec_b"
|
||||
OpName %one "one"
|
||||
OpName %two "two"
|
||||
OpName %ok "ok"
|
||||
OpName %test_mat_b "test_mat_b"
|
||||
OpName %ok_0 "ok"
|
||||
OpName %main "main"
|
||||
OpName %_0_one "_0_one"
|
||||
OpName %_1_two "_1_two"
|
||||
OpName %_4_ok "_4_ok"
|
||||
OpDecorate %sk_FragColor RelaxedPrecision
|
||||
OpDecorate %sk_FragColor Location 0
|
||||
OpDecorate %sk_FragColor Index 0
|
||||
OpDecorate %sk_Clockwise BuiltIn FrontFacing
|
||||
OpMemberDecorate %_UniformBuffer 0 Offset 0
|
||||
OpMemberDecorate %_UniformBuffer 0 RelaxedPrecision
|
||||
OpMemberDecorate %_UniformBuffer 1 Offset 16
|
||||
OpMemberDecorate %_UniformBuffer 1 RelaxedPrecision
|
||||
OpDecorate %_UniformBuffer Block
|
||||
OpDecorate %12 Binding 0
|
||||
OpDecorate %12 DescriptorSet 0
|
||||
OpDecorate %37 RelaxedPrecision
|
||||
OpDecorate %57 RelaxedPrecision
|
||||
OpDecorate %60 RelaxedPrecision
|
||||
OpDecorate %70 RelaxedPrecision
|
||||
OpDecorate %73 RelaxedPrecision
|
||||
OpDecorate %75 RelaxedPrecision
|
||||
OpDecorate %80 RelaxedPrecision
|
||||
OpDecorate %82 RelaxedPrecision
|
||||
OpDecorate %83 RelaxedPrecision
|
||||
OpDecorate %84 RelaxedPrecision
|
||||
OpDecorate %85 RelaxedPrecision
|
||||
OpDecorate %90 RelaxedPrecision
|
||||
OpDecorate %94 RelaxedPrecision
|
||||
OpDecorate %95 RelaxedPrecision
|
||||
OpDecorate %100 RelaxedPrecision
|
||||
OpDecorate %104 RelaxedPrecision
|
||||
OpDecorate %121 RelaxedPrecision
|
||||
OpDecorate %123 RelaxedPrecision
|
||||
OpDecorate %124 RelaxedPrecision
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%sk_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
%bool = OpTypeBool
|
||||
%_ptr_Input_bool = OpTypePointer Input %bool
|
||||
%sk_Clockwise = OpVariable %_ptr_Input_bool Input
|
||||
%_UniformBuffer = OpTypeStruct %v4float %v4float
|
||||
%_ptr_Uniform__UniformBuffer = OpTypePointer Uniform %_UniformBuffer
|
||||
%12 = OpVariable %_ptr_Uniform__UniformBuffer Uniform
|
||||
%void = OpTypeVoid
|
||||
%17 = OpTypeFunction %void
|
||||
%v2float = OpTypeVector %float 2
|
||||
%float_0 = OpConstant %float 0
|
||||
%21 = OpConstantComposite %v2float %float_0 %float_0
|
||||
%_ptr_Function_v2float = OpTypePointer Function %v2float
|
||||
%25 = OpTypeFunction %bool
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Function_int = OpTypePointer Function %int
|
||||
%int_1 = OpConstant %int 1
|
||||
%int_2 = OpConstant %int 2
|
||||
%_ptr_Function_bool = OpTypePointer Function %bool
|
||||
%true = OpConstantTrue %bool
|
||||
%false = OpConstantFalse %bool
|
||||
%v2int = OpTypeVector %int 2
|
||||
%v2bool = OpTypeVector %bool 2
|
||||
%61 = OpTypeFunction %v4float %_ptr_Function_v2float
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%float_1 = OpConstant %float 1
|
||||
%float_2 = OpConstant %float 2
|
||||
%v3float = OpTypeVector %float 3
|
||||
%v4bool = OpTypeVector %bool 4
|
||||
%float_n2 = OpConstant %float -2
|
||||
%94 = OpConstantComposite %v2float %float_1 %float_n2
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float
|
||||
%int_0 = OpConstant %int 0
|
||||
%_entrypoint_v = OpFunction %void None %17
|
||||
%18 = OpLabel
|
||||
%22 = OpVariable %_ptr_Function_v2float Function
|
||||
OpStore %22 %21
|
||||
%24 = OpFunctionCall %v4float %main %22
|
||||
OpStore %sk_FragColor %24
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
%test_ivec_b = OpFunction %bool None %25
|
||||
%26 = OpLabel
|
||||
%one = OpVariable %_ptr_Function_int Function
|
||||
%two = OpVariable %_ptr_Function_int Function
|
||||
%ok = OpVariable %_ptr_Function_bool Function
|
||||
OpStore %one %int_1
|
||||
OpStore %two %int_2
|
||||
OpStore %ok %true
|
||||
%37 = OpLoad %bool %ok
|
||||
OpSelectionMerge %39 None
|
||||
OpBranchConditional %37 %38 %39
|
||||
%38 = OpLabel
|
||||
%43 = OpLoad %int %one
|
||||
%42 = OpSNegate %int %43
|
||||
%44 = OpLoad %int %one
|
||||
%45 = OpLoad %int %one
|
||||
%46 = OpIAdd %int %44 %45
|
||||
%47 = OpCompositeConstruct %v2int %42 %46
|
||||
%40 = OpSNegate %v2int %47
|
||||
%49 = OpLoad %int %one
|
||||
%50 = OpLoad %int %two
|
||||
%51 = OpISub %int %49 %50
|
||||
%52 = OpCompositeConstruct %v2int %51 %int_2
|
||||
%48 = OpSNegate %v2int %52
|
||||
%53 = OpIEqual %v2bool %40 %48
|
||||
%55 = OpAll %bool %53
|
||||
OpBranch %39
|
||||
%39 = OpLabel
|
||||
%56 = OpPhi %bool %false %26 %55 %38
|
||||
OpStore %ok %56
|
||||
%57 = OpLoad %bool %ok
|
||||
OpReturnValue %57
|
||||
OpFunctionEnd
|
||||
%test_mat_b = OpFunction %bool None %25
|
||||
%58 = OpLabel
|
||||
%ok_0 = OpVariable %_ptr_Function_bool Function
|
||||
OpStore %ok_0 %true
|
||||
%60 = OpLoad %bool %ok_0
|
||||
OpReturnValue %60
|
||||
OpFunctionEnd
|
||||
%main = OpFunction %v4float None %61
|
||||
%62 = OpFunctionParameter %_ptr_Function_v2float
|
||||
%63 = OpLabel
|
||||
%_0_one = OpVariable %_ptr_Function_float Function
|
||||
%_1_two = OpVariable %_ptr_Function_float Function
|
||||
%_4_ok = OpVariable %_ptr_Function_bool Function
|
||||
%113 = OpVariable %_ptr_Function_v4float Function
|
||||
OpStore %_0_one %float_1
|
||||
OpStore %_1_two %float_2
|
||||
OpStore %_4_ok %true
|
||||
%70 = OpLoad %bool %_4_ok
|
||||
OpSelectionMerge %72 None
|
||||
OpBranchConditional %70 %71 %72
|
||||
%71 = OpLabel
|
||||
%74 = OpLoad %float %_1_two
|
||||
%75 = OpCompositeConstruct %v4float %74 %74 %74 %74
|
||||
%73 = OpFNegate %v4float %75
|
||||
%77 = OpLoad %float %_1_two
|
||||
%76 = OpFNegate %float %77
|
||||
%79 = OpLoad %float %_1_two
|
||||
%78 = OpFNegate %float %79
|
||||
%80 = OpCompositeConstruct %v3float %78 %78 %78
|
||||
%82 = OpCompositeExtract %float %80 0
|
||||
%83 = OpCompositeExtract %float %80 1
|
||||
%84 = OpCompositeExtract %float %80 2
|
||||
%85 = OpCompositeConstruct %v4float %76 %82 %83 %84
|
||||
%86 = OpFOrdEqual %v4bool %73 %85
|
||||
%88 = OpAll %bool %86
|
||||
OpBranch %72
|
||||
%72 = OpLabel
|
||||
%89 = OpPhi %bool %false %63 %88 %71
|
||||
OpStore %_4_ok %89
|
||||
%90 = OpLoad %bool %_4_ok
|
||||
OpSelectionMerge %92 None
|
||||
OpBranchConditional %90 %91 %92
|
||||
%91 = OpLabel
|
||||
%96 = OpLoad %float %_0_one
|
||||
%97 = OpLoad %float %_1_two
|
||||
%98 = OpFSub %float %96 %97
|
||||
%99 = OpLoad %float %_1_two
|
||||
%100 = OpCompositeConstruct %v2float %98 %99
|
||||
%95 = OpFNegate %v2float %100
|
||||
%101 = OpFOrdEqual %v2bool %94 %95
|
||||
%102 = OpAll %bool %101
|
||||
OpBranch %92
|
||||
%92 = OpLabel
|
||||
%103 = OpPhi %bool %false %72 %102 %91
|
||||
OpStore %_4_ok %103
|
||||
%104 = OpLoad %bool %_4_ok
|
||||
OpSelectionMerge %106 None
|
||||
OpBranchConditional %104 %105 %106
|
||||
%105 = OpLabel
|
||||
%107 = OpFunctionCall %bool %test_ivec_b
|
||||
OpBranch %106
|
||||
%106 = OpLabel
|
||||
%108 = OpPhi %bool %false %92 %107 %105
|
||||
OpSelectionMerge %110 None
|
||||
OpBranchConditional %108 %109 %110
|
||||
%109 = OpLabel
|
||||
%111 = OpFunctionCall %bool %test_mat_b
|
||||
OpBranch %110
|
||||
%110 = OpLabel
|
||||
%112 = OpPhi %bool %false %106 %111 %109
|
||||
OpSelectionMerge %117 None
|
||||
OpBranchConditional %112 %115 %116
|
||||
%115 = OpLabel
|
||||
%118 = OpAccessChain %_ptr_Uniform_v4float %12 %int_0
|
||||
%121 = OpLoad %v4float %118
|
||||
OpStore %113 %121
|
||||
OpBranch %117
|
||||
%116 = OpLabel
|
||||
%122 = OpAccessChain %_ptr_Uniform_v4float %12 %int_1
|
||||
%123 = OpLoad %v4float %122
|
||||
OpStore %113 %123
|
||||
OpBranch %117
|
||||
%117 = OpLabel
|
||||
%124 = OpLoad %v4float %113
|
||||
OpReturnValue %124
|
||||
OpFunctionEnd
|
23
tests/sksl/shared/Negation.glsl
Normal file
23
tests/sksl/shared/Negation.glsl
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
out vec4 sk_FragColor;
|
||||
uniform vec4 colorGreen;
|
||||
uniform vec4 colorRed;
|
||||
bool test_ivec_b() {
|
||||
int one = 1;
|
||||
const int two = 2;
|
||||
bool ok = true;
|
||||
ok = ok && -ivec2(-one, one + one) == -ivec2(one - two, 2);
|
||||
return ok;
|
||||
}
|
||||
bool test_mat_b() {
|
||||
bool ok = true;
|
||||
return ok;
|
||||
}
|
||||
vec4 main() {
|
||||
const float _0_one = 1.0;
|
||||
float _1_two = 2.0;
|
||||
bool _4_ok = true;
|
||||
_4_ok = _4_ok && -vec4(_1_two) == vec4(-_1_two, vec3(-_1_two));
|
||||
_4_ok = _4_ok && vec2(1.0, -2.0) == -vec2(_0_one - _1_two, _1_two);
|
||||
return (_4_ok && test_ivec_b()) && test_mat_b() ? colorGreen : colorRed;
|
||||
}
|
34
tests/sksl/shared/Negation.metal
Normal file
34
tests/sksl/shared/Negation.metal
Normal file
@ -0,0 +1,34 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
using namespace metal;
|
||||
struct Uniforms {
|
||||
float4 colorGreen;
|
||||
float4 colorRed;
|
||||
};
|
||||
struct Inputs {
|
||||
};
|
||||
struct Outputs {
|
||||
float4 sk_FragColor [[color(0)]];
|
||||
};
|
||||
bool test_ivec_b() {
|
||||
int one = 1;
|
||||
const int two = 2;
|
||||
bool ok = true;
|
||||
ok = ok && all(-int2(-one, one + one) == -int2(one - two, 2));
|
||||
return ok;
|
||||
}
|
||||
bool test_mat_b() {
|
||||
bool ok = true;
|
||||
return ok;
|
||||
}
|
||||
fragment Outputs fragmentMain(Inputs _in [[stage_in]], constant Uniforms& _uniforms [[buffer(0)]], bool _frontFacing [[front_facing]], float4 _fragCoord [[position]]) {
|
||||
Outputs _out;
|
||||
(void)_out;
|
||||
const float _0_one = 1.0;
|
||||
float _1_two = 2.0;
|
||||
bool _4_ok = true;
|
||||
_4_ok = _4_ok && all(-float4(_1_two) == float4(-_1_two, float3(-_1_two)));
|
||||
_4_ok = _4_ok && all(float2(1.0, -2.0) == -float2(_0_one - _1_two, _1_two));
|
||||
_out.sk_FragColor = (_4_ok && test_ivec_b()) && test_mat_b() ? _uniforms.colorGreen : _uniforms.colorRed;
|
||||
return _out;
|
||||
}
|
Loading…
Reference in New Issue
Block a user