Replace salting process in SkSLInliner with a symbol table check.
Ideally, we wouldn't need a counter at all here, and we could just rely
on the symbol table to check for name collisions. Unfortunately, this
fails in practice on a couple of tests, because we don't construct
programs in a strict top-to-bottom order--particularly when inlining.
However, by checking the symbol table before using a name, we can at
least solve cases where the inliner reuses a name that was taken in a
previous pass, which was why salt was originally added. This makes the
generated code much easier to read.
Change-Id: Ib69611c8df457fbd03b31e52158113ad4a8735d5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314277
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
index e85e7dd..95184f3 100644
--- a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
@@ -43,12 +43,12 @@
fragBuilder->codeAppendf(
R"SkSL(half4 inputColor = %s;
@if (%s) {
- half4 _inlineResulthalf4unpremulhalf40;
+ half4 _0_unpremul;
{
- _inlineResulthalf4unpremulhalf40 = half4(inputColor.xyz / max(inputColor.w, 9.9999997473787516e-05), inputColor.w);
+ _0_unpremul = half4(inputColor.xyz / max(inputColor.w, 9.9999997473787516e-05), inputColor.w);
}
- inputColor = _inlineResulthalf4unpremulhalf40;
+ inputColor = _0_unpremul;
}
%s = %s * inputColor + %s;
diff --git a/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp b/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp
index 8561e51..a9564d2 100644
--- a/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp
+++ b/src/gpu/effects/generated/GrHighContrastFilterEffect.cpp
@@ -52,12 +52,12 @@
fragBuilder->codeAppendf(
R"SkSL(
half4 inColor = %s;
-half4 _inlineResulthalf4unpremulhalf40;
+half4 _0_unpremul;
{
- _inlineResulthalf4unpremulhalf40 = half4(inColor.xyz / max(inColor.w, 9.9999997473787516e-05), inColor.w);
+ _0_unpremul = half4(inColor.xyz / max(inColor.w, 9.9999997473787516e-05), inColor.w);
}
-half4 color = _inlineResulthalf4unpremulhalf40;
+half4 color = _0_unpremul;
@if (%s) {
color.xyz = color.xyz * color.xyz;
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index eb9e02e..736cb56 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -436,24 +436,29 @@
InlinedCall inlinedCall;
std::vector<std::unique_ptr<Statement>> inlinedBody;
- // Use unique variable names based on the function signature. Otherwise there are situations in
- // which an inlined function is later inlined into another function, and we end up with
- // duplicate names like 'inlineResult0' because the counter was reset. (skbug.com/10526)
- String raw = function.fDeclaration.description();
- String inlineSalt;
- for (size_t i = 0; i < raw.length(); ++i) {
- char c = raw[i];
- if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
- c == '_') {
- inlineSalt += c;
- }
- }
-
- auto makeInlineVar = [&](const String& name, const Type& type, Modifiers modifiers,
+ auto makeInlineVar = [&](const String& baseName, const Type& type, Modifiers modifiers,
std::unique_ptr<Expression>* initialValue) -> const Variable* {
+ // If the base name starts with an underscore, like "_coords", we can't append another
+ // underscore, because some OpenGL platforms error out when they see two consecutive
+ // underscores (anywhere in the string!). But in the general case, using the underscore as
+ // a splitter reads nicely enough that it's worth putting in this special case.
+ const char* splitter = baseName.startsWith("_") ? "_X" : "_";
+
+ // Append a unique numeric prefix to avoid name overlap. Check the symbol table to make sure
+ // we're not reusing an existing name. (Note that within a single compilation pass, this
+ // check isn't fully comprehensive, as code isn't always generated in top-to-bottom order.)
+ String uniqueName;
+ for (;;) {
+ uniqueName = String::printf("_%d%s%s", fInlineVarCounter++, splitter, baseName.c_str());
+ StringFragment frag{uniqueName.data(), uniqueName.length()};
+ if ((*symbolTableForCall)[frag] == nullptr) {
+ break;
+ }
+ }
+
// Add our new variable's name to the symbol table.
- const String* namePtr =
- symbolTableForCall->takeOwnershipOfString(std::make_unique<String>(name));
+ const String* namePtr = symbolTableForCall->takeOwnershipOfString(
+ std::make_unique<String>(std::move(uniqueName)));
StringFragment nameFrag{namePtr->c_str(), namePtr->length()};
// Add our new variable to the symbol table.
@@ -484,17 +489,14 @@
// Create a variable to hold the result in the extra statements (excepting void).
const Variable* resultVar = nullptr;
if (function.fDeclaration.fReturnType != *fContext->fVoid_Type) {
- int varIndex = fInlineVarCounter++;
-
std::unique_ptr<Expression> noInitialValue;
- resultVar = makeInlineVar(String::printf("_inlineResult%s%d", inlineSalt.c_str(), varIndex),
+ resultVar = makeInlineVar(String(function.fDeclaration.fName),
function.fDeclaration.fReturnType, Modifiers{}, &noInitialValue);
}
// Create variables in the extra statements to hold the arguments, and assign the arguments to
// them.
VariableRewriteMap varMap;
- int argIndex = fInlineVarCounter++;
for (int i = 0; i < (int) arguments.size(); ++i) {
const Variable* param = function.fDeclaration.fParameters[i];
@@ -508,9 +510,8 @@
}
}
- varMap[param] = makeInlineVar(
- String::printf("_inlineArg%s%d_%d", inlineSalt.c_str(), argIndex, i),
- arguments[i]->fType, param->fModifiers, &arguments[i]);
+ varMap[param] = makeInlineVar(String(param->fName), arguments[i]->fType, param->fModifiers,
+ &arguments[i]);
}
const Block& body = function.fBody->as<Block>();
diff --git a/tests/SkSLFPTest.cpp b/tests/SkSLFPTest.cpp
index 3a61104..4044fb4 100644
--- a/tests/SkSLFPTest.cpp
+++ b/tests/SkSLFPTest.cpp
@@ -821,8 +821,7 @@
}
)SkSL"
, args.fOutputColor, _sample200.c_str(), args.fOutputColor);
-)__Cpp__",
- });
+)__Cpp__"});
}
DEF_TEST(SkSLFPChildProcessorInlineFieldAccess, r) {
@@ -856,8 +855,7 @@
}
)SkSL"
, args.fOutputColor, _sample161.c_str(), args.fOutputColor);
-)__Cpp__",
- });
+)__Cpp__"});
}
DEF_TEST(SkSLFPChildProcessorFieldAccess, r) {
@@ -1045,12 +1043,12 @@
R"SkSL(return c.wzyx;
)SkSL", &flip_name);
fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4fliphalf40;
+R"SkSL(half4 _0_flip;
{
- _inlineResulthalf4fliphalf40 = %s.wzyx;
+ _0_flip = %s.wzyx;
}
-%s = _inlineResulthalf4fliphalf40;
+%s = _0_flip;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
@@ -1117,8 +1115,7 @@
R"SkSL(%s = %s(%s);
)SkSL"
, args.fOutputColor, switchy_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__",
- });
+)__Cpp__"});
}
DEF_TEST(SkSLFPSwitchWithoutReturnInsideCanBeInlined, r) {
@@ -1141,7 +1138,7 @@
/*expectedH=*/{},
/*expectedCPP=*/{
R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4switchyhalf40;
+R"SkSL(half4 _0_switchy;
{
half4 result;
switch (int(%s.x)) {
@@ -1149,15 +1146,14 @@
result = %s.yyyy;
}
result = %s.zzzz;
- _inlineResulthalf4switchyhalf40 = result;
+ _0_switchy = result;
}
-%s = _inlineResulthalf4switchyhalf40;
+%s = _0_switchy;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__",
- });
+)__Cpp__"});
}
DEF_TEST(SkSLFPForLoopWithReturnInsideCannotBeInlined, r) {
@@ -1187,8 +1183,7 @@
R"SkSL(%s = %s(%s);
)SkSL"
, args.fOutputColor, loopy_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__",
- });
+)__Cpp__"});
}
DEF_TEST(SkSLFPSwitchWithCastCanBeInlined, r) {
@@ -1210,7 +1205,7 @@
)__SkSL__",
/*expectedH=*/{},
/*expectedCPP=*/{R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4switchyhalf40;
+R"SkSL(half4 _0_switchy;
{
half4 result;
switch (int(%s.x)) {
@@ -1221,10 +1216,10 @@
result = %s.zzzz;
break;
}
- _inlineResulthalf4switchyhalf40 = result;
+ _0_switchy = result;
}
-%s = _inlineResulthalf4switchyhalf40;
+%s = _0_switchy;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
@@ -1251,22 +1246,133 @@
/*expectedH=*/{},
/*expectedCPP=*/{
R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4loopyhalf40;
+R"SkSL(half4 _0_loopy;
{
half4 pix;
for (int x = 0;x < 5; ++x) {
if (x == int(%s.w)) pix = %s.yyyy;
}
pix = %s.zzzz;
- _inlineResulthalf4loopyhalf40 = pix;
+ _0_loopy = pix;
}
-%s = _inlineResulthalf4loopyhalf40;
+%s = _0_loopy;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__",
- });
+)__Cpp__"});
+}
+
+DEF_TEST(SkSLFPInlinerManglesOverlappingNames, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ R"__SkSL__(
+ uniform half4 color;
+ half add(half a, half b) {
+ half c = a + b;
+ return c;
+ }
+ half mul(half a, half b) {
+ return a * b;
+ }
+ half fma(half a, half b, half c) {
+ return add(mul(a, b), c);
+ }
+ half4 main() {
+ half a = fma(color.x, color.y, color.z);
+ half b = fma(color.y, color.z, color.w);
+ half c = fma(color.z, color.w, color.x);
+ return half4(a, b, mul(c, c), mul(a, mul(b, c)));
+ }
+ )__SkSL__",
+ /*expectedH=*/{},
+ /*expectedCPP=*/{R"__Cpp__(fragBuilder->codeAppendf(
+R"SkSL(half _2_fma;
+half _3_a = %s.x;
+half _4_b = %s.y;
+half _5_c = %s.z;
+{
+ half _0_mul;
+ {
+ _0_mul = _3_a * _4_b;
+ }
+
+ half _1_add;
+ {
+ half c = _0_mul + _5_c;
+ _1_add = c;
+ }
+
+ _2_fma = _1_add;
+
+}
+
+half a = _2_fma;
+
+half _6_fma;
+half _7_a = %s.y;
+half _8_b = %s.z;
+half _9_c = %s.w;
+{
+ half _0_mul;
+ {
+ _0_mul = _7_a * _8_b;
+ }
+
+ half _1_add;
+ {
+ half c = _0_mul + _9_c;
+ _1_add = c;
+ }
+
+ _6_fma = _1_add;
+
+}
+
+half b = _6_fma;
+
+half _10_fma;
+half _11_a = %s.z;
+half _12_b = %s.w;
+half _13_c = %s.x;
+{
+ half _0_mul;
+ {
+ _0_mul = _11_a * _12_b;
+ }
+
+ half _1_add;
+ {
+ half c = _0_mul + _13_c;
+ _1_add = c;
+ }
+
+ _10_fma = _1_add;
+
+}
+
+half c = _10_fma;
+
+half _14_mul;
+{
+ _14_mul = c * c;
+}
+
+half _15_mul;
+{
+ _15_mul = b * c;
+}
+
+half _16_mul;
+{
+ _16_mul = a * _15_mul;
+}
+
+return half4(a, b, _14_mul, _16_mul);
+
+)SkSL"
+, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar));
+)__Cpp__"});
}
DEF_TEST(SkSLFPIfStatementWithReturnInsideCanBeInlined, r) {
@@ -1284,17 +1390,16 @@
/*expectedH=*/{},
/*expectedCPP=*/{
R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4branchyhalf40;
+R"SkSL(half4 _0_branchy;
{
- if (%s.z == %s.w) _inlineResulthalf4branchyhalf40 = %s.yyyy; else _inlineResulthalf4branchyhalf40 = %s.zzzz;
+ if (%s.z == %s.w) _0_branchy = %s.yyyy; else _0_branchy = %s.zzzz;
}
-%s = _inlineResulthalf4branchyhalf40;
+%s = _0_branchy;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__",
- });
+)__Cpp__"});
}
DEF_TEST(SkSLFPUnnecessaryBlocksDoNotAffectEarlyReturnDetection, r) {
@@ -1314,14 +1419,14 @@
/*expectedH=*/{},
/*expectedCPP=*/{
R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4blockyhalf40;
+R"SkSL(half4 _0_blocky;
{
{
- _inlineResulthalf4blockyhalf40 = %s;
+ _0_blocky = %s;
}
}
-%s = _inlineResulthalf4blockyhalf40;
+%s = _0_blocky;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
@@ -1345,23 +1450,23 @@
/*expectedH=*/{},
/*expectedCPP=*/{
R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4returnyhalf40;
+R"SkSL(half4 _0_returny;
do {
if (%s.x > %s.y) {
- _inlineResulthalf4returnyhalf40 = %s.xxxx;
+ _0_returny = %s.xxxx;
break;
}
if (%s.y > %s.z) {
- _inlineResulthalf4returnyhalf40 = %s.yyyy;
+ _0_returny = %s.yyyy;
break;
}
{
- _inlineResulthalf4returnyhalf40 = %s.zzzz;
+ _0_returny = %s.zzzz;
break;
}
} while (false);
-%s = _inlineResulthalf4returnyhalf40;
+%s = _0_returny;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
@@ -1405,27 +1510,27 @@
/*expectedH=*/{},
/*expectedCPP=*/{
R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _inlineResulthalf4branchyhalf40;
-half4 _inlineArghalf4branchyhalf41_0 = %s;
+R"SkSL(half4 _0_branchy;
+half4 _1_c = %s;
{
- _inlineArghalf4branchyhalf41_0 *= 0.5;
- if (_inlineArghalf4branchyhalf41_0.x > 0.0) _inlineResulthalf4branchyhalf40 = _inlineArghalf4branchyhalf41_0.xxxx; else if (_inlineArghalf4branchyhalf41_0.y > 0.0) _inlineResulthalf4branchyhalf40 = _inlineArghalf4branchyhalf41_0.yyyy; else if (_inlineArghalf4branchyhalf41_0.z > 0.0) _inlineResulthalf4branchyhalf40 = _inlineArghalf4branchyhalf41_0.zzzz; else _inlineResulthalf4branchyhalf40 = _inlineArghalf4branchyhalf41_0.wwww;
+ _1_c *= 0.5;
+ if (_1_c.x > 0.0) _0_branchy = _1_c.xxxx; else if (_1_c.y > 0.0) _0_branchy = _1_c.yyyy; else if (_1_c.z > 0.0) _0_branchy = _1_c.zzzz; else _0_branchy = _1_c.wwww;
}
-half4 _inlineResulthalf4branchyAndBlockyhalf42;
+half4 _2_branchyAndBlocky;
{
{
{
if (%s.x > 0.0) {
half4 d = %s * 0.5;
- _inlineResulthalf4branchyAndBlockyhalf42 = d.xxxx;
+ _2_branchyAndBlocky = d.xxxx;
} else {
{
{
if (%s.x < 0.0) {
- _inlineResulthalf4branchyAndBlockyhalf42 = %s.wwww;
+ _2_branchyAndBlocky = %s.wwww;
} else {
- _inlineResulthalf4branchyAndBlockyhalf42 = %s.yyyy;
+ _2_branchyAndBlocky = %s.yyyy;
}
}
}
@@ -1434,7 +1539,7 @@
}
}
-%s = _inlineResulthalf4branchyhalf40 * _inlineResulthalf4branchyAndBlockyhalf42;
+%s = _0_branchy * _2_branchyAndBlocky;
)SkSL"
, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 6e0436f..62b63a4 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -102,26 +102,27 @@
"void bar(inout float x) { float y[2], z; y[0] = x; y[1] = x * 2; z = foo(y); x = z; }"
"void main() { float x = 10; bar(x); sk_FragColor = half4(half(x)); }",
*SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "out vec4 sk_FragColor;\n"
- "void main() {\n"
- " float x = 10.0;\n"
- " {\n"
- " float y[2], z;\n"
- " y[0] = 10.0;\n"
- " y[1] = 20.0;\n"
- " float _inlineResultfloatfoofloat20;\n"
- " {\n"
- " _inlineResultfloatfoofloat20 = y[0] * y[1];\n"
- " }\n"
- "\n"
- " z = _inlineResultfloatfoofloat20;\n"
- "\n"
- " x = z;\n"
- " }\n"
- "\n"
- " sk_FragColor = vec4(x);\n"
- "}\n");
+R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+ float x = 10.0;
+ {
+ float y[2], z;
+ y[0] = 10.0;
+ y[1] = 20.0;
+ float _0_foo;
+ {
+ _0_foo = y[0] * y[1];
+ }
+
+ z = _0_foo;
+
+ x = z;
+ }
+
+ sk_FragColor = vec4(x);
+}
+)__GLSL__");
}
DEF_TEST(SkSLFunctionInlineThreshold, r) {
@@ -266,19 +267,20 @@
" sk_FragColor.x = parameterWrite(1);"
"}",
*SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "out vec4 sk_FragColor;\n"
- "void main() {\n"
- " float _inlineResulthalfparameterWritehalf0;\n"
- " float _inlineArghalfparameterWritehalf1_0 = 1.0;\n"
- " {\n"
- " _inlineArghalfparameterWritehalf1_0 *= 2.0;\n"
- " _inlineResulthalfparameterWritehalf0 = _inlineArghalfparameterWritehalf1_0;\n"
- " }\n"
- "\n"
- " sk_FragColor.x = _inlineResulthalfparameterWritehalf0;\n"
- "\n"
- "}\n");
+R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+ float _0_parameterWrite;
+ float _1_x = 1.0;
+ {
+ _1_x *= 2.0;
+ _0_parameterWrite = _1_x;
+ }
+
+ sk_FragColor.x = _0_parameterWrite;
+
+}
+)__GLSL__");
test(r,
"void outParameter(inout half x) {"
" x *= 2;"
@@ -310,30 +312,61 @@
" return y;"
"}"
"void main() {"
+ " half _1_y = 123;" // make sure the inliner doesn't try to reuse this name
" half z = 0;"
" bar(z);"
" sk_FragColor.x = z;"
"}",
*SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "out vec4 sk_FragColor;\n"
- "void foo(out float x) {\n"
- " ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n"
- " ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n ++x;\n"
- " ++x;\n --x;\n --x;\n --x;\n --x;\n --x;\n --x;\n --x;\n"
- " --x;\n --x;\n --x;\n --x;\n --x;\n --x;\n --x;\n --x;\n"
- " --x;\n --x;\n"
- " x = 42.0;\n"
- "}\n"
- "void main() {\n"
- " float _inlineArghalfbarhalf1_0 = 0.0;\n"
- " {\n"
- " foo(_inlineArghalfbarhalf1_0);\n"
- " }\n"
- "\n"
- "\n"
- " sk_FragColor.x = 0.0;\n"
- "}\n");
+R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void foo(out float x) {
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ ++x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ --x;
+ x = 42.0;
+}
+void main() {
+ float _2_y = 0.0;
+ {
+ foo(_2_y);
+ }
+
+
+ sk_FragColor.x = 0.0;
+}
+)__GLSL__");
}
DEF_TEST(SkSLMatrices, r) {