aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Ethan Nicholas <ethannicholas@google.com>2018-01-03 17:03:56 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-01-04 21:31:00 +0000
commit6e6525c930b683e6dcd5551bd7a3b68ecc68e45e (patch)
tree082822d9b9957705b6fc852bce922e3585a17dea
parent511c5d45ddf4dd029673f0855116513a13a5e028 (diff)
sksl now provides support for inverse, transpose, et al. on older versions of OpenGL
Bug: skia: Change-Id: I7dec3e3ae9f111a61c294cba4547c1af2260722f Reviewed-on: https://skia-review.googlesource.com/90525 Reviewed-by: Chris Dalton <csmartdalton@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.cpp210
-rw-r--r--src/sksl/SkSLGLSLCodeGenerator.h10
2 files changed, 220 insertions, 0 deletions
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index 4223a4114b..ad3fde52f9 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -247,6 +247,191 @@ void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherEx
this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
}
+void GLSLCodeGenerator::writeInverseSqrtHack(const Expression& x) {
+ this->write("(1.0 / sqrt(");
+ this->writeExpression(x, kTopLevel_Precedence);
+ this->write("))");
+}
+
+void GLSLCodeGenerator::writeDeterminantHack(const Expression& mat) {
+ String name;
+ if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) {
+ name = "_determinant2";
+ if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
+ fWrittenIntrinsics.insert(name);
+ fExtraFunctions.writeText((
+ "float " + name + "(mat2 m) {"
+ " return m[0][0] * m[1][1] - m[0][1] * m[1][0];"
+ "}"
+ ).c_str());
+ }
+ }
+ else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) {
+ name = "_determinant3";
+ if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
+ fWrittenIntrinsics.insert(name);
+ fExtraFunctions.writeText((
+ "float " + name + "(mat3 m) {"
+ " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
+ " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
+ " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
+ " float b01 = a22 * a11 - a12 * a21;"
+ " float b11 = -a22 * a10 + a12 * a20;"
+ " float b21 = a21 * a10 - a11 * a20;"
+ " return a00 * b01 + a01 * b11 + a02 * b21;"
+ "}"
+ ).c_str());
+ }
+ }
+ else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) {
+ name = "_determinant3";
+ if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
+ fWrittenIntrinsics.insert(name);
+ fExtraFunctions.writeText((
+ "mat4 " + name + "(mat4 m) {"
+ " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
+ " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
+ " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
+ " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
+ " float b00 = a00 * a11 - a01 * a10;"
+ " float b01 = a00 * a12 - a02 * a10;"
+ " float b02 = a00 * a13 - a03 * a10;"
+ " float b03 = a01 * a12 - a02 * a11;"
+ " float b04 = a01 * a13 - a03 * a11;"
+ " float b05 = a02 * a13 - a03 * a12;"
+ " float b06 = a20 * a31 - a21 * a30;"
+ " float b07 = a20 * a32 - a22 * a30;"
+ " float b08 = a20 * a33 - a23 * a30;"
+ " float b09 = a21 * a32 - a22 * a31;"
+ " float b10 = a21 * a33 - a23 * a31;"
+ " float b11 = a22 * a33 - a23 * a32;"
+ " return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;"
+ "}"
+ ).c_str());
+ }
+ }
+ else {
+ ASSERT(false);
+ }
+ this->write(name + "(");
+ this->writeExpression(mat, kTopLevel_Precedence);
+ this->write(")");
+}
+
+void GLSLCodeGenerator::writeInverseHack(const Expression& mat) {
+ String name;
+ if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) {
+ name = "_inverse2";
+ if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
+ fWrittenIntrinsics.insert(name);
+ fExtraFunctions.writeText((
+ "mat2 " + name + "(mat2 m) {"
+ " return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / "
+ "(m[0][0] * m[1][1] - m[0][1] * m[1][0]);"
+ "}"
+ ).c_str());
+ }
+ }
+ else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) {
+ name = "_inverse3";
+ if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
+ fWrittenIntrinsics.insert(name);
+ fExtraFunctions.writeText((
+ "mat3 " + name + "(mat3 m) {"
+ " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
+ " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
+ " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
+ " float b01 = a22 * a11 - a12 * a21;"
+ " float b11 = -a22 * a10 + a12 * a20;"
+ " float b21 = a21 * a10 - a11 * a20;"
+ " float det = a00 * b01 + a01 * b11 + a02 * b21;"
+ " return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),"
+ " b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),"
+ " b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;"
+ "}"
+ ).c_str());
+ }
+ }
+ else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) {
+ name = "_inverse4";
+ if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
+ fWrittenIntrinsics.insert(name);
+ fExtraFunctions.writeText((
+ "mat4 " + name + "(mat4 m) {"
+ " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
+ " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
+ " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
+ " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
+ " float b00 = a00 * a11 - a01 * a10;"
+ " float b01 = a00 * a12 - a02 * a10;"
+ " float b02 = a00 * a13 - a03 * a10;"
+ " float b03 = a01 * a12 - a02 * a11;"
+ " float b04 = a01 * a13 - a03 * a11;"
+ " float b05 = a02 * a13 - a03 * a12;"
+ " float b06 = a20 * a31 - a21 * a30;"
+ " float b07 = a20 * a32 - a22 * a30;"
+ " float b08 = a20 * a33 - a23 * a30;"
+ " float b09 = a21 * a32 - a22 * a31;"
+ " float b10 = a21 * a33 - a23 * a31;"
+ " float b11 = a22 * a33 - a23 * a32;"
+ " float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - "
+ " b04 * b07 + b05 * b06;"
+ " return mat4("
+ " a11 * b11 - a12 * b10 + a13 * b09,"
+ " a02 * b10 - a01 * b11 - a03 * b09,"
+ " a31 * b05 - a32 * b04 + a33 * b03,"
+ " a22 * b04 - a21 * b05 - a23 * b03,"
+ " a12 * b08 - a10 * b11 - a13 * b07,"
+ " a00 * b11 - a02 * b08 + a03 * b07,"
+ " a32 * b02 - a30 * b05 - a33 * b01,"
+ " a20 * b05 - a22 * b02 + a23 * b01,"
+ " a10 * b10 - a11 * b08 + a13 * b06,"
+ " a01 * b08 - a00 * b10 - a03 * b06,"
+ " a30 * b04 - a31 * b02 + a33 * b00,"
+ " a21 * b02 - a20 * b04 - a23 * b00,"
+ " a11 * b07 - a10 * b09 - a12 * b06,"
+ " a00 * b09 - a01 * b07 + a02 * b06,"
+ " a31 * b01 - a30 * b03 - a32 * b00,"
+ " a20 * b03 - a21 * b01 + a22 * b00) / det;"
+ "}"
+ ).c_str());
+ }
+ }
+ else {
+ ASSERT(false);
+ }
+ this->write(name + "(");
+ this->writeExpression(mat, kTopLevel_Precedence);
+ this->write(")");
+}
+
+void GLSLCodeGenerator::writeTransposeHack(const Expression& mat) {
+ String name = "transpose" + to_string(mat.fType.columns()) + to_string(mat.fType.rows());
+ if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
+ fWrittenIntrinsics.insert(name);
+ String type = this->getTypeName(mat.fType);
+ const Type& base = mat.fType.componentType();
+ String transposed = this->getTypeName(base.toCompound(fContext,
+ mat.fType.rows(),
+ mat.fType.columns()));
+ fExtraFunctions.writeText((transposed + " " + name + "(" + type + " m) {\nreturn " +
+ transposed + "(").c_str());
+ const char* separator = "";
+ for (int row = 0; row < mat.fType.rows(); ++row) {
+ for (int column = 0; column < mat.fType.columns(); ++column) {
+ fExtraFunctions.writeText(separator);
+ fExtraFunctions.writeText(("m[" + to_string(column) + "][" + to_string(row) +
+ "]").c_str());
+ separator = ", ";
+ }
+ }
+ fExtraFunctions.writeText("); }");
+ }
+ this->write(name + "(");
+ this->writeExpression(mat, kTopLevel_Precedence);
+ this->write(")");
+}
+
void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" &&
c.fFunction.fBuiltin) {
@@ -288,6 +473,30 @@ void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
return;
}
}
+ if (c.fFunction.fBuiltin && c.fFunction.fName == "determinant" &&
+ fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
+ ASSERT(c.fArguments.size() == 1);
+ this->writeDeterminantHack(*c.fArguments[0]);
+ return;
+ }
+ if (c.fFunction.fBuiltin && c.fFunction.fName == "inverse" &&
+ fProgram.fSettings.fCaps->generation() < k140_GrGLSLGeneration) {
+ ASSERT(c.fArguments.size() == 1);
+ this->writeInverseHack(*c.fArguments[0]);
+ return;
+ }
+ if (c.fFunction.fBuiltin && c.fFunction.fName == "inverseSqrt" &&
+ fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
+ ASSERT(c.fArguments.size() == 1);
+ this->writeInverseSqrtHack(*c.fArguments[0]);
+ return;
+ }
+ if (c.fFunction.fBuiltin && c.fFunction.fName == "transpose" &&
+ fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
+ ASSERT(c.fArguments.size() == 1);
+ this->writeTransposeHack(*c.fArguments[0]);
+ return;
+ }
if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") &&
c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) {
ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport());
@@ -1048,6 +1257,7 @@ bool GLSLCodeGenerator::generateCode() {
if (this->usesPrecisionModifiers()) {
this->writeLine("precision mediump float;");
}
+ write_stringstream(fExtraFunctions, *rawOut);
write_stringstream(body, *rawOut);
return true;
}
diff --git a/src/sksl/SkSLGLSLCodeGenerator.h b/src/sksl/SkSLGLSLCodeGenerator.h
index e9a63ac48f..70ce920900 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.h
+++ b/src/sksl/SkSLGLSLCodeGenerator.h
@@ -136,6 +136,14 @@ protected:
void writeMinAbsHack(Expression& absExpr, Expression& otherExpr);
+ void writeDeterminantHack(const Expression& mat);
+
+ void writeInverseHack(const Expression& mat);
+
+ void writeTransposeHack(const Expression& mat);
+
+ void writeInverseSqrtHack(const Expression& x);
+
virtual void writeFunctionCall(const FunctionCall& c);
void writeConstructor(const Constructor& c, Precedence parentPrecedence);
@@ -187,6 +195,7 @@ protected:
const char* fLineEnding;
const Context& fContext;
StringStream fHeader;
+ StringStream fExtraFunctions;
String fFunctionHeader;
Program::Kind fProgramKind;
int fVarCount = 0;
@@ -196,6 +205,7 @@ protected:
// more than one or two structs per shader, a simple linear search will be faster than anything
// fancier.
std::vector<const Type*> fWrittenStructs;
+ std::set<String> fWrittenIntrinsics;
// true if we have run into usages of dFdx / dFdy
bool fFoundDerivatives = false;
bool fFoundImageDecl = false;