Workaround Mali static analysis bug

Comment describes it: Unless we do something to confuse their optimizer,
they will (incorrectly) deduce that uniform opaque color (modulated only
by a texture fetch) is always going to remain opaque. Then they skip
inserting their shader based blending code, turning SrcOver into Src.

Doing a max against zero is enough to squelch the optimization.

Bug: skia:
Change-Id: I74676cebb0b0c8d121da868dd8a88050e0cfcc0d
Reviewed-on: https://skia-review.googlesource.com/17924
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2017-05-25 11:34:38 -04:00 committed by Skia Commit-Bot
parent 3fdd0bf2d9
commit ac1e4964e7
6 changed files with 25 additions and 0 deletions

View File

@ -161,6 +161,8 @@ public:
// On MacBook, geometry shaders break if they have more than one invocation.
bool mustImplementGSInvocationsWithLoop() const { return fMustImplementGSInvocationsWithLoop; }
bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
// Returns the string of an extension that must be enabled in the shader to support
// derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
// this function, the caller should check that shaderDerivativeSupport exists.
@ -289,6 +291,7 @@ private:
bool fAtan2ImplementedAsAtanYOverX : 1;
bool fRequiresLocalOutputColorForFBFetch : 1;
bool fMustImplementGSInvocationsWithLoop : 1;
bool fMustObfuscateUniformColor : 1;
PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];

View File

@ -60,6 +60,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fAtan2ImplementedAsAtanYOverX = false;
fRequiresLocalOutputColorForFBFetch = false;
fMustImplementGSInvocationsWithLoop = false;
fMustObfuscateUniformColor = false;
fFlatInterpolationSupport = false;
fNoPerspectiveInterpolationSupport = false;
fMultisampleInterpolationSupport = false;
@ -146,6 +147,7 @@ SkString GrShaderCaps::dump() const {
"YES" : "NO"));
r.appendf("Must implement geo shader invocations with loop : %s\n",
(fMustImplementGSInvocationsWithLoop ? "YES" : "NO"));
r.appendf("Must obfuscate uniform color: %s\n", (fMustObfuscateUniformColor ? "YES" : "NO"));
r.appendf("Flat interpolation support: %s\n", (fFlatInterpolationSupport ? "YES" : "NO"));
r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ?
"YES" : "NO"));

View File

@ -876,6 +876,16 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
// term plan for this WAR is for it to eventually be baked into SkSL.
shaderCaps->fMustImplementGSInvocationsWithLoop = true;
#endif
// Newer Mali GPUs do incorrect static analysis in specific situations: If there is uniform
// color, and that uniform contains an opaque color, and the output of the shader is only based
// on that uniform plus soemthing un-trackable (like a texture read), the compiler will deduce
// that the shader always outputs opaque values. In that case, it appears to remove the shader
// based blending code it normally injects, turning SrcOver into Src. To fix this, we always
// insert an extra bit of math on the uniform that confuses the compiler just enough...
if (kMaliT_GrGLRenderer == ctxInfo.renderer()) {
shaderCaps->fMustObfuscateUniformColor = true;
}
}
bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {

View File

@ -326,6 +326,10 @@ GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
if (0 == strcmp("Mesa Offscreen", rendererString)) {
return kOSMesa_GrGLRenderer;
}
static const char kMaliTStr[] = "Mali-T";
if (0 == strncmp(rendererString, kMaliTStr, SK_ARRAY_COUNT(kMaliTStr) - 1)) {
return kMaliT_GrGLRenderer;
}
}
return kOther_GrGLRenderer;
}

View File

@ -56,6 +56,8 @@ enum GrGLRenderer {
kOSMesa_GrGLRenderer,
/** Either HD 6xxx or Iris 6xxx */
kIntel6xxx_GrGLRenderer,
/** T-6xx, T-7xx, or T-8xx */
kMaliT_GrGLRenderer,
kOther_GrGLRenderer
};

View File

@ -9,6 +9,7 @@
#include "GrCoordTransform.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLUniformHandler.h"
#include "glsl/GrGLSLVertexShaderBuilder.h"
@ -46,6 +47,9 @@ void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLPPFragmentBuilder* fragBu
"Color",
&stagedLocalVarName);
fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
if (fragBuilder->getProgramBuilder()->shaderCaps()->mustObfuscateUniformColor()) {
fragBuilder->codeAppendf("%s = max(%s, vec4(0, 0, 0, 0));", outputName, outputName);
}
}
//////////////////////////////////////////////////////////////////////////////