diff options
author | Brian Osman <brianosman@google.com> | 2017-05-25 11:34:38 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-25 16:15:07 +0000 |
commit | ac1e4964e7816de1f4977b52fa5f2f372537468b (patch) | |
tree | aebc6f877d48d956f72908b6cd27fd290502e156 | |
parent | 3fdd0bf2d90b1b82c1ac3aa982bdca600de7f4a8 (diff) |
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>
-rw-r--r-- | include/gpu/GrShaderCaps.h | 3 | ||||
-rw-r--r-- | src/gpu/GrShaderCaps.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 10 | ||||
-rw-r--r-- | src/gpu/gl/GrGLUtil.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLUtil.h | 2 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp | 4 |
6 files changed, 25 insertions, 0 deletions
diff --git a/include/gpu/GrShaderCaps.h b/include/gpu/GrShaderCaps.h index e52bcf1c81..e5edc7ebea 100644 --- a/include/gpu/GrShaderCaps.h +++ b/include/gpu/GrShaderCaps.h @@ -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]; diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp index 9a429bb0de..cf29ab5976 100644 --- a/src/gpu/GrShaderCaps.cpp +++ b/src/gpu/GrShaderCaps.cpp @@ -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")); diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index 9164de7539..0d1d4f6fff 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -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) { diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp index 58b5860f13..41c57eb1e1 100644 --- a/src/gpu/gl/GrGLUtil.cpp +++ b/src/gpu/gl/GrGLUtil.cpp @@ -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; } diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h index 25bd68175b..261a4cd22d 100644 --- a/src/gpu/gl/GrGLUtil.h +++ b/src/gpu/gl/GrGLUtil.h @@ -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 }; diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp index f39fff2a07..d32766c3fc 100644 --- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp +++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp @@ -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); + } } ////////////////////////////////////////////////////////////////////////////// |