Reland "Rewrite switch statements in GLSL strict-ES2 mode."

This reverts commit d26d0e6a47.

Reason for revert: uses dedicated caps bit

Original change's description:
> Revert "Rewrite switch statements in GLSL strict-ES2 mode."
>
> This reverts commit 45e3838006.
>
> Reason for revert: Also need to rewrite them in actual ES2 mode.
>
> Original change's description:
> > Rewrite switch statements in GLSL strict-ES2 mode.
> >
> > Once this lands, switch statements will work everywhere--Metal, SPIR-V,
> > GLSL, and SkVM.
> >
> > Change-Id: I2797d0a872de8be77bb9f7aa6acb93421d571d70
> > Bug: skia:12450
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452356
> > Commit-Queue: John Stiles <johnstiles@google.com>
> > Auto-Submit: John Stiles <johnstiles@google.com>
> > Reviewed-by: Brian Osman <brianosman@google.com>
>
> Bug: skia:12450
> Change-Id: I92656ed40289872405c0873f2c56a52b04e35b1d
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452556
> Auto-Submit: Brian Osman <brianosman@google.com>
> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>

Bug: skia:12450
Change-Id: I0d3b0969d2040dbb4ee808132146687767c97442
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452560
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
John Stiles 2021-09-24 11:44:21 -04:00 committed by SkCQ
parent 6b88839eed
commit c81edd0e8c
15 changed files with 256 additions and 50 deletions

View File

@ -397,10 +397,6 @@ sksl_shared_tests = [
"/sksl/shared/Structs.sksl",
"/sksl/shared/StructsInFunctions.sksl",
"/sksl/shared/StructMaxDepth.sksl",
"/sksl/shared/Switch.sksl",
"/sksl/shared/SwitchDefaultOnly.sksl",
"/sksl/shared/SwitchWithFallthrough.sksl",
"/sksl/shared/SwitchWithLoops.sksl",
"/sksl/shared/SwizzleBoolConstants.sksl",
"/sksl/shared/SwizzleByConstantIndex.sksl",
"/sksl/shared/SwizzleByIndex.sksl",
@ -523,6 +519,10 @@ sksl_settings_tests = [
"/sksl/inliner/ExponentialGrowth.sksl",
"/sksl/inliner/InlinerCanBeDisabled.sksl",
"/sksl/shared/Derivatives.sksl",
"/sksl/shared/Switch.sksl",
"/sksl/shared/SwitchDefaultOnly.sksl",
"/sksl/shared/SwitchWithFallthrough.sksl",
"/sksl/shared/SwitchWithLoops.sksl",
"/sksl/workarounds/AbsInt.sksl",
"/sksl/workarounds/BlendGuardedDivide.sksl",
"/sksl/workarounds/BlendModesAllZeroVec.sksl",

View File

@ -1,3 +1,5 @@
/*#pragma settings RewriteSwitchStatements*/
uniform half4 colorGreen, colorRed;
half4 main(float2 coords) {

View File

@ -1,3 +1,5 @@
/*#pragma settings RewriteSwitchStatements*/
uniform half4 colorGreen, colorRed;
half4 main(float2 coords) {

View File

@ -1,3 +1,5 @@
/*#pragma settings RewriteSwitchStatements*/
uniform half4 colorGreen, colorRed;
bool switch_fallthrough(int value) {

View File

@ -1,3 +1,5 @@
/*#pragma settings RewriteSwitchStatements*/
uniform half4 colorGreen, colorRed;
bool switch_with_break_in_loop(int x) {

View File

@ -1354,9 +1354,67 @@ void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
}
void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
if (fProgram.fConfig->strictES2Mode()) {
// TODO(skia:12450): write switch compatibility code
fContext.fErrors->error(s.fLine, "switch statements are not supported");
if (this->caps().rewriteSwitchStatements()) {
String fallthroughVar = "_tmpSwitchFallthrough" + to_string(fVarCount++);
String valueVar = "_tmpSwitchValue" + to_string(fVarCount++);
String loopVar = "_tmpSwitchLoop" + to_string(fVarCount++);
this->write("int ");
this->write(valueVar);
this->write(" = ");
this->writeExpression(*s.value(), Precedence::kAssignment);
this->write(", ");
this->write(fallthroughVar);
this->writeLine(" = 0;");
this->write("for (int ");
this->write(loopVar);
this->write(" = 0; ");
this->write(loopVar);
this->write(" < 1; ");
this->write(loopVar);
this->writeLine("++) {");
fIndentation++;
bool firstCase = true;
for (const std::unique_ptr<Statement>& stmt : s.cases()) {
const SwitchCase& c = stmt->as<SwitchCase>();
if (c.value()) {
this->write("if ((");
if (firstCase) {
firstCase = false;
} else {
this->write(fallthroughVar);
this->write(" > 0) || (");
}
this->write(valueVar);
this->write(" == ");
this->writeExpression(*c.value(), Precedence::kEquality);
this->writeLine(")) {");
fIndentation++;
// We write the entire case-block statement here, and then set `switchFallthrough`
// to 1. If the case-block had a break statement in it, we break out of the outer
// for-loop entirely, meaning the `switchFallthrough` assignment never occurs, nor
// does any code after it inside the switch. We've forbidden `continue` statements
// inside switch case-blocks entirely, so we don't need to consider their effect on
// control flow; see the Finalizer in FunctionDefinition::Convert.
this->writeStatement(*c.statement());
this->finishLine();
this->write(fallthroughVar);
this->write(" = 1;");
this->writeLine();
fIndentation--;
this->writeLine("}");
} else {
// This is the default case. Since it's always last, we can just dump in the code.
this->writeStatement(*c.statement());
this->finishLine();
}
}
fIndentation--;
this->writeLine("}");
return;
}
this->write("switch (");

View File

@ -323,10 +323,10 @@ SKSL_TEST(SkSLStaticIf, "shared/StaticIf.sksl")
SKSL_TEST_ES3(SkSLStaticSwitch, "shared/StaticSwitch.sksl")
SKSL_TEST(SkSLStructArrayFollowedByScalar, "shared/StructArrayFollowedByScalar.sksl")
SKSL_TEST(SkSLStructsInFunctions, "shared/StructsInFunctions.sksl")
SKSL_TEST_ES3(SkSLSwitch, "shared/Switch.sksl")
SKSL_TEST_ES3(SkSLSwitchDefaultOnly, "shared/SwitchDefaultOnly.sksl")
SKSL_TEST_ES3(SkSLSwitchWithFallthrough, "shared/SwitchWithFallthrough.sksl")
SKSL_TEST_ES3(SkSLSwitchWithLoops, "shared/SwitchWithLoops.sksl")
SKSL_TEST(SkSLSwitch, "shared/Switch.sksl")
SKSL_TEST(SkSLSwitchDefaultOnly, "shared/SwitchDefaultOnly.sksl")
SKSL_TEST(SkSLSwitchWithFallthrough, "shared/SwitchWithFallthrough.sksl")
SKSL_TEST(SkSLSwitchWithLoops, "shared/SwitchWithLoops.sksl")
SKSL_TEST(SkSLSwizzleBoolConstants, "shared/SwizzleBoolConstants.sksl")
SKSL_TEST(SkSLSwizzleByConstantIndex, "shared/SwizzleByConstantIndex.sksl")
SKSL_TEST(SkSLSwizzleConstants, "shared/SwizzleConstants.sksl")

View File

@ -1,19 +1,23 @@
#version 400
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
vec4 color;
switch (int(colorGreen.y)) {
case 0:
int _tmpSwitchValue1 = int(colorGreen.y), _tmpSwitchFallthrough0 = 0;
for (int _tmpSwitchLoop2 = 0; _tmpSwitchLoop2 < 1; _tmpSwitchLoop2++) {
if ((_tmpSwitchValue1 == 0)) {
color = colorRed;
break;
case 1:
_tmpSwitchFallthrough0 = 1;
}
if ((_tmpSwitchFallthrough0 > 0) || (_tmpSwitchValue1 == 1)) {
color = colorGreen;
break;
default:
color = colorRed;
break;
_tmpSwitchFallthrough0 = 1;
}
color = colorRed;
break;
}
return color;
}

View File

@ -1,11 +1,10 @@
#version 400
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
switch (int(colorGreen.y)) {
case 0:
default:
return colorGreen;
int _tmpSwitchValue1 = int(colorGreen.y), _tmpSwitchFallthrough0 = 0;
for (int _tmpSwitchLoop2 = 0; _tmpSwitchLoop2 < 1; _tmpSwitchLoop2++) {
return colorGreen;
}
}

View File

@ -0,0 +1,11 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
switch (int(colorGreen.y)) {
case 0:
default:
return colorGreen;
}
}

View File

@ -0,0 +1,19 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
vec4 main() {
vec4 color;
switch (int(colorGreen.y)) {
case 0:
color = colorRed;
break;
case 1:
color = colorGreen;
break;
default:
color = colorRed;
break;
}
return color;
}

View File

@ -1,34 +1,54 @@
#version 400
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
bool switch_fallthrough_twice_bi(int value) {
bool ok = false;
switch (value) {
case 0:
int _tmpSwitchValue1 = value, _tmpSwitchFallthrough0 = 0;
for (int _tmpSwitchLoop2 = 0; _tmpSwitchLoop2 < 1; _tmpSwitchLoop2++) {
if ((_tmpSwitchValue1 == 0)) {
break;
case 1:
case 2:
case 3:
_tmpSwitchFallthrough0 = 1;
}
if ((_tmpSwitchFallthrough0 > 0) || (_tmpSwitchValue1 == 1)) {
{
}
_tmpSwitchFallthrough0 = 1;
}
if ((_tmpSwitchFallthrough0 > 0) || (_tmpSwitchValue1 == 2)) {
{
}
_tmpSwitchFallthrough0 = 1;
}
if ((_tmpSwitchFallthrough0 > 0) || (_tmpSwitchValue1 == 3)) {
ok = true;
break;
default:
break;
_tmpSwitchFallthrough0 = 1;
}
break;
}
return ok;
}
vec4 main() {
int x = int(colorGreen.y);
bool _0_ok = false;
switch (x) {
case 2:
int _tmpSwitchValue4 = x, _tmpSwitchFallthrough3 = 0;
for (int _tmpSwitchLoop5 = 0; _tmpSwitchLoop5 < 1; _tmpSwitchLoop5++) {
if ((_tmpSwitchValue4 == 2)) {
break;
case 1:
case 0:
_tmpSwitchFallthrough3 = 1;
}
if ((_tmpSwitchFallthrough3 > 0) || (_tmpSwitchValue4 == 1)) {
{
}
_tmpSwitchFallthrough3 = 1;
}
if ((_tmpSwitchFallthrough3 > 0) || (_tmpSwitchValue4 == 0)) {
_0_ok = true;
break;
default:
break;
_tmpSwitchFallthrough3 = 1;
}
break;
}
return _0_ok && switch_fallthrough_twice_bi(x) ? colorGreen : colorRed;
}

View File

@ -0,0 +1,34 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
bool switch_fallthrough_twice_bi(int value) {
bool ok = false;
switch (value) {
case 0:
break;
case 1:
case 2:
case 3:
ok = true;
break;
default:
break;
}
return ok;
}
vec4 main() {
int x = int(colorGreen.y);
bool _0_ok = false;
switch (x) {
case 2:
break;
case 1:
case 0:
_0_ok = true;
break;
default:
break;
}
return _0_ok && switch_fallthrough_twice_bi(x) ? colorGreen : colorRed;
}

View File

@ -1,30 +1,34 @@
#version 400
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
bool switch_with_continue_in_loop_bi(int x) {
int val = 0;
switch (x) {
case 1:
int _tmpSwitchValue1 = x, _tmpSwitchFallthrough0 = 0;
for (int _tmpSwitchLoop2 = 0; _tmpSwitchLoop2 < 1; _tmpSwitchLoop2++) {
if ((_tmpSwitchValue1 == 1)) {
for (int i = 0;i < 10; ++i) {
++val;
continue;
++val;
}
default:
++val;
_tmpSwitchFallthrough0 = 1;
}
++val;
}
return val == 11;
}
bool loop_with_break_in_switch_bi(int x) {
int val = 0;
for (int i = 0;i < 10; ++i) {
switch (x) {
case 1:
int _tmpSwitchValue4 = x, _tmpSwitchFallthrough3 = 0;
for (int _tmpSwitchLoop5 = 0; _tmpSwitchLoop5 < 1; _tmpSwitchLoop5++) {
if ((_tmpSwitchValue4 == 1)) {
++val;
break;
default:
return false;
_tmpSwitchFallthrough3 = 1;
}
return false;
}
++val;
}
@ -33,15 +37,17 @@ bool loop_with_break_in_switch_bi(int x) {
vec4 main() {
int x = int(colorGreen.y);
int _0_val = 0;
switch (x) {
case 1:
int _tmpSwitchValue7 = x, _tmpSwitchFallthrough6 = 0;
for (int _tmpSwitchLoop8 = 0; _tmpSwitchLoop8 < 1; _tmpSwitchLoop8++) {
if ((_tmpSwitchValue7 == 1)) {
for (int _1_i = 0;_1_i < 10; ++_1_i) {
++_0_val;
break;
++_0_val;
}
default:
++_0_val;
_tmpSwitchFallthrough6 = 1;
}
++_0_val;
}
return (_0_val == 2 && switch_with_continue_in_loop_bi(x)) && loop_with_break_in_switch_bi(x) ? colorGreen : colorRed;
}

View File

@ -0,0 +1,47 @@
out vec4 sk_FragColor;
uniform vec4 colorGreen;
uniform vec4 colorRed;
bool switch_with_continue_in_loop_bi(int x) {
int val = 0;
switch (x) {
case 1:
for (int i = 0;i < 10; ++i) {
++val;
continue;
++val;
}
default:
++val;
}
return val == 11;
}
bool loop_with_break_in_switch_bi(int x) {
int val = 0;
for (int i = 0;i < 10; ++i) {
switch (x) {
case 1:
++val;
break;
default:
return false;
}
++val;
}
return val == 20;
}
vec4 main() {
int x = int(colorGreen.y);
int _0_val = 0;
switch (x) {
case 1:
for (int _1_i = 0;_1_i < 10; ++_1_i) {
++_0_val;
break;
++_0_val;
}
default:
++_0_val;
}
return (_0_val == 2 && switch_with_continue_in_loop_bi(x)) && loop_with_break_in_switch_bi(x) ? colorGreen : colorRed;
}