Add remove_pow_with_constant_exponent workaround

Bug: chromium: 477306, 829614
Change-Id: If88c57b15a4cfd6f362a2f5171f8e9c0775cb9d4
Reviewed-on: https://skia-review.googlesource.com/148480
Commit-Queue: Adrienne Walker <enne@chromium.org>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
Adrienne Walker 2018-08-22 16:04:57 -07:00 committed by Skia Commit-Bot
parent 8b23ca6406
commit 2f4c09b5ca
9 changed files with 62 additions and 0 deletions

View File

@ -28,6 +28,8 @@
max_texture_size_limit_4096) \
GPU_OP(PACK_PARAMETERS_WORKAROUND_WITH_PACK_BUFFER, \
pack_parameters_workaround_with_pack_buffer) \
GPU_OP(REMOVE_POW_WITH_CONSTANT_EXPONENT, \
remove_pow_with_constant_exponent) \
GPU_OP(RESTORE_SCISSOR_ON_FBO_CHANGE, \
restore_scissor_on_fbo_change) \
GPU_OP(REWRITE_DO_WHILE_LOOPS, \

View File

@ -42,6 +42,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fUnfoldShortCircuitAsTernary = false;
fEmulateAbsIntFunction = false;
fRewriteDoWhileLoops = false;
fRemovePowWithConstantExponent = false;
fFlatInterpolationSupport = false;
fPreferFlatInterpolation = false;
fNoPerspectiveInterpolationSupport = false;
@ -112,6 +113,7 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Unfold short circuit as ternary", fUnfoldShortCircuitAsTernary);
writer->appendBool("Emulate abs(int) function", fEmulateAbsIntFunction);
writer->appendBool("Rewrite do while loops", fRewriteDoWhileLoops);
writer->appendBool("Rewrite pow with constant exponent", fRemovePowWithConstantExponent);
writer->appendBool("Flat interpolation support", fFlatInterpolationSupport);
writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation);
writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport);
@ -148,6 +150,7 @@ void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
SkASSERT(!fUnfoldShortCircuitAsTernary);
SkASSERT(!fEmulateAbsIntFunction);
SkASSERT(!fRewriteDoWhileLoops);
SkASSERT(!fRemovePowWithConstantExponent);
}
#if GR_TEST_UTILS
fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;

View File

@ -135,6 +135,8 @@ public:
bool rewriteDoWhileLoops() const { return fRewriteDoWhileLoops; }
bool removePowWithConstantExponent() const { return fRemovePowWithConstantExponent; }
bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
@ -274,6 +276,7 @@ private:
bool fUnfoldShortCircuitAsTernary : 1;
bool fEmulateAbsIntFunction : 1;
bool fRewriteDoWhileLoops : 1;
bool fRemovePowWithConstantExponent : 1;
const char* fVersionDeclString;

View File

@ -2585,6 +2585,10 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
shaderCaps->fRewriteDoWhileLoops = true;
}
if (fDriverBugWorkarounds.remove_pow_with_constant_exponent) {
shaderCaps->fRemovePowWithConstantExponent = 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

@ -9,6 +9,7 @@ max_fragment_uniform_vectors_32
max_msaa_sample_count_4
max_texture_size_limit_4096
pack_parameters_workaround_with_pack_buffer
remove_pow_with_constant_exponent
restore_scissor_on_fbo_change
rewrite_do_while_loops
unbind_attachments_on_bound_render_fbo_delete

View File

@ -470,6 +470,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
(*fFunctionClasses)["inverse"] = FunctionClass::kInverse;
(*fFunctionClasses)["inverseSqrt"] = FunctionClass::kInverseSqrt;
(*fFunctionClasses)["min"] = FunctionClass::kMin;
(*fFunctionClasses)["pow"] = FunctionClass::kPow;
(*fFunctionClasses)["saturate"] = FunctionClass::kSaturate;
(*fFunctionClasses)["texture"] = FunctionClass::kTexture;
(*fFunctionClasses)["transpose"] = FunctionClass::kTranspose;
@ -573,6 +574,21 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
}
}
break;
case FunctionClass::kPow:
if (!fProgram.fSettings.fCaps->removePowWithConstantExponent()) {
break;
}
// pow(x, y) on some NVIDIA drivers causes crashes if y is a
// constant. It's hard to tell what constitutes "constant" here
// so just replace in all cases.
// Change pow(x, y) into exp2(y * log2(x))
this->write("exp2(");
this->writeExpression(*c.fArguments[1], kMultiplicative_Precedence);
this->write(" * log2(");
this->writeExpression(*c.fArguments[0], kSequence_Precedence);
this->write("))");
return;
case FunctionClass::kSaturate:
SkASSERT(c.fArguments.size() == 1);
this->write("clamp(");

View File

@ -231,6 +231,7 @@ protected:
kInverse,
kInverseSqrt,
kMin,
kPow,
kSaturate,
kTexture,
kTranspose

View File

@ -193,6 +193,10 @@ public:
return false;
}
bool removePowWithConstantExponent() const {
return false;
}
const char* fbFetchColorName() const {
return nullptr;
}
@ -364,6 +368,13 @@ public:
result->fRewriteDoWhileLoops = true;
return result;
}
static sk_sp<GrShaderCaps> RemovePowWithConstantExponent() {
sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
result->fVersionDeclString = "#version 400";
result->fRemovePowWithConstantExponent = true;
return result;
}
};
#endif

View File

@ -2094,3 +2094,24 @@ DEF_TEST(SkSLWorkaroundRewriteDoWhileLoops, r) {
SkSL::Program::kFragment_Kind
);
}
DEF_TEST(SkSLWorkaroundRemovePowWithConstantExponent, r) {
test(r,
"uniform float x;"
"uniform float y;"
"void main() {"
" float z = pow(x + 1.0, y + 2.0);"
" sk_FragColor = float4(z);"
"}",
*SkSL::ShaderCapsFactory::RemovePowWithConstantExponent(),
"#version 400\n"
"out vec4 sk_FragColor;\n"
"uniform float x;\n"
"uniform float y;\n"
"void main() {\n"
" float z = exp2((y + 2.0) * log2(x + 1.0));\n"
" sk_FragColor = vec4(z);\n"
"}\n",
SkSL::Program::kFragment_Kind
);
}