Fixed SkSL optimization issue

When collapsing static switches down to a single statement, we detect
break statements and don't copy them. But the logic was broken; we
weren't copying the entire statement in which the break occurred, which
could be a block, causing some of the code to simply be omitted.

Change-Id: Ic5b59c11d12326c93d49080193a0a5297732bfb0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/295776
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
Ethan Nicholas 2020-06-11 12:16:14 -04:00 committed by Skia Commit-Bot
parent ee2ffc3b43
commit 739e1caf35
2 changed files with 85 additions and 0 deletions

View File

@ -1070,6 +1070,21 @@ static bool contains_unconditional_break(Statement& s) {
}
}
static void copy_all_but_break(std::unique_ptr<Statement>& stmt,
std::vector<std::unique_ptr<Statement>*>* target) {
switch (stmt->fKind) {
case Statement::kBlock_Kind:
for (auto& s : ((Block&) *stmt).fStatements) {
copy_all_but_break(s, target);
}
break;
case Statement::kBreak_Kind:
return;
default:
target->push_back(&stmt);
}
}
// Returns a block containing all of the statements that will be run if the given case matches
// (which, owing to the statements being owned by unique_ptrs, means the switch itself will be
// broken by this call and must then be discarded).
@ -1089,6 +1104,7 @@ static std::unique_ptr<Statement> block_for_case(SwitchStatement* s, SwitchCase*
}
if (contains_unconditional_break(*stmt)) {
capturing = false;
copy_all_but_break(stmt, &statementPtrs);
break;
}
statementPtrs.push_back(&stmt);

View File

@ -1635,6 +1635,75 @@ DEF_TEST(SkSLSwitch, r) {
" }\n"
" sk_FragColor = vec4(x);\n"
"}\n");
// static test w/ break in a block
test(r,
"void main() {"
" float x = 0.0;"
" switch (0) {"
" case 0: {"
" x = 0.0;"
" sk_FragColor = half4(half(x));"
" break;"
" }"
" case 1:"
" x = 1.0;"
" }"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" {\n"
" sk_FragColor = vec4(0.0);\n"
" }\n"
"}\n");
// static test w/ static conditional break in a block
test(r,
"void main() {"
" float x = 0.0;"
" switch (0) {"
" case 0:"
" x = 0.0;"
" if (x < 1) { sk_FragColor = half4(half(x)); break; }"
" case 1:"
" x = 1.0;"
" }"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" {\n"
" sk_FragColor = vec4(0.0);\n"
" }\n"
"}\n");
// static test w/ non-static conditional break in a block
test(r,
"void main() {"
" float x = 0.0;"
" switch (0) {"
" case 0:"
" x = 0.0;"
" if (x < sqrt(1)) { sk_FragColor = half4(half(x)); break; }"
" case 1:"
" x = 1.0;"
" }"
"}",
*SkSL::ShaderCapsFactory::Default(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" switch (0) {\n"
" case 0:\n"
" ;\n"
" if (0.0 < sqrt(1.0)) {\n"
" sk_FragColor = vec4(0.0);\n"
" break;\n"
" }\n"
" case 1:\n"
" ;\n"
" }\n"
"}\n");
}
DEF_TEST(SkSLRectangleTexture, r) {