Remove interpolants are inaccurate workaround for Adreno 3xx.

The chrome screenshot unit test that led to adding this workaround has
been adjusted to avoid testing AA edges of rendered rectangles. We're
accepting the inaccuracy in favor of increased performance.

Chrome change: https://chromium-review.googlesource.com/c/chromium/src/+/1129041

Bug: chromium:847984
Change-Id: I9b714ade2a67e956ebb2773ebe3b8632dc3a50c6
Reviewed-on: https://skia-review.googlesource.com/140180
Commit-Queue: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Salomon 2018-07-10 09:23:40 -04:00 committed by Skia Commit-Bot
parent e4db80f1a6
commit a7a278205b
4 changed files with 28 additions and 68 deletions

View File

@ -38,7 +38,6 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fMustObfuscateUniformColor = false;
fMustGuardDivisionEvenAfterExplicitZeroCheck = false;
fCanUseFragCoord = true;
fInterpolantsAreInaccurate = false;
fIncompleteShortIntPrecision = false;
fFlatInterpolationSupport = false;
fPreferFlatInterpolation = false;
@ -112,7 +111,6 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Must guard division even after explicit zero check",
fMustGuardDivisionEvenAfterExplicitZeroCheck);
writer->appendBool("Can use gl_FragCoord", fCanUseFragCoord);
writer->appendBool("Interpolants are inaccurate", fInterpolantsAreInaccurate);
writer->appendBool("Incomplete short int precision", fIncompleteShortIntPrecision);
writer->appendBool("Flat interpolation support", fFlatInterpolationSupport);
writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation);
@ -148,7 +146,6 @@ void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
SkASSERT(!fMustObfuscateUniformColor);
SkASSERT(!fMustGuardDivisionEvenAfterExplicitZeroCheck);
SkASSERT(fCanUseFragCoord);
SkASSERT(!fInterpolantsAreInaccurate);
SkASSERT(!fIncompleteShortIntPrecision);
}
#if GR_TEST_UTILS

View File

@ -121,9 +121,6 @@ public:
// If false, SkSL uses a workaround so that sk_FragCoord doesn't actually query gl_FragCoord
bool canUseFragCoord() const { return fCanUseFragCoord; }
// If true interpolated vertex shader outputs are inaccurate.
bool interpolantsAreInaccurate() const { return fInterpolantsAreInaccurate; }
// If true, short ints can't represent every integer in the 16-bit two's complement range as
// required by the spec. SKSL will always emit full ints.
bool incompleteShortIntPrecision() const { return fIncompleteShortIntPrecision; }
@ -277,7 +274,6 @@ private:
bool fMustObfuscateUniformColor : 1;
bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
bool fCanUseFragCoord : 1;
bool fInterpolantsAreInaccurate : 1;
bool fIncompleteShortIntPrecision : 1;
const char* fVersionDeclString;

View File

@ -2608,11 +2608,9 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
#endif
// We've seen Adreno 3xx devices produce incorrect (flipped) values for gl_FragCoord, in some
// (rare) situations. It's sporadic, and mostly on older drivers. It also seems to be the case
// that the interpolation of vertex shader outputs is quite inaccurate.
// (rare) situations. It's sporadic, and mostly on older drivers.
if (kAdreno3xx_GrGLRenderer == ctxInfo.renderer()) {
shaderCaps->fCanUseFragCoord = false;
shaderCaps->fInterpolantsAreInaccurate = true;
}
// gl_FragCoord has an incorrect subpixel offset on legacy Tegra hardware.

View File

@ -203,69 +203,38 @@ public:
}
args.fFragBuilder->codeAppend(";");
if (textureGP.usesCoverageEdgeAA()) {
const char* aaDistName = nullptr;
bool mulByFragCoordW = false;
// When interpolation is inaccurate we perform the evaluation of the edge
// equations in the fragment shader rather than interpolating values computed
// in the vertex shader.
if (!args.fShaderCaps->interpolantsAreInaccurate()) {
GrGLSLVarying aaDistVarying(kFloat4_GrSLType,
GrGLSLVarying::Scope::kVertToFrag);
if (kFloat3_GrVertexAttribType == textureGP.fPositions.type()) {
args.fVaryingHandler->addVarying("aaDists", &aaDistVarying);
// The distance from edge equation e to homogenous point p=sk_Position
// is e.x*p.x/p.wx + e.y*p.y/p.w + e.z. However, we want screen space
// interpolation of this distance. We can do this by multiplying the
// varying in the VS by p.w and then multiplying by sk_FragCoord.w in
// the FS. So we output e.x*p.x + e.y*p.y + e.z * p.w
args.fVertBuilder->codeAppendf(
R"(%s = float4(dot(aaEdge0, %s), dot(aaEdge1, %s),
dot(aaEdge2, %s), dot(aaEdge3, %s));)",
aaDistVarying.vsOut(), textureGP.fPositions.name(),
textureGP.fPositions.name(), textureGP.fPositions.name(),
textureGP.fPositions.name());
mulByFragCoordW = true;
} else {
args.fVaryingHandler->addVarying("aaDists", &aaDistVarying);
args.fVertBuilder->codeAppendf(
R"(%s = float4(dot(aaEdge0.xy, %s.xy) + aaEdge0.z,
dot(aaEdge1.xy, %s.xy) + aaEdge1.z,
dot(aaEdge2.xy, %s.xy) + aaEdge2.z,
dot(aaEdge3.xy, %s.xy) + aaEdge3.z);)",
aaDistVarying.vsOut(), textureGP.fPositions.name(),
textureGP.fPositions.name(), textureGP.fPositions.name(),
textureGP.fPositions.name());
}
aaDistName = aaDistVarying.fsIn();
GrGLSLVarying aaDistVarying(kFloat4_GrSLType,
GrGLSLVarying::Scope::kVertToFrag);
if (kFloat3_GrVertexAttribType == textureGP.fPositions.type()) {
args.fVaryingHandler->addVarying("aaDists", &aaDistVarying);
// The distance from edge equation e to homogenous point p=sk_Position
// is e.x*p.x/p.wx + e.y*p.y/p.w + e.z. However, we want screen space
// interpolation of this distance. We can do this by multiplying the
// varying in the VS by p.w and then multiplying by sk_FragCoord.w in
// the FS. So we output e.x*p.x + e.y*p.y + e.z * p.w
args.fVertBuilder->codeAppendf(
R"(%s = float4(dot(aaEdge0, %s), dot(aaEdge1, %s),
dot(aaEdge2, %s), dot(aaEdge3, %s));)",
aaDistVarying.vsOut(), textureGP.fPositions.name(),
textureGP.fPositions.name(), textureGP.fPositions.name(),
textureGP.fPositions.name());
mulByFragCoordW = true;
} else {
GrGLSLVarying aaEdgeVarying[4]{
{kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag},
{kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag},
{kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag},
{kFloat3_GrSLType, GrGLSLVarying::Scope::kVertToFrag}
};
for (int i = 0; i < 4; ++i) {
SkString name;
name.printf("aaEdge%d", i);
args.fVaryingHandler->addVarying(name.c_str(), &aaEdgeVarying[i],
Interpolation::kCanBeFlat);
args.fVertBuilder->codeAppendf(
"%s = aaEdge%d;", aaEdgeVarying[i].vsOut(), i);
}
args.fFragBuilder->codeAppendf(
R"(float4 aaDists = float4(dot(%s.xy, sk_FragCoord.xy) + %s.z,
dot(%s.xy, sk_FragCoord.xy) + %s.z,
dot(%s.xy, sk_FragCoord.xy) + %s.z,
dot(%s.xy, sk_FragCoord.xy) + %s.z);)",
aaEdgeVarying[0].fsIn(), aaEdgeVarying[0].fsIn(),
aaEdgeVarying[1].fsIn(), aaEdgeVarying[1].fsIn(),
aaEdgeVarying[2].fsIn(), aaEdgeVarying[2].fsIn(),
aaEdgeVarying[3].fsIn(), aaEdgeVarying[3].fsIn());
aaDistName = "aaDists";
args.fVaryingHandler->addVarying("aaDists", &aaDistVarying);
args.fVertBuilder->codeAppendf(
R"(%s = float4(dot(aaEdge0.xy, %s.xy) + aaEdge0.z,
dot(aaEdge1.xy, %s.xy) + aaEdge1.z,
dot(aaEdge2.xy, %s.xy) + aaEdge2.z,
dot(aaEdge3.xy, %s.xy) + aaEdge3.z);)",
aaDistVarying.vsOut(), textureGP.fPositions.name(),
textureGP.fPositions.name(), textureGP.fPositions.name(),
textureGP.fPositions.name());
}
args.fFragBuilder->codeAppendf(
"float mindist = min(min(%s.x, %s.y), min(%s.z, %s.w));",
aaDistName, aaDistName, aaDistName, aaDistName);
aaDistVarying.fsIn(), aaDistVarying.fsIn(), aaDistVarying.fsIn(),
aaDistVarying.fsIn());
if (mulByFragCoordW) {
args.fFragBuilder->codeAppend("mindist *= sk_FragCoord.w;");
}