Migrate inliner-related tests to a separate unit-test file.
All tests are now GLSL-based instead of .fp based, for ease of
readability. DEF_TESTs which called test() more than once have been
split up into a separate individual DEF_TEST for each test() call, to
simplify fixups going forward.
Change-Id: I9202e95e9cafff3efc0c32aa3f3ca2eea04719fe
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/314886
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/gn/tests.gni b/gn/tests.gni
index 5ac9e8f..749bc7c 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -262,6 +262,7 @@
"$_tests/SkSLErrorTest.cpp",
"$_tests/SkSLFPTest.cpp",
"$_tests/SkSLGLSLTest.cpp",
+ "$_tests/SkSLInlinerTest.cpp",
"$_tests/SkSLInterpreterTest.cpp",
"$_tests/SkSLMemoryLayoutTest.cpp",
"$_tests/SkSLMetalTest.cpp",
diff --git a/tests/SkSLFPTest.cpp b/tests/SkSLFPTest.cpp
index 9f49561..521023a 100644
--- a/tests/SkSLFPTest.cpp
+++ b/tests/SkSLFPTest.cpp
@@ -1087,878 +1087,6 @@
)__Cpp__"});
}
-DEF_TEST(SkSLFPTernaryExpressionsShouldNotInlineResults, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half count = 0;
- bool test(half4 v) {
- return v.x <= 0.5;
- }
- half4 trueSide(half4 v) {
- count += 1;
- return half4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
- }
- half4 falseSide(half4 v) {
- count += 1;
- return half4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
- }
- void main() {
- sk_OutColor = test(color) ? trueSide(color) : falseSide(color);
- sk_OutColor *= count;
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(SkString trueSide_name;
- const GrShaderVar trueSide_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kHalf4_GrSLType, "trueSide", 1, trueSide_args,
-R"SkSL(count += 1.0;
-return half4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
-)SkSL", &trueSide_name);
- SkString falseSide_name;
- const GrShaderVar falseSide_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kHalf4_GrSLType, "falseSide", 1, falseSide_args,
-R"SkSL(count += 1.0;
-return half4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
-)SkSL", &falseSide_name);
- fragBuilder->codeAppendf(
-R"SkSL(half count = %f;
-bool _0_test;
-{
- _0_test = %s.x <= 0.5;
-}
-
-%s = _0_test ? %s(%s) : %s(%s);
-
-%s *= count;
-)SkSL"
-, count, args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor, trueSide_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), falseSide_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPShortCircuitEvaluationsCannotInlineRightHandSide, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- bool testA(half4 v) {
- return v.x <= 0.5;
- }
- bool testB(half4 v) {
- return v.x > 0.5;
- }
- void main() {
- sk_OutColor = half4(0);
- if (testA(color) && testB(color)) {
- sk_OutColor = half4(0.5);
- }
- if (testB(color) || testA(color)) {
- sk_OutColor = half4(1.0);
- }
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__( SkString testA_name;
- const GrShaderVar testA_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kBool_GrSLType, "testA", 1, testA_args,
-R"SkSL(return v.x <= 0.5;
-)SkSL", &testA_name);
- SkString testB_name;
- const GrShaderVar testB_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kBool_GrSLType, "testB", 1, testB_args,
-R"SkSL(return v.x > 0.5;
-)SkSL", &testB_name);
- fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-bool _0_testA;
-{
- _0_testA = %s.x <= 0.5;
-}
-
-if (_0_testA && %s(%s)) {
- %s = half4(0.5);
-}
-
-bool _1_testB;
-{
- _1_testB = %s.x > 0.5;
-}
-
-if (_1_testB || %s(%s)) {
- %s = half4(1.0);
-}
-
-)SkSL"
-, args.fOutputColor, args.fUniformHandler->getUniformCStr(colorVar), testB_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor, args.fUniformHandler->getUniformCStr(colorVar), testA_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPWhileTestCannotBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- bool shouldLoop(half4 v) {
- return v.x < 0.5;
- }
- void main() {
- sk_OutColor = half4(0);
- while (shouldLoop(sk_OutColor)) {
- sk_OutColor += half4(0.125);
- }
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(SkString shouldLoop_name;
- const GrShaderVar shouldLoop_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kBool_GrSLType, "shouldLoop", 1, shouldLoop_args,
-R"SkSL(return v.x < 0.5;
-)SkSL", &shouldLoop_name);
- fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-while (%s(%s)) {
- %s += half4(0.125);
-}
-)SkSL"
-, args.fOutputColor, shouldLoop_name.c_str(), args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedWhileBodyMustBeInAScope, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- half4 adjust(half4 v) {
- return v + half4(0.125);
- }
- void main() {
- sk_OutColor = half4(0);
- while (sk_OutColor.x < 0.5)
- sk_OutColor = adjust(sk_OutColor);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "adjust", 1, adjust_args,
-R"SkSL(return v + half4(0.125);
-)SkSL", &adjust_name);
- fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-while (%s.x < 0.5) {
- half4 _0_adjust;
- {
- _0_adjust = %s + half4(0.125);
- }
-
- %s = _0_adjust;
-}
-)SkSL"
-, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPDoWhileTestCannotBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- bool shouldLoop(half4 v) {
- return v.x < 0.5;
- }
- void main() {
- sk_OutColor = half4(0);
- do {
- sk_OutColor += half4(0.125);
- } while (shouldLoop(sk_OutColor));
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(SkString shouldLoop_name;
- const GrShaderVar shouldLoop_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kBool_GrSLType, "shouldLoop", 1, shouldLoop_args,
-R"SkSL(return v.x < 0.5;
-)SkSL", &shouldLoop_name);
- fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-do {
- %s += half4(0.125);
-} while (%s(%s));
-)SkSL"
-, args.fOutputColor, args.fOutputColor, shouldLoop_name.c_str(), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedDoWhileBodyMustBeInAScope, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- half4 adjust(half4 v) {
- return v + half4(0.125);
- }
- void main() {
- sk_OutColor = half4(0);
- do
- sk_OutColor = adjust(sk_OutColor);
- while (sk_OutColor.x < 0.5);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "adjust", 1, adjust_args,
-R"SkSL(return v + half4(0.125);
-)SkSL", &adjust_name);
- fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-do {
- half4 _0_adjust;
- {
- _0_adjust = %s + half4(0.125);
- }
-
- %s = _0_adjust;
-} while (%s.x < 0.5);
-)SkSL"
-, args.fOutputColor, args.fOutputColor, args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPOnlyForInitializerExpressionsCanBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- half4 initLoopVar() {
- return half4(0.0625);
- }
- bool shouldLoop(half4 v) {
- return v.x < 0.5;
- }
- half4 grow(half4 v) {
- return v + half4(0.125);
- }
- void main() {
- for (sk_OutColor = initLoopVar();
- shouldLoop(sk_OutColor);
- sk_OutColor = grow(sk_OutColor)) {
- }
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(SkString initLoopVar_name;
- const GrShaderVar initLoopVar_args[] = { };
- fragBuilder->emitFunction(kHalf4_GrSLType, "initLoopVar", 0, initLoopVar_args,
-R"SkSL(return half4(0.0625);
-)SkSL", &initLoopVar_name);
- SkString shouldLoop_name;
- const GrShaderVar shouldLoop_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kBool_GrSLType, "shouldLoop", 1, shouldLoop_args,
-R"SkSL(return v.x < 0.5;
-)SkSL", &shouldLoop_name);
- SkString grow_name;
- const GrShaderVar grow_args[] = { GrShaderVar("v", kHalf4_GrSLType)};
- fragBuilder->emitFunction(kHalf4_GrSLType, "grow", 1, grow_args,
-R"SkSL(return v + half4(0.125);
-)SkSL", &grow_name);
- fragBuilder->codeAppendf(
-R"SkSL(for (%s = half4(0.0625);
-%s(%s); %s = %s(%s)) {
-}
-)SkSL"
-, args.fOutputColor, shouldLoop_name.c_str(), args.fOutputColor, args.fOutputColor, grow_name.c_str(), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedForBodyMustBeInAScope, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- half4 adjust(half4 v) {
- return v + half4(0.125);
- }
- void main() {
- sk_OutColor = half4(0);
- for (int x=0; x<4; ++x)
- sk_OutColor = adjust(sk_OutColor);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(%s = half4(0.0);
-for (int x = 0;x < 4; ++x) {
- half4 _0_adjust;
- {
- _0_adjust = %s + half4(0.125);
- }
-
- %s = _0_adjust;
-}
-)SkSL"
-, args.fOutputColor, args.fOutputColor, args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPIfTestsCanBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- bool ifTest(half4 v) {
- return color.x >= 0.5;
- }
- void main() {
- if (ifTest(color))
- sk_OutColor = half4(1.0);
- else
- sk_OutColor = half4(0.5);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(bool _0_ifTest;
-{
- _0_ifTest = %s.x >= 0.5;
-}
-
-if (_0_ifTest) %s = half4(1.0); else %s = half4(0.5);
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedIfBodyMustBeInAScope, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 ifBody() {
- return color + half4(0.125);
- }
- void main() {
- half4 c = color;
- if (c.x >= 0.5)
- c = ifBody();
- sk_OutColor = c;
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 c = %s;
-if (c.x >= 0.5) {
- half4 _0_ifBody;
- {
- _0_ifBody = %s + half4(0.125);
- }
-
- c = _0_ifBody;
-}
-%s = c;
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedElseBodyMustBeInAScope, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 elseBody() {
- return color + half4(0.125);
- }
- void main() {
- half4 c = color;
- if (c.x >= 0.5)
- ;
- else
- c = elseBody();
- sk_OutColor = c;
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 c = %s;
-if (c.x >= 0.5) {
-} else {
- half4 _0_elseBody;
- {
- _0_elseBody = %s + half4(0.125);
- }
-
- c = _0_elseBody;
-}
-%s = c;
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPSwitchWithReturnInsideCannotBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 switchy(half4 c) {
- switch (int(c.x)) {
- case 0: return c.yyyy;
- }
- return c.zzzz;
- }
- void main() {
- sk_OutColor = switchy(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "switchy", 1, switchy_args,
-R"SkSL(switch (int(c.x)) {
- case 0:
- return c.yyyy;
-}
-return c.zzzz;
-)SkSL", &switchy_name);
- fragBuilder->codeAppendf(
-R"SkSL(%s = %s(%s);
-)SkSL"
-, args.fOutputColor, switchy_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPSwitchWithoutReturnInsideCanBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 switchy(half4 c) {
- half4 result;
- switch (int(c.x)) {
- case 0: result = c.yyyy;
- }
- result = c.zzzz;
- return result;
- }
- void main() {
- sk_OutColor = switchy(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_switchy;
-{
- half4 result;
- switch (int(%s.x)) {
- case 0:
- result = %s.yyyy;
- }
- result = %s.zzzz;
- _0_switchy = result;
-}
-
-%s = _0_switchy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPForLoopWithReturnInsideCannotBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 loopy(half4 c) {
- for (int x=0; x<5; ++x) {
- if (x == int(c.w)) return c.yyyy;
- }
- return c.zzzz;
- }
- void main() {
- sk_OutColor = loopy(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->emitFunction(kHalf4_GrSLType, "loopy", 1, loopy_args,
-R"SkSL(for (int x = 0;x < 5; ++x) {
- if (x == int(c.w)) return c.yyyy;
-}
-return c.zzzz;
-)SkSL", &loopy_name);
- fragBuilder->codeAppendf(
-R"SkSL(%s = %s(%s);
-)SkSL"
-, args.fOutputColor, loopy_name.c_str(), args.fUniformHandler->getUniformCStr(colorVar));
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPSwitchWithCastCanBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 switchy(half4 c) {
- half4 result;
- switch (int(c.x)) {
- case 1: result = c.yyyy; break;
- default: result = c.zzzz; break;
- }
- return result;
- }
- void main() {
- sk_OutColor = switchy(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_switchy;
-{
- half4 result;
- switch (int(%s.x)) {
- case 1:
- result = %s.yyyy;
- break;
- default:
- result = %s.zzzz;
- break;
- }
- _0_switchy = result;
-}
-
-%s = _0_switchy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPForLoopWithoutReturnInsideCanBeInlined, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 loopy(half4 c) {
- half4 pix;
- for (int x=0; x<5; ++x) {
- if (x == int(c.w)) pix = c.yyyy;
- }
- pix = c.zzzz;
- return pix;
- }
- void main() {
- sk_OutColor = loopy(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-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;
- _0_loopy = pix;
-}
-
-%s = _0_loopy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__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) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 branchy(half4 c) {
- if (c.z == c.w) return c.yyyy; else return c.zzzz;
- }
- void main() {
- sk_OutColor = branchy(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_branchy;
-{
- if (%s.z == %s.w) _0_branchy = %s.yyyy; else _0_branchy = %s.zzzz;
-}
-
-%s = _0_branchy;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPUnnecessaryBlocksDoNotAffectEarlyReturnDetection, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- half4 blocky(half4 c) {
- {
- return c;
- }
- }
- void main() {
- sk_OutColor = blocky(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_blocky;
-{
- {
- _0_blocky = %s;
- }
-}
-
-%s = _0_blocky;
-
-)SkSL"
-, args.fUniformHandler->getUniformCStr(colorVar), args.fOutputColor);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPInlinedEarlyReturnsAreWrappedInDoWhileBlock, r) {
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- inline half4 returny(half4 c) {
- if (c.x > c.y) return c.xxxx;
- if (c.y > c.z) return c.yyyy;
- return c.zzzz;
- }
- void main() {
- sk_OutColor = returny(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_returny;
-do {
- if (%s.x > %s.y) {
- _0_returny = %s.xxxx;
- break;
- }
- if (%s.y > %s.z) {
- _0_returny = %s.yyyy;
- break;
- }
- {
- _0_returny = %s.zzzz;
- break;
- }
-} while (false);
-
-%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);
-)__Cpp__"});
-}
-
-DEF_TEST(SkSLFPEarlyReturnDetectionSupportsIfElse, r) {
- // An if-else statement at the end of a function, with a return as the last statement on all
- // paths, are not actually "early" returns. The inliner is able to recognize this pattern.
- test(r,
- *SkSL::ShaderCapsFactory::Default(),
- R"__SkSL__(
- uniform half4 color;
- inline half4 branchy(half4 c) {
- c *= 0.5;
- if (c.x > 0)
- return c.xxxx;
- else if (c.y > 0)
- return c.yyyy;
- else if (c.z > 0)
- return c.zzzz;
- else
- return c.wwww;
- }
- inline half4 branchyAndBlocky(half4 c) {{{
- if (c.x > 0) {
- half4 d = c * 0.5;
- return d.xxxx;
- } else {{{
- if (c.x < 0) {
- return c.wwww;
- } else {
- return c.yyyy;
- }
- }}}
- }}}
- void main() {
- sk_OutColor = branchy(color) * branchyAndBlocky(color);
- }
- )__SkSL__",
- /*expectedH=*/{},
- /*expectedCPP=*/{
- R"__Cpp__(fragBuilder->codeAppendf(
-R"SkSL(half4 _0_branchy;
-half4 _1_c = %s;
-{
- _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 _2_branchyAndBlocky;
-{
- {
- {
- if (%s.x > 0.0) {
- half4 d = %s * 0.5;
- _2_branchyAndBlocky = d.xxxx;
- } else {
- {
- {
- if (%s.x < 0.0) {
- _2_branchyAndBlocky = %s.wwww;
- } else {
- _2_branchyAndBlocky = %s.yyyy;
- }
- }
- }
- }
- }
- }
-}
-
-%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);
-)__Cpp__"});
-}
-
DEF_TEST(SkSLFPGrSLTypesAreSupported, r) {
// We thwart the optimizer by wrapping our return statement in a loop, which prevents inlining.
test(r,
diff --git a/tests/SkSLGLSLTest.cpp b/tests/SkSLGLSLTest.cpp
index 62b63a4..16724fb 100644
--- a/tests/SkSLGLSLTest.cpp
+++ b/tests/SkSLGLSLTest.cpp
@@ -125,70 +125,6 @@
)__GLSL__");
}
-DEF_TEST(SkSLFunctionInlineThreshold, r) {
- test(r,
- "void tooBig(inout int 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;"
- "}"
- "void main() { int x = 0; tooBig(x); }",
- *SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "void tooBig(inout int 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"
- "}\n"
- "void main() {\n"
- " int x = 0;\n"
- " tooBig(x);\n"
- "}\n"
- );
- test(r,
- "inline void tooBig(inout int 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;"
- "}"
- "void main() { int y = 0; tooBig(y); }",
- *SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "void main() {\n"
- " int y = 0;\n"
- " {\n"
- " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
- " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
- " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
- " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
- " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
- " ++y;\n ++y;\n ++y;\n ++y;\n"
- " }\n"
- "\n"
- "}\n"
- );
- test(r,
- "inline void cantActuallyInline(inout int x) {"
- " for (;;) {"
- " ++x;"
- " if (x > 10) return;"
- " }"
- "}"
- "void main() { int x = 0; cantActuallyInline(x); }",
- *SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "void cantActuallyInline(inout int x) {\n"
- " for (; ; ) {\n"
- " ++x;\n"
- " if (x > 10) return;\n"
- " }\n"
- "}\n"
- "void main() {\n"
- " int x = 0;\n"
- " cantActuallyInline(x);\n"
- "}\n");
-}
-
DEF_TEST(SkSLOperators, r) {
test(r,
"void main() {"
@@ -239,136 +175,6 @@
"}\n");
}
-DEF_TEST(SkSLFunctionInlineArguments, r) {
- test(r,
- "half basic(half x) {"
- " return x * 2;"
- "}"
- "void main() {"
- " sk_FragColor.x = basic(1);"
- " half y = 2;"
- " sk_FragColor.y = basic(y);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "out vec4 sk_FragColor;\n"
- "void main() {\n"
- " sk_FragColor.x = 2.0;\n"
- "\n"
- " sk_FragColor.y = 4.0;\n"
- "\n"
- "}\n");
- test(r,
- "half parameterWrite(half x) {"
- " x *= 2;"
- " return x;"
- "}"
- "void main() {"
- " sk_FragColor.x = parameterWrite(1);"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
-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;"
- "}"
- "void main() {"
- " half x = 1;"
- " outParameter(x);"
- " sk_FragColor.x = x;"
- "}",
- *SkSL::ShaderCapsFactory::Default(),
- "#version 400\n"
- "out vec4 sk_FragColor;\n"
- "void main() {\n"
- " float x = 1.0;\n"
- " {\n"
- " x *= 2.0;\n"
- " }\n"
- "\n"
- " sk_FragColor.x = x;\n"
- "}\n");
- test(r,
- "void foo(out half 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;"
- "}"
- "half bar(half y) {"
- " foo(y);"
- " 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(),
-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) {
test(r,
"void main() {"
diff --git a/tests/SkSLInlinerTest.cpp b/tests/SkSLInlinerTest.cpp
new file mode 100644
index 0000000..4bb7be0
--- /dev/null
+++ b/tests/SkSLInlinerTest.cpp
@@ -0,0 +1,1100 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/sksl/SkSLCompiler.h"
+
+#include "tests/Test.h"
+
+// Note that the optimizer will aggressively kill dead code and substitute constants in place of
+// variables, so we have to jump through a few hoops to ensure that the code in these tests has the
+// necessary side-effects to remain live. In some cases we rely on the optimizer not (yet) being
+// smart enough to optimize around certain constructs; as the optimizer gets smarter it will
+// undoubtedly end up breaking some of these tests. That is a good thing, as long as the new code is
+// equivalent!
+
+static void test(skiatest::Reporter* r, const SkSL::Program::Settings& settings,
+ const char* src, const char* expectedGLSL, SkSL::Program::Inputs* inputs,
+ SkSL::Program::Kind kind = SkSL::Program::kFragment_Kind) {
+ SkSL::Compiler compiler;
+ SkSL::String output;
+ std::unique_ptr<SkSL::Program> program = compiler.convertProgram(kind, SkSL::String(src),
+ settings);
+ if (!program) {
+ SkDebugf("Unexpected error compiling %s\n%s", src, compiler.errorText().c_str());
+ }
+ REPORTER_ASSERT(r, program);
+ if (program) {
+ *inputs = program->fInputs;
+ REPORTER_ASSERT(r, compiler.toGLSL(*program, &output));
+ if (program) {
+ SkSL::String skExpected(expectedGLSL);
+ if (output != skExpected) {
+ SkDebugf("GLSL MISMATCH:\nsource:\n%s\n\nexpected:\n'%s'\n\nreceived:\n'%s'",
+ src, expectedGLSL, output.c_str());
+ }
+ REPORTER_ASSERT(r, output == skExpected);
+ }
+ }
+}
+
+static void test(skiatest::Reporter* r, const GrShaderCaps& caps,
+ const char* src, const char* expectedGLSL,
+ SkSL::Program::Kind kind = SkSL::Program::kFragment_Kind) {
+ SkSL::Program::Settings settings;
+ settings.fCaps = ∩︀
+ SkSL::Program::Inputs inputs;
+ test(r, settings, src, expectedGLSL, &inputs, kind);
+}
+
+DEF_TEST(SkSLFunctionInlineThreshold, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ "void tooBig(inout int 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;"
+ "}"
+ "void main() { int x = 0; tooBig(x); }",
+ "#version 400\n"
+ "void tooBig(inout int 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"
+ "}\n"
+ "void main() {\n"
+ " int x = 0;\n"
+ " tooBig(x);\n"
+ "}\n"
+ );
+}
+
+DEF_TEST(SkSLFunctionInlineKeywordOverridesThreshold, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ "inline void tooBig(inout int 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;"
+ "}"
+ "void main() { int y = 0; tooBig(y); }",
+ "#version 400\n"
+ "void main() {\n"
+ " int y = 0;\n"
+ " {\n"
+ " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
+ " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
+ " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
+ " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
+ " ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n ++y;\n"
+ " ++y;\n ++y;\n ++y;\n ++y;\n"
+ " }\n"
+ "\n"
+ "}\n"
+ );
+}
+
+DEF_TEST(SkSLFunctionUnableToInlineReturnsInsideLoop, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ "inline void cantActuallyInline(inout int x) {"
+ " for (;;) {"
+ " ++x;"
+ " if (x > 10) return;"
+ " }"
+ "}"
+ "void main() { int x = 0; cantActuallyInline(x); }",
+ "#version 400\n"
+ "void cantActuallyInline(inout int x) {\n"
+ " for (; ; ) {\n"
+ " ++x;\n"
+ " if (x > 10) return;\n"
+ " }\n"
+ "}\n"
+ "void main() {\n"
+ " int x = 0;\n"
+ " cantActuallyInline(x);\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLFunctionInlineWithUnmodifiedArgument, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ "half basic(half x) {"
+ " return x * 2;"
+ "}"
+ "void main() {"
+ " sk_FragColor.x = basic(1);"
+ " half y = 2;"
+ " sk_FragColor.y = basic(y);"
+ "}",
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " sk_FragColor.x = 2.0;\n"
+ "\n"
+ " sk_FragColor.y = 4.0;\n"
+ "\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLFunctionInlineWithModifiedArgument, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ "half parameterWrite(half x) {"
+ " x *= 2;"
+ " return x;"
+ "}"
+ "void main() {"
+ " sk_FragColor.x = parameterWrite(1);"
+ "}",
+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__");
+}
+
+DEF_TEST(SkSLFunctionInlineWithInoutArgument, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ "void outParameter(inout half x) {"
+ " x *= 2;"
+ "}"
+ "void main() {"
+ " half x = 1;"
+ " outParameter(x);"
+ " sk_FragColor.x = x;"
+ "}",
+ "#version 400\n"
+ "out vec4 sk_FragColor;\n"
+ "void main() {\n"
+ " float x = 1.0;\n"
+ " {\n"
+ " x *= 2.0;\n"
+ " }\n"
+ "\n"
+ " sk_FragColor.x = x;\n"
+ "}\n");
+}
+
+DEF_TEST(SkSLFunctionInlineWithNestedCall, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ "void foo(out half 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;"
+ "}"
+ "half bar(half y) {"
+ " foo(y);"
+ " 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;"
+ "}",
+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(SkSLFPTernaryExpressionsShouldNotInlineResults, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half count = 0;
+ bool test(half4 v) {
+ return v.x <= 0.5;
+ }
+ half4 trueSide(half4 v) {
+ count += 1;
+ return half4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
+ }
+ half4 falseSide(half4 v) {
+ count += 1;
+ return half4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
+ }
+ void main() {
+ sk_FragColor = test(color) ? trueSide(color) : falseSide(color);
+ sk_FragColor *= count;
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+float count = 0.0;
+vec4 trueSide(vec4 v) {
+ count += 1.0;
+ return vec4(sin(v.x), sin(v.y), sin(v.z), sin(v.w));
+}
+vec4 falseSide(vec4 v) {
+ count += 1.0;
+ return vec4(cos(v.y), cos(v.z), cos(v.w), cos(v.z));
+}
+void main() {
+ bool _0_test;
+ {
+ _0_test = color.x <= 0.5;
+ }
+
+ sk_FragColor = _0_test ? trueSide(color) : falseSide(color);
+
+ sk_FragColor *= count;
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPShortCircuitEvaluationsCannotInlineRightHandSide, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ bool testA(half4 v) {
+ return v.x <= 0.5;
+ }
+ bool testB(half4 v) {
+ return v.x > 0.5;
+ }
+ void main() {
+ sk_FragColor = half4(0);
+ if (testA(color) && testB(color)) {
+ sk_FragColor = half4(0.5);
+ }
+ if (testB(color) || testA(color)) {
+ sk_FragColor = half4(1.0);
+ }
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+bool testA(vec4 v) {
+ return v.x <= 0.5;
+}
+bool testB(vec4 v) {
+ return v.x > 0.5;
+}
+void main() {
+ sk_FragColor = vec4(0.0);
+ bool _0_testA;
+ {
+ _0_testA = color.x <= 0.5;
+ }
+
+ if (_0_testA && testB(color)) {
+ sk_FragColor = vec4(0.5);
+ }
+
+ bool _1_testB;
+ {
+ _1_testB = color.x > 0.5;
+ }
+
+ if (_1_testB || testA(color)) {
+ sk_FragColor = vec4(1.0);
+ }
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPWhileTestCannotBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ bool shouldLoop(half4 v) {
+ return v.x < 0.5;
+ }
+ void main() {
+ sk_FragColor = half4(0);
+ while (shouldLoop(sk_FragColor)) {
+ sk_FragColor += half4(0.125);
+ }
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+bool shouldLoop(vec4 v) {
+ return v.x < 0.5;
+}
+void main() {
+ sk_FragColor = vec4(0.0);
+ while (shouldLoop(sk_FragColor)) {
+ sk_FragColor += vec4(0.125);
+ }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedWhileBodyMustBeInAScope, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ half4 adjust(half4 v) {
+ return v + half4(0.125);
+ }
+ void main() {
+ sk_FragColor = half4(0);
+ while (sk_FragColor.x < 0.5)
+ sk_FragColor = adjust(sk_FragColor);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+ sk_FragColor = vec4(0.0);
+ while (sk_FragColor.x < 0.5) {
+ vec4 _0_adjust;
+ {
+ _0_adjust = sk_FragColor + vec4(0.125);
+ }
+
+ sk_FragColor = _0_adjust;
+ }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPDoWhileTestCannotBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ bool shouldLoop(half4 v) {
+ return v.x < 0.5;
+ }
+ void main() {
+ sk_FragColor = half4(0);
+ do {
+ sk_FragColor += half4(0.125);
+ } while (shouldLoop(sk_FragColor));
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+bool shouldLoop(vec4 v) {
+ return v.x < 0.5;
+}
+void main() {
+ sk_FragColor = vec4(0.0);
+ do {
+ sk_FragColor += vec4(0.125);
+ } while (shouldLoop(sk_FragColor));
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedDoWhileBodyMustBeInAScope, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ half4 adjust(half4 v) {
+ return v + half4(0.125);
+ }
+ void main() {
+ sk_FragColor = half4(0);
+ do
+ sk_FragColor = adjust(sk_FragColor);
+ while (sk_FragColor.x < 0.5);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+ sk_FragColor = vec4(0.0);
+ do {
+ vec4 _0_adjust;
+ {
+ _0_adjust = sk_FragColor + vec4(0.125);
+ }
+
+ sk_FragColor = _0_adjust;
+ } while (sk_FragColor.x < 0.5);
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPOnlyForInitializerExpressionsCanBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ half4 initLoopVar() {
+ return half4(0.0625);
+ }
+ bool shouldLoop(half4 v) {
+ return v.x < 0.5;
+ }
+ half4 grow(half4 v) {
+ return v + half4(0.125);
+ }
+ void main() {
+ for (sk_FragColor = initLoopVar();
+ shouldLoop(sk_FragColor);
+ sk_FragColor = grow(sk_FragColor)) {
+ }
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+bool shouldLoop(vec4 v) {
+ return v.x < 0.5;
+}
+vec4 grow(vec4 v) {
+ return v + vec4(0.125);
+}
+void main() {
+ for (sk_FragColor = vec4(0.0625);
+ shouldLoop(sk_FragColor); sk_FragColor = grow(sk_FragColor)) {
+ }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedForBodyMustBeInAScope, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ half4 adjust(half4 v) {
+ return v + half4(0.125);
+ }
+ void main() {
+ sk_FragColor = half4(0);
+ for (int x=0; x<4; ++x)
+ sk_FragColor = adjust(sk_FragColor);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+void main() {
+ sk_FragColor = vec4(0.0);
+ for (int x = 0;x < 4; ++x) {
+ vec4 _0_adjust;
+ {
+ _0_adjust = sk_FragColor + vec4(0.125);
+ }
+
+ sk_FragColor = _0_adjust;
+ }
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPIfTestsCanBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ bool ifTest(half4 v) {
+ return color.x >= 0.5;
+ }
+ void main() {
+ if (ifTest(color))
+ sk_FragColor = half4(1.0);
+ else
+ sk_FragColor = half4(0.5);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ bool _0_ifTest;
+ {
+ _0_ifTest = color.x >= 0.5;
+ }
+
+ if (_0_ifTest) sk_FragColor = vec4(1.0); else sk_FragColor = vec4(0.5);
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedIfBodyMustBeInAScope, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 ifBody() {
+ return color + half4(0.125);
+ }
+ void main() {
+ half4 c = color;
+ if (c.x >= 0.5)
+ c = ifBody();
+ sk_FragColor = c;
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 c = color;
+ if (c.x >= 0.5) {
+ vec4 _0_ifBody;
+ {
+ _0_ifBody = color + vec4(0.125);
+ }
+
+ c = _0_ifBody;
+ }
+ sk_FragColor = c;
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedElseBodyMustBeInAScope, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 elseBody() {
+ return color + half4(0.125);
+ }
+ void main() {
+ half4 c = color;
+ if (c.x >= 0.5)
+ ;
+ else
+ c = elseBody();
+ sk_FragColor = c;
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 c = color;
+ if (c.x >= 0.5) {
+ } else {
+ vec4 _0_elseBody;
+ {
+ _0_elseBody = color + vec4(0.125);
+ }
+
+ c = _0_elseBody;
+ }
+ sk_FragColor = c;
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPSwitchWithReturnInsideCannotBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 switchy(half4 c) {
+ switch (int(c.x)) {
+ case 0: return c.yyyy;
+ }
+ return c.zzzz;
+ }
+ void main() {
+ sk_FragColor = switchy(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+vec4 switchy(vec4 c) {
+ switch (int(c.x)) {
+ case 0:
+ return c.yyyy;
+ }
+ return c.zzzz;
+}
+void main() {
+ sk_FragColor = switchy(color);
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPSwitchWithoutReturnInsideCanBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 switchy(half4 c) {
+ half4 result;
+ switch (int(c.x)) {
+ case 0: result = c.yyyy;
+ }
+ result = c.zzzz;
+ return result;
+ }
+ void main() {
+ sk_FragColor = switchy(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 _0_switchy;
+ {
+ vec4 result;
+ switch (int(color.x)) {
+ case 0:
+ result = color.yyyy;
+ }
+ result = color.zzzz;
+ _0_switchy = result;
+ }
+
+ sk_FragColor = _0_switchy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPForLoopWithReturnInsideCannotBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 loopy(half4 c) {
+ for (int x=0; x<5; ++x) {
+ if (x == int(c.w)) return c.yyyy;
+ }
+ return c.zzzz;
+ }
+ void main() {
+ sk_FragColor = loopy(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+vec4 loopy(vec4 c) {
+ for (int x = 0;x < 5; ++x) {
+ if (x == int(c.w)) return c.yyyy;
+ }
+ return c.zzzz;
+}
+void main() {
+ sk_FragColor = loopy(color);
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPSwitchWithCastCanBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 switchy(half4 c) {
+ half4 result;
+ switch (int(c.x)) {
+ case 1: result = c.yyyy; break;
+ default: result = c.zzzz; break;
+ }
+ return result;
+ }
+ void main() {
+ sk_FragColor = switchy(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 _0_switchy;
+ {
+ vec4 result;
+ switch (int(color.x)) {
+ case 1:
+ result = color.yyyy;
+ break;
+ default:
+ result = color.zzzz;
+ break;
+ }
+ _0_switchy = result;
+ }
+
+ sk_FragColor = _0_switchy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPForLoopWithoutReturnInsideCanBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 loopy(half4 c) {
+ half4 pix;
+ for (int x=0; x<5; ++x) {
+ if (x == int(c.w)) pix = c.yyyy;
+ }
+ pix = c.zzzz;
+ return pix;
+ }
+ void main() {
+ sk_FragColor = loopy(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 _0_loopy;
+ {
+ vec4 pix;
+ for (int x = 0;x < 5; ++x) {
+ if (x == int(color.w)) pix = color.yyyy;
+ }
+ pix = color.zzzz;
+ _0_loopy = pix;
+ }
+
+ sk_FragColor = _0_loopy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinerManglesOverlappingNames, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/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__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+uniform vec4 color;
+vec4 main() {
+ float _2_fma;
+ float _3_a = color.x;
+ float _4_b = color.y;
+ float _5_c = color.z;
+ {
+ float _0_mul;
+ {
+ _0_mul = _3_a * _4_b;
+ }
+
+ float _1_add;
+ {
+ float c = _0_mul + _5_c;
+ _1_add = c;
+ }
+
+ _2_fma = _1_add;
+
+ }
+
+ float a = _2_fma;
+
+ float _6_fma;
+ float _7_a = color.y;
+ float _8_b = color.z;
+ float _9_c = color.w;
+ {
+ float _0_mul;
+ {
+ _0_mul = _7_a * _8_b;
+ }
+
+ float _1_add;
+ {
+ float c = _0_mul + _9_c;
+ _1_add = c;
+ }
+
+ _6_fma = _1_add;
+
+ }
+
+ float b = _6_fma;
+
+ float _10_fma;
+ float _11_a = color.z;
+ float _12_b = color.w;
+ float _13_c = color.x;
+ {
+ float _0_mul;
+ {
+ _0_mul = _11_a * _12_b;
+ }
+
+ float _1_add;
+ {
+ float c = _0_mul + _13_c;
+ _1_add = c;
+ }
+
+ _10_fma = _1_add;
+
+ }
+
+ float c = _10_fma;
+
+ float _14_mul;
+ {
+ _14_mul = c * c;
+ }
+
+ float _15_mul;
+ {
+ _15_mul = b * c;
+ }
+
+ float _16_mul;
+ {
+ _16_mul = a * _15_mul;
+ }
+
+ return vec4(a, b, _14_mul, _16_mul);
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPIfStatementWithReturnInsideCanBeInlined, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 branchy(half4 c) {
+ if (c.z == c.w) return c.yyyy; else return c.zzzz;
+ }
+ void main() {
+ sk_FragColor = branchy(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 _0_branchy;
+ {
+ if (color.z == color.w) _0_branchy = color.yyyy; else _0_branchy = color.zzzz;
+ }
+
+ sk_FragColor = _0_branchy;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPUnnecessaryBlocksDoNotAffectEarlyReturnDetection, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ half4 blocky(half4 c) {
+ {
+ return c;
+ }
+ }
+ void main() {
+ sk_FragColor = blocky(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 _0_blocky;
+ {
+ {
+ _0_blocky = color;
+ }
+ }
+
+ sk_FragColor = _0_blocky;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPInlinedEarlyReturnsAreWrappedInDoWhileBlock, r) {
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ inline half4 returny(half4 c) {
+ if (c.x > c.y) return c.xxxx;
+ if (c.y > c.z) return c.yyyy;
+ return c.zzzz;
+ }
+ void main() {
+ sk_FragColor = returny(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 _0_returny;
+ do {
+ if (color.x > color.y) {
+ _0_returny = color.xxxx;
+ break;
+ }
+ if (color.y > color.z) {
+ _0_returny = color.yyyy;
+ break;
+ }
+ {
+ _0_returny = color.zzzz;
+ break;
+ }
+ } while (false);
+
+ sk_FragColor = _0_returny;
+
+}
+)__GLSL__");
+}
+
+DEF_TEST(SkSLFPEarlyReturnDetectionSupportsIfElse, r) {
+ // An if-else statement at the end of a function, with a return as the last statement on all
+ // paths, are not actually "early" returns. The inliner is able to recognize this pattern.
+ test(r,
+ *SkSL::ShaderCapsFactory::Default(),
+ /*src=*/R"__SkSL__(
+ uniform half4 color;
+ inline half4 branchy(half4 c) {
+ c *= 0.5;
+ if (c.x > 0)
+ return c.xxxx;
+ else if (c.y > 0)
+ return c.yyyy;
+ else if (c.z > 0)
+ return c.zzzz;
+ else
+ return c.wwww;
+ }
+ inline half4 branchyAndBlocky(half4 c) {{{
+ if (c.x > 0) {
+ half4 d = c * 0.5;
+ return d.xxxx;
+ } else {{{
+ if (c.x < 0) {
+ return c.wwww;
+ } else {
+ return c.yyyy;
+ }
+ }}}
+ }}}
+ void main() {
+ sk_FragColor = branchy(color) * branchyAndBlocky(color);
+ }
+ )__SkSL__",
+ /*expectedGLSL=*/R"__GLSL__(#version 400
+out vec4 sk_FragColor;
+uniform vec4 color;
+void main() {
+ vec4 _0_branchy;
+ vec4 _1_c = color;
+ {
+ _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;
+ }
+
+ vec4 _2_branchyAndBlocky;
+ {
+ {
+ {
+ if (color.x > 0.0) {
+ vec4 d = color * 0.5;
+ _2_branchyAndBlocky = d.xxxx;
+ } else {
+ {
+ {
+ if (color.x < 0.0) {
+ _2_branchyAndBlocky = color.wwww;
+ } else {
+ _2_branchyAndBlocky = color.yyyy;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ sk_FragColor = _0_branchy * _2_branchyAndBlocky;
+
+}
+)__GLSL__");
+}