diff options
author | Brian Osman <brianosman@google.com> | 2017-08-01 14:46:18 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-08-01 19:07:55 +0000 |
commit | dff5d4368dde7f27870b30c3724a4acc702f879c (patch) | |
tree | 18eeba84268ffce495ae9c06e03c4c90b90a3892 /src | |
parent | 93061b53442ce303e9d3ef74c7eeddc034802c4f (diff) |
Guard against D3D NaN/Infinity literals bug
Bug: angle:2098 skia:6857
Change-Id: I502f05cdeb56514db4e144fdbb6d6f5a6f476b2e
Reviewed-on: https://skia-review.googlesource.com/29520
Reviewed-by: Yuqian Li <liyuqian@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrShaderCaps.cpp | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 18 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLBlend.cpp | 27 |
3 files changed, 41 insertions, 7 deletions
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp index 6f5dc7f0d7..7d34df9382 100644 --- a/src/gpu/GrShaderCaps.cpp +++ b/src/gpu/GrShaderCaps.cpp @@ -61,6 +61,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) { fRequiresLocalOutputColorForFBFetch = false; fMustImplementGSInvocationsWithLoop = false; fMustObfuscateUniformColor = false; + fMustGuardDivisionEvenAfterExplicitZeroCheck = false; fFlatInterpolationSupport = false; fNoPerspectiveInterpolationSupport = false; fMultisampleInterpolationSupport = false; @@ -149,6 +150,8 @@ SkString GrShaderCaps::dump() const { 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("Must guard division even after explicit zero check: %s\n", + (fMustGuardDivisionEvenAfterExplicitZeroCheck ? "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 6becba8207..6ca9d632ee 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -927,6 +927,24 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) { if (kMaliT_GrGLRenderer == ctxInfo.renderer()) { shaderCaps->fMustObfuscateUniformColor = true; } + +#ifdef SK_BUILD_FOR_WIN + // Check for ANGLE on Windows, so we can workaround a bug in D3D itself (anglebug.com/2098). + // + // Basically, if a shader has a construct like: + // + // float x = someCondition ? someValue : 0; + // float2 result = (0 == x) ? float2(x, x) + // : float2(2 * x / x, 0); + // + // ... the compiler will produce an error 'NaN and infinity literals not allowed', even though + // we've explicitly guarded the division with a check against zero. This manifests in much + // more complex ways in some of our shaders, so we use this caps bit to add an epsilon value + // to the denominator of divisions, even when we've added checks that the denominator isn't 0. + if (kANGLE_GrGLDriver == ctxInfo.driver() || kChromium_GrGLDriver == ctxInfo.driver()) { + shaderCaps->fMustGuardDivisionEvenAfterExplicitZeroCheck = true; + } +#endif } bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) { diff --git a/src/gpu/glsl/GrGLSLBlend.cpp b/src/gpu/glsl/GrGLSLBlend.cpp index b37169b3c5..9d7a064b81 100644 --- a/src/gpu/glsl/GrGLSLBlend.cpp +++ b/src/gpu/glsl/GrGLSLBlend.cpp @@ -7,6 +7,7 @@ #include "GrGLSLBlend.h" #include "glsl/GrGLSLFragmentShaderBuilder.h" +#include "glsl/GrGLSLProgramBuilder.h" #include "SkBlendModePriv.h" ////////////////////////////////////////////////////////////////////////////// @@ -39,6 +40,12 @@ static void color_dodge_component(GrGLSLFragmentBuilder* fsBuilder, const char* src, const char* dst, const char component) { + const char* divisorGuard = ""; + const GrShaderCaps* shaderCaps = fsBuilder->getProgramBuilder()->shaderCaps(); + if (shaderCaps->mustGuardDivisionEvenAfterExplicitZeroCheck()) { + divisorGuard = "+ 0.00000001"; + } + fsBuilder->codeAppendf("if (0.0 == %s.%c) {", dst, component); fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);", final, component, src, component, dst); @@ -49,8 +56,8 @@ static void color_dodge_component(GrGLSLFragmentBuilder* fsBuilder, final, component, src, dst, src, component, dst, dst, component, src); fsBuilder->codeAppend("} else {"); - fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / d);", - dst, dst, component, src); + fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / (d %s));", + dst, dst, component, src, divisorGuard); fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);", final, component, src, src, component, dst, dst, component, src); fsBuilder->codeAppend("}"); @@ -84,14 +91,20 @@ static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder, const char* src, const char* dst, const char component) { + const char* divisorGuard = ""; + const GrShaderCaps* shaderCaps = fsBuilder->getProgramBuilder()->shaderCaps(); + if (shaderCaps->mustGuardDivisionEvenAfterExplicitZeroCheck()) { + divisorGuard = "+ 0.00000001"; + } + // if (2S < Sa) fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src); // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) - fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a +" + fsBuilder->codeAppendf("%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / (%s.a %s) +" "(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);", final, component, dst, component, dst, component, src, src, - component, dst, dst, src, component, dst, component, src, src, - component); + component, dst, divisorGuard, dst, src, component, dst, component, src, + src, component); // else if (4D < Da) fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {", dst, component, dst); @@ -104,10 +117,10 @@ static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder, fsBuilder->codeAppendf("%s.%c =" "(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) +" " 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c) -" - " DaCub*%s.%c) / DaSqd;", + " DaCub*%s.%c) / (DaSqd %s);", final, component, src, component, dst, component, src, src, component, dst, src, src, component, src, src, - component, src, component); + component, src, component, divisorGuard); fsBuilder->codeAppendf("} else {"); // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S fsBuilder->codeAppendf("%s.%c = %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c -" |