Add a shader cap for incomplete short int precision

Bug: skia:
Change-Id: Iac36eb763e687f6ecc3acbd4afced66f95596be2
Reviewed-on: https://skia-review.googlesource.com/109003
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2018-03-07 07:46:10 -07:00 committed by Skia Commit-Bot
parent c4f4904091
commit c2d0dd658b
6 changed files with 73 additions and 2 deletions

View File

@ -119,6 +119,10 @@ public:
// 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; }
bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }
bool mustObfuscateUniformColor() const { return fMustObfuscateUniformColor; }
@ -261,6 +265,7 @@ private:
bool fMustGuardDivisionEvenAfterExplicitZeroCheck : 1;
bool fCanUseFragCoord : 1;
bool fInterpolantsAreInaccurate : 1;
bool fIncompleteShortIntPrecision : 1;
const char* fVersionDeclString;

View File

@ -39,6 +39,7 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fMustGuardDivisionEvenAfterExplicitZeroCheck = false;
fCanUseFragCoord = true;
fInterpolantsAreInaccurate = false;
fIncompleteShortIntPrecision = false;
fFlatInterpolationSupport = false;
fPreferFlatInterpolation = false;
fNoPerspectiveInterpolationSupport = false;
@ -110,6 +111,7 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
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);
writer->appendBool("No perspective interpolation support", fNoPerspectiveInterpolationSupport);
@ -144,6 +146,7 @@ void GrShaderCaps::applyOptionsOverrides(const GrContextOptions& options) {
SkASSERT(!fMustGuardDivisionEvenAfterExplicitZeroCheck);
SkASSERT(fCanUseFragCoord);
SkASSERT(!fInterpolantsAreInaccurate);
SkASSERT(!fIncompleteShortIntPrecision);
}
#if GR_TEST_UTILS
fDualSourceBlendingSupport = fDualSourceBlendingSupport && !options.fSuppressDualSourceBlending;

View File

@ -2371,6 +2371,12 @@ void GrGLCaps::applyDriverCorrectnessWorkarounds(const GrGLContextInfo& ctxInfo,
shaderCaps->fInterpolantsAreInaccurate = true;
}
// On Mali G71, mediump ints don't appear capable of representing every integer beyond +/-2048.
// (Are they implemented with fp16?)
if (kARM_GrGLVendor == ctxInfo.vendor()) {
shaderCaps->fIncompleteShortIntPrecision = true;
}
// Disabling advanced blend on various platforms with major known issues. We also block Chrome
// for now until its own blacklists can be updated.
if (kAdreno4xx_GrGLRenderer == ctxInfo.renderer() ||

View File

@ -1015,8 +1015,14 @@ const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
if (usesPrecisionModifiers()) {
switch (type.kind()) {
case Type::kScalar_Kind:
if (type == *fContext.fHalf_Type || type == *fContext.fShort_Type ||
type == *fContext.fUShort_Type) {
if (type == *fContext.fShort_Type || type == *fContext.fUShort_Type) {
if (fProgram.fSettings.fForceHighPrecision ||
fProgram.fSettings.fCaps->incompleteShortIntPrecision()) {
return "highp ";
}
return "mediump ";
}
if (type == *fContext.fHalf_Type) {
return fProgram.fSettings.fForceHighPrecision ? "highp " : "mediump ";
}
if (type == *fContext.fFloat_Type || type == *fContext.fInt_Type ||

View File

@ -299,6 +299,14 @@ public:
result->fCanUseFragCoord = false;
return result;
}
static sk_sp<GrShaderCaps> IncompleteShortIntPrecision() {
sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
result->fVersionDeclString = "#version 310es";
result->fUsesPrecisionModifiers = true;
result->fIncompleteShortIntPrecision = true;
return result;
}
};
#endif

View File

@ -1902,4 +1902,47 @@ DEF_TEST(SkSLTernaryLValue, r) {
"}\n");
}
DEF_TEST(SkSLIncompleteShortIntPrecision, r) {
test(r,
"uniform sampler2D tex;"
"in float2 texcoord;"
"in short2 offset;"
"void main() {"
" short scalar = offset.y;"
" sk_FragColor = texture(tex, texcoord + float2(offset * scalar));"
"}",
*SkSL::ShaderCapsFactory::UsesPrecisionModifiers(),
"#version 400\n"
"precision mediump float;\n"
"out mediump vec4 sk_FragColor;\n"
"uniform sampler2D tex;\n"
"in highp vec2 texcoord;\n"
"in mediump ivec2 offset;\n"
"void main() {\n"
" mediump int scalar = offset.y;\n"
" sk_FragColor = texture(tex, texcoord + vec2(offset * scalar));\n"
"}\n",
SkSL::Program::kFragment_Kind);
test(r,
"uniform sampler2D tex;"
"in float2 texcoord;"
"in short2 offset;"
"void main() {"
" short scalar = offset.y;"
" sk_FragColor = texture(tex, texcoord + float2(offset * scalar));"
"}",
*SkSL::ShaderCapsFactory::IncompleteShortIntPrecision(),
"#version 310es\n"
"precision mediump float;\n"
"out mediump vec4 sk_FragColor;\n"
"uniform sampler2D tex;\n"
"in highp vec2 texcoord;\n"
"in highp ivec2 offset;\n"
"void main() {\n"
" highp int scalar = offset.y;\n"
" sk_FragColor = texture(tex, texcoord + vec2(offset * scalar));\n"
"}\n",
SkSL::Program::kFragment_Kind);
}
#endif