Add a workaround for inaccurate interpolants on Adreno 3xx.
Also ensure that sk_FragCoord x and y values are at pixel centers when workaround is used. Change-Id: Ib748af9e496a406a50622e00e96e1346cbb5eb26 Reviewed-on: https://skia-review.googlesource.com/97064 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
5081eede67
commit
dba65f95e4
@ -124,6 +124,9 @@ 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; }
|
||||
|
||||
bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
|
||||
|
||||
bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
|
||||
@ -279,6 +282,7 @@ private:
|
||||
bool fMustObfuscateUniformColor : 1;
|
||||
bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
|
||||
bool fCanUseFragCoord : 1;
|
||||
bool fInterpolantsAreInaccurate : 1;
|
||||
|
||||
const char* fVersionDeclString;
|
||||
|
||||
|
@ -39,6 +39,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
|
||||
fMustObfuscateUniformColor = false;
|
||||
fMustGuardDivisionEvenAfterExplicitZeroCheck = false;
|
||||
fCanUseFragCoord = true;
|
||||
fInterpolantsAreInaccurate = false;
|
||||
fFlatInterpolationSupport = false;
|
||||
fPreferFlatInterpolation = false;
|
||||
fNoPerspectiveInterpolationSupport = false;
|
||||
@ -115,6 +116,7 @@ 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("Flat interpolation support", fFlatInterpolationSupport);
|
||||
writer->appendBool("Prefer flat interpolation", fPreferFlatInterpolation);
|
||||
writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport);
|
||||
|
@ -1045,9 +1045,11 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
|
||||
#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 drviers.
|
||||
// (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.
|
||||
if (kAdreno3xx_GrGLRenderer == ctxInfo.renderer()) {
|
||||
shaderCaps->fCanUseFragCoord = false;
|
||||
shaderCaps->fInterpolantsAreInaccurate = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,6 +168,11 @@ public:
|
||||
}
|
||||
args.fFragBuilder->codeAppend(";");
|
||||
if (textureGP.usesCoverageEdgeAA()) {
|
||||
const char* aaDistName = nullptr;
|
||||
// When interpolation is innacurate 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);
|
||||
args.fVaryingHandler->addVarying("aaDists", &aaDistVarying);
|
||||
@ -179,11 +184,35 @@ public:
|
||||
aaDistVarying.vsOut(), textureGP.fPositions.fName,
|
||||
textureGP.fPositions.fName, textureGP.fPositions.fName,
|
||||
textureGP.fPositions.fName);
|
||||
|
||||
aaDistName = aaDistVarying.fsIn();
|
||||
} 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]);
|
||||
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.fFragBuilder->codeAppendf(
|
||||
"float mindist = min(min(%s.x, %s.y), min(%s.z, %s.w));",
|
||||
aaDistVarying.fsIn(), aaDistVarying.fsIn(), aaDistVarying.fsIn(),
|
||||
aaDistVarying.fsIn());
|
||||
aaDistName, aaDistName, aaDistName, aaDistName);
|
||||
args.fFragBuilder->codeAppendf("%s = float4(clamp(mindist, 0, 1));",
|
||||
args.fOutputCoverage);
|
||||
} else {
|
||||
|
@ -598,8 +598,19 @@ void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parent
|
||||
|
||||
void GLSLCodeGenerator::writeFragCoord() {
|
||||
if (!fProgram.fSettings.fCaps->canUseFragCoord()) {
|
||||
this->write("vec4(sk_FragCoord_Workaround.xyz / sk_FragCoord_Workaround.w, "
|
||||
"1.0 / sk_FragCoord_Workaround.w)");
|
||||
if (!fSetupFragCoordWorkaround) {
|
||||
const char* precision = usesPrecisionModifiers() ? "highp " : "";
|
||||
fFunctionHeader += precision;
|
||||
fFunctionHeader += " float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n";
|
||||
fFunctionHeader += precision;
|
||||
fFunctionHeader += " vec4 sk_FragCoord_Resolved = "
|
||||
"vec4(sk_FragCoord_Workaround.xyz * sk_FragCoord_InvW, sk_FragCoord_InvW);\n";
|
||||
// Ensure that we get exact .5 values for x and y.
|
||||
fFunctionHeader += " sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + "
|
||||
"vec2(.5);\n";
|
||||
fSetupFragCoordWorkaround = true;
|
||||
}
|
||||
this->write("sk_FragCoord_Resolved");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -212,6 +212,7 @@ protected:
|
||||
bool fFoundGSInvocations = false;
|
||||
bool fSetupFragPositionGlobal = false;
|
||||
bool fSetupFragPositionLocal = false;
|
||||
bool fSetupFragCoordWorkaround = false;
|
||||
|
||||
typedef CodeGenerator INHERITED;
|
||||
};
|
||||
|
@ -1093,8 +1093,11 @@ DEF_TEST(SkSLFragCoord, r) {
|
||||
"in vec4 sk_FragCoord_Workaround;\n"
|
||||
"out vec4 sk_FragColor;\n"
|
||||
"void main() {\n"
|
||||
" sk_FragColor.xy = vec4(sk_FragCoord_Workaround.xyz / sk_FragCoord_Workaround.w, "
|
||||
"1.0 / sk_FragCoord_Workaround.w).xy;\n"
|
||||
" float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n"
|
||||
" vec4 sk_FragCoord_Resolved = vec4(sk_FragCoord_Workaround.xyz * "
|
||||
"sk_FragCoord_InvW, sk_FragCoord_InvW);\n"
|
||||
" sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + vec2(.5);\n"
|
||||
" sk_FragColor.xy = sk_FragCoord_Resolved.xy;\n"
|
||||
"}\n");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user