sksl: Polyfill fma() when not present in GLSL

Bug: skia:
Change-Id: Ibaf57ac2feb786ed45b42e5cb23d231a2204fb23
Reviewed-on: https://skia-review.googlesource.com/c/171420
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
This commit is contained in:
Chris Dalton 2018-11-16 09:33:43 -05:00 committed by Skia Commit-Bot
parent b3d2760e2f
commit a708618f2c
5 changed files with 30 additions and 0 deletions

View File

@ -51,6 +51,8 @@ GrShaderCaps::GrShaderCaps(const GrContextOptions& options) {
fFPManipulationSupport = false;
fFloatIs32Bits = true;
fHalfIs32Bits = false;
fUnsignedSupport = false;
fBuiltinFMASupport = false;
fVersionDeclString = nullptr;
fShaderDerivativeExtensionString = nullptr;
@ -120,6 +122,7 @@ void GrShaderCaps::dumpJSON(SkJSONWriter* writer) const {
writer->appendBool("Floating point manipulation support", fFPManipulationSupport);
writer->appendBool("float == fp32", fFloatIs32Bits);
writer->appendBool("half == fp32", fHalfIs32Bits);
writer->appendBool("Builtin fma() support", fBuiltinFMASupport);
writer->appendS32("Max FS Samplers", fMaxFragmentSamplers);
writer->appendString("Advanced blend equation interaction",

View File

@ -86,6 +86,9 @@ public:
bool unsignedSupport() const { return fUnsignedSupport; }
// SkSL only.
bool builtinFMASupport() const { return fBuiltinFMASupport; }
AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }
bool mustEnableAdvBlendEqs() const {
@ -254,6 +257,9 @@ private:
bool fHalfIs32Bits : 1;
bool fUnsignedSupport : 1;
// Used by SkSL to know when to generate polyfills.
bool fBuiltinFMASupport : 1;
// Used for specific driver bug work arounds
bool fCanUseAnyFunctionInShader : 1;
bool fCanUseMinAndAbsTogether : 1;

View File

@ -798,6 +798,12 @@ void GrGLCaps::initGLSL(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli
// Unsigned integers only supported in and after GLSL 1.30.
shaderCaps->fUnsignedSupport = ctxInfo.glslGeneration() >= k130_GrGLSLGeneration;
if (kGL_GrGLStandard == standard) {
shaderCaps->fBuiltinFMASupport = ctxInfo.glslGeneration() >= k400_GrGLSLGeneration;
} else {
shaderCaps->fBuiltinFMASupport = ctxInfo.glslGeneration() >= k320es_GrGLSLGeneration;
}
}
bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {

View File

@ -467,6 +467,7 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
(*fFunctionClasses)["dFdx"] = FunctionClass::kDerivative;
(*fFunctionClasses)["dFdy"] = FunctionClass::kDerivative;
(*fFunctionClasses)["fwidth"] = FunctionClass::kDerivative;
(*fFunctionClasses)["fma"] = FunctionClass::kFMA;
(*fFunctionClasses)["fract"] = FunctionClass::kFract;
(*fFunctionClasses)["inverse"] = FunctionClass::kInverse;
(*fFunctionClasses)["inverseSqrt"] = FunctionClass::kInverseSqrt;
@ -535,6 +536,19 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
return;
}
break;
case FunctionClass::kFMA:
if (!fProgram.fSettings.fCaps->builtinFMASupport()) {
SkASSERT(c.fArguments.size() == 3);
this->write("((");
this->writeExpression(*c.fArguments[0], kSequence_Precedence);
this->write(") * (");
this->writeExpression(*c.fArguments[1], kSequence_Precedence);
this->write(") + (");
this->writeExpression(*c.fArguments[2], kSequence_Precedence);
this->write("))");
return;
}
break;
case FunctionClass::kFract:
if (!fProgram.fSettings.fCaps->canUseFractForNegativeValues()) {
SkASSERT(c.fArguments.size() == 1);

View File

@ -228,6 +228,7 @@ protected:
kAtan,
kDeterminant,
kDerivative,
kFMA,
kFract,
kInverse,
kInverseSqrt,