Add rewrite_do_while_loops workaround

Bug: chromium: 644669, 829614
Change-Id: Ic6a4cbd9f7c73b9b9a78608f1b4ac4ce4c4f2cb9
Reviewed-on: https://skia-review.googlesource.com/148439
Commit-Queue: Adrienne Walker <enne@chromium.org>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Adrienne Walker 2018-08-22 10:45:41 -07:00 committed by Skia Commit-Bot
parent 9b7e99e394
commit 8b23ca6406
8 changed files with 120 additions and 4 deletions

View File

@ -30,6 +30,8 @@
pack_parameters_workaround_with_pack_buffer) \
GPU_OP(RESTORE_SCISSOR_ON_FBO_CHANGE, \
restore_scissor_on_fbo_change) \
GPU_OP(REWRITE_DO_WHILE_LOOPS, \
rewrite_do_while_loops) \
GPU_OP(UNBIND_ATTACHMENTS_ON_BOUND_RENDER_FBO_DELETE, \
unbind_attachments_on_bound_render_fbo_delete) \
GPU_OP(UNFOLD_SHORT_CIRCUIT_AS_TERNARY_OPERATION, \

View File

@ -41,6 +41,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fAddAndTrueToLoopCondition = false;
fUnfoldShortCircuitAsTernary = false;
fEmulateAbsIntFunction = false;
fRewriteDoWhileLoops = false;
fFlatInterpolationSupport = false;
fPreferFlatInterpolation = false;
fNoPerspectiveInterpolationSupport = false;
@ -110,6 +111,7 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Add and true to loops workaround", fAddAndTrueToLoopCondition);
writer->appendBool("Unfold short circuit as ternary", fUnfoldShortCircuitAsTernary);
writer->appendBool("Emulate abs(int) function", fEmulateAbsIntFunction);
writer->appendBool("Rewrite do while loops", fRewriteDoWhileLoops);
writer->appendBool("Flat interpolation support", fFlatInterpolationSupport);
writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation);
writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport);
@ -145,6 +147,7 @@ void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
SkASSERT(!fAddAndTrueToLoopCondition);
SkASSERT(!fUnfoldShortCircuitAsTernary);
SkASSERT(!fEmulateAbsIntFunction);
SkASSERT(!fRewriteDoWhileLoops);
}
#if GR_TEST_UTILS
fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;

View File

@ -133,6 +133,8 @@ public:
bool emulateAbsIntFunction() const { return fEmulateAbsIntFunction; }
bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
@ -271,6 +273,7 @@ private:
bool fAddAndTrueToLoopCondition : 1;
bool fUnfoldShortCircuitAsTernary : 1;
bool fEmulateAbsIntFunction : 1;
bool fRewriteDoWhileLoops : 1;
const char* fVersionDeclString;

View File

@ -2581,6 +2581,10 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
shaderCaps->fEmulateAbsIntFunction = true;
}
if (fDriverBugWorkarounds.rewrite_do_while_loops) {
shaderCaps->fRewriteDoWhileLoops = true;
}
// Disabling advanced blend on various platforms with major known issues. We also block Chrome
// for now until its own blacklists can be updated.
if (kAdreno430_GrGLRenderer == ctxInfo.renderer() ||

View File

@ -10,5 +10,6 @@ max_msaa_sample_count_4
max_texture_size_limit_4096
pack_parameters_workaround_with_pack_buffer
restore_scissor_on_fbo_change
rewrite_do_while_loops
unbind_attachments_on_bound_render_fbo_delete
unfold_short_circuit_as_ternary_operation

View File

@ -1334,11 +1334,56 @@ void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) {
}
void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
this->write("do ");
if (!fProgram.fSettings.fCaps->rewriteDoWhileLoops()) {
this->write("do ");
this->writeStatement(*d.fStatement);
this->write(" while (");
this->writeExpression(*d.fTest, kTopLevel_Precedence);
this->write(");");
return;
}
// Otherwise, do the do while loop workaround, to rewrite loops of the form:
// do {
// CODE;
// } while (CONDITION)
//
// to loops of the form
// bool temp = false;
// while (true) {
// if (temp) {
// if (!CONDITION) {
// break;
// }
// }
// temp = true;
// CODE;
// }
String tmpVar = "_tmpLoopSeenOnce" + to_string(fVarCount++);
this->write("bool ");
this->write(tmpVar);
this->writeLine(" = false;");
this->writeLine("while (true) {");
fIndentation++;
this->write("if (");
this->write(tmpVar);
this->writeLine(") {");
fIndentation++;
this->write("if (!");
this->writeExpression(*d.fTest, kPrefix_Precedence);
this->writeLine(") {");
fIndentation++;
this->writeLine("break;");
fIndentation--;
this->writeLine("}");
fIndentation--;
this->writeLine("}");
this->write(tmpVar);
this->writeLine(" = true;");
this->writeStatement(*d.fStatement);
this->write(" while (");
this->writeExpression(*d.fTest, kTopLevel_Precedence);
this->write(");");
this->writeLine();
fIndentation--;
this->write("}");
}
void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {

View File

@ -189,6 +189,10 @@ public:
return false;
}
bool rewriteDoWhileLoops() const {
return false;
}
const char* fbFetchColorName() const {
return nullptr;
}
@ -353,6 +357,13 @@ public:
result->fEmulateAbsIntFunction = true;
return result;
}
static sk_sp<GrShaderCaps> RewriteDoWhileLoops() {
sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
result->fVersionDeclString = "#version 400";
result->fRewriteDoWhileLoops = true;
return result;
}
};
#endif

View File

@ -2047,3 +2047,50 @@ DEF_TEST(SkSLWorkaroundEmulateAbsIntFunction, r) {
SkSL::Program::kFragment_Kind
);
}
DEF_TEST(SkSLWorkaroundRewriteDoWhileLoops, r) {
test(r,
"void main() {"
" int i = 0;"
" do {"
" ++i;"
" do {"
" i++;"
" } while (true);"
" } while (i < 10);"
" sk_FragColor = float4(i);"
"}",
*SkSL::ShaderCapsFactory::RewriteDoWhileLoops(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"void main() {\n"
" int i = 0;\n"
" bool _tmpLoopSeenOnce0 = false;\n"
" while (true) {\n"
" if (_tmpLoopSeenOnce0) {\n"
" if (!(i < 10)) {\n"
" break;\n"
" }\n"
" }\n"
" _tmpLoopSeenOnce0 = true;\n"
" {\n"
" ++i;\n"
" bool _tmpLoopSeenOnce1 = false;\n"
" while (true) {\n"
" if (_tmpLoopSeenOnce1) {\n"
" if (!true) {\n"
" break;\n"
" }\n"
" }\n"
" _tmpLoopSeenOnce1 = true;\n"
" {\n"
" i++;\n"
" }\n"
" }\n"
" }\n"
" }\n"
" sk_FragColor = vec4(float(i));\n"
"}\n",
SkSL::Program::kFragment_Kind
);
}