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>
This commit is contained in:
parent
93061b5344
commit
dff5d4368d
@ -165,6 +165,12 @@ public:
|
|||||||
|
|
||||||
bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
|
bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
|
||||||
|
|
||||||
|
// The D3D shader compiler, when targeting PS 3.0 (ie within ANGLE) fails to compile certain
|
||||||
|
// constructs. See detailed comments in GrGLCaps.cpp.
|
||||||
|
bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
|
||||||
|
return fMustGuardDivisionEvenAfterExplicitZeroCheck;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the string of an extension that must be enabled in the shader to support
|
// 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
|
// derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
|
||||||
// this function, the caller should check that shaderDerivativeSupport exists.
|
// this function, the caller should check that shaderDerivativeSupport exists.
|
||||||
@ -295,6 +301,7 @@ private:
|
|||||||
bool fRequiresLocalOutputColorForFBFetch : 1;
|
bool fRequiresLocalOutputColorForFBFetch : 1;
|
||||||
bool fMustImplementGSInvocationsWithLoop : 1;
|
bool fMustImplementGSInvocationsWithLoop : 1;
|
||||||
bool fMustObfuscateUniformColor : 1;
|
bool fMustObfuscateUniformColor : 1;
|
||||||
|
bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
|
||||||
|
|
||||||
PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
|
PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
|
|||||||
fRequiresLocalOutputColorForFBFetch = false;
|
fRequiresLocalOutputColorForFBFetch = false;
|
||||||
fMustImplementGSInvocationsWithLoop = false;
|
fMustImplementGSInvocationsWithLoop = false;
|
||||||
fMustObfuscateUniformColor = false;
|
fMustObfuscateUniformColor = false;
|
||||||
|
fMustGuardDivisionEvenAfterExplicitZeroCheck = false;
|
||||||
fFlatInterpolationSupport = false;
|
fFlatInterpolationSupport = false;
|
||||||
fNoPerspectiveInterpolationSupport = false;
|
fNoPerspectiveInterpolationSupport = false;
|
||||||
fMultisampleInterpolationSupport = false;
|
fMultisampleInterpolationSupport = false;
|
||||||
@ -149,6 +150,8 @@ SkString GrShaderCaps::dump() const {
|
|||||||
r.appendf("Must implement geo shader invocations with loop : %s\n",
|
r.appendf("Must implement geo shader invocations with loop : %s\n",
|
||||||
(fMustImplementGSInvocationsWithLoop ? "YES" : "NO"));
|
(fMustImplementGSInvocationsWithLoop ? "YES" : "NO"));
|
||||||
r.appendf("Must obfuscate uniform color: %s\n", (fMustObfuscateUniformColor ? "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("Flat interpolation support: %s\n", (fFlatInterpolationSupport ? "YES" : "NO"));
|
||||||
r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ?
|
r.appendf("No perspective interpolation support: %s\n", (fNoPerspectiveInterpolationSupport ?
|
||||||
"YES" : "NO"));
|
"YES" : "NO"));
|
||||||
|
@ -927,6 +927,24 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo) {
|
|||||||
if (kMaliT_GrGLRenderer == ctxInfo.renderer()) {
|
if (kMaliT_GrGLRenderer == ctxInfo.renderer()) {
|
||||||
shaderCaps->fMustObfuscateUniformColor = true;
|
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) {
|
bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "GrGLSLBlend.h"
|
#include "GrGLSLBlend.h"
|
||||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||||
|
#include "glsl/GrGLSLProgramBuilder.h"
|
||||||
#include "SkBlendModePriv.h"
|
#include "SkBlendModePriv.h"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@ -39,6 +40,12 @@ static void color_dodge_component(GrGLSLFragmentBuilder* fsBuilder,
|
|||||||
const char* src,
|
const char* src,
|
||||||
const char* dst,
|
const char* dst,
|
||||||
const char component) {
|
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("if (0.0 == %s.%c) {", dst, component);
|
||||||
fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
|
fsBuilder->codeAppendf("%s.%c = %s.%c * (1.0 - %s.a);",
|
||||||
final, component, src, component, dst);
|
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,
|
final, component, src, dst, src, component, dst, dst, component,
|
||||||
src);
|
src);
|
||||||
fsBuilder->codeAppend("} else {");
|
fsBuilder->codeAppend("} else {");
|
||||||
fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / d);",
|
fsBuilder->codeAppendf("d = min(%s.a, %s.%c * %s.a / (d %s));",
|
||||||
dst, dst, component, src);
|
dst, dst, component, src, divisorGuard);
|
||||||
fsBuilder->codeAppendf("%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);",
|
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);
|
final, component, src, src, component, dst, dst, component, src);
|
||||||
fsBuilder->codeAppend("}");
|
fsBuilder->codeAppend("}");
|
||||||
@ -84,14 +91,20 @@ static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder,
|
|||||||
const char* src,
|
const char* src,
|
||||||
const char* dst,
|
const char* dst,
|
||||||
const char component) {
|
const char component) {
|
||||||
|
const char* divisorGuard = "";
|
||||||
|
const GrShaderCaps* shaderCaps = fsBuilder->getProgramBuilder()->shaderCaps();
|
||||||
|
if (shaderCaps->mustGuardDivisionEvenAfterExplicitZeroCheck()) {
|
||||||
|
divisorGuard = "+ 0.00000001";
|
||||||
|
}
|
||||||
|
|
||||||
// if (2S < Sa)
|
// if (2S < Sa)
|
||||||
fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src);
|
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)
|
// (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);",
|
"(1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);",
|
||||||
final, component, dst, component, dst, component, src, src,
|
final, component, dst, component, dst, component, src, src,
|
||||||
component, dst, dst, src, component, dst, component, src, src,
|
component, dst, divisorGuard, dst, src, component, dst, component, src,
|
||||||
component);
|
src, component);
|
||||||
// else if (4D < Da)
|
// else if (4D < Da)
|
||||||
fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {",
|
fsBuilder->codeAppendf("} else if (4.0 * %s.%c <= %s.a) {",
|
||||||
dst, component, dst);
|
dst, component, dst);
|
||||||
@ -104,10 +117,10 @@ static void soft_light_component_pos_dst_alpha(GrGLSLFragmentBuilder* fsBuilder,
|
|||||||
fsBuilder->codeAppendf("%s.%c ="
|
fsBuilder->codeAppendf("%s.%c ="
|
||||||
"(DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) +"
|
"(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) -"
|
" 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,
|
final, component, src, component, dst, component,
|
||||||
src, src, component, dst, src, src, component, src, src,
|
src, src, component, dst, src, src, component, src, src,
|
||||||
component, src, component);
|
component, src, component, divisorGuard);
|
||||||
fsBuilder->codeAppendf("} else {");
|
fsBuilder->codeAppendf("} else {");
|
||||||
// -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
|
// -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 -"
|
fsBuilder->codeAppendf("%s.%c = %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c -"
|
||||||
|
Loading…
Reference in New Issue
Block a user