diff options
author | 2016-10-11 08:47:04 -0700 | |
---|---|---|
committer | 2016-10-11 08:47:06 -0700 | |
commit | ccb1dd8f267f9d7fe7c9d0ce222ebc81b41853b3 (patch) | |
tree | 8ba52d3b32da6ed9c3feefb30abd2c9ee66f4a3e /src/sksl/SkSLGLSLCodeGenerator.cpp | |
parent | 568c98606fee6ad1b8a0714dd4dffbd4aa1d11d0 (diff) |
Turned on SkSL->GLSL compiler
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2288033003
Committed: https://skia.googlesource.com/skia/+/9b0fe3d125f237d9884732a48414fa85fc71b4e3
Committed: https://skia.googlesource.com/skia/+/b12b3c6908c62c908b3680be01e3b5bfd30de310
Committed: https://skia.googlesource.com/skia/+/f008b0a59f45c0d4bea3e66faf3b01805009ec89
Committed: https://skia.googlesource.com/skia/+/08b2ccf398e2b81bc05d2c105837e5419899469b
Committed: https://skia.googlesource.com/skia/+/dcfe6dba4a335e50e86ff68e3252065d4197432c
Review-Url: https://codereview.chromium.org/2288033003
Diffstat (limited to 'src/sksl/SkSLGLSLCodeGenerator.cpp')
-rw-r--r-- | src/sksl/SkSLGLSLCodeGenerator.cpp | 206 |
1 files changed, 184 insertions, 22 deletions
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp index da0bcb903c..58cf7d3c36 100644 --- a/src/sksl/SkSLGLSLCodeGenerator.cpp +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp @@ -14,8 +14,11 @@ #include "ir/SkSLExpressionStatement.h" #include "ir/SkSLExtension.h" #include "ir/SkSLIndexExpression.h" +#include "ir/SkSLModifiersDeclaration.h" #include "ir/SkSLVariableReference.h" +#define SK_FRAGCOLOR_BUILTIN 10001 + namespace SkSL { void GLSLCodeGenerator::write(const char* s) { @@ -66,7 +69,7 @@ void GLSLCodeGenerator::writeType(const Type& type) { this->writeLine("struct " + type.name() + " {"); fIndentation++; for (const auto& f : type.fields()) { - this->writeModifiers(f.fModifiers); + this->writeModifiers(f.fModifiers, false); // sizes (which must be static in structs) are part of the type name here this->writeType(*f.fType); this->writeLine(" " + f.fName + ";"); @@ -124,7 +127,42 @@ void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren } } +static bool is_abs(Expression& expr) { + if (expr.fKind != Expression::kFunctionCall_Kind) { + return false; + } + return ((FunctionCall&) expr).fFunction.fName == "abs"; +} + +// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a +// Tegra3 compiler bug. +void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { + ASSERT(!fCaps.fCanUseMinAndAbsTogether); + std::string tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); + std::string tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); + this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; + this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n"; + this->write("((" + tmpVar1 + " = "); + this->writeExpression(absExpr, kTopLevel_Precedence); + this->write(") < (" + tmpVar2 + " = "); + this->writeExpression(otherExpr, kAssignment_Precedence); + this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")"); +} + void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { + if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min") { + ASSERT(c.fArguments.size() == 2); + if (is_abs(*c.fArguments[0])) { + this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); + return; + } + if (is_abs(*c.fArguments[1])) { + // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will + // ever end up mattering, but it's worth calling out. + this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]); + return; + } + } this->write(c.fFunction.fName + "("); const char* separator = ""; for (const auto& arg : c.fArguments) { @@ -147,7 +185,15 @@ void GLSLCodeGenerator::writeConstructor(const Constructor& c) { } void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { - this->write(ref.fVariable.fName); + if (ref.fVariable.fModifiers.fLayout.fBuiltin == SK_FRAGCOLOR_BUILTIN) { + if (fCaps.fMustDeclareFragmentShaderOutput) { + this->write("sk_FragColor"); + } else { + this->write("gl_FragColor"); + } + } else { + this->write(ref.fVariable.fName); + } } void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { @@ -270,7 +316,11 @@ void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { } void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { - this->write(to_string(i.fValue)); + if (i.fType == *fContext.fUInt_Type) { + this->write(to_string(i.fValue & 0xffffffff) + "u"); + } else { + this->write(to_string((int32_t) i.fValue)); + } } void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { @@ -284,28 +334,99 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { for (const auto& param : f.fDeclaration.fParameters) { this->write(separator); separator = ", "; - this->writeModifiers(param->fModifiers); - this->writeType(param->fType); + this->writeModifiers(param->fModifiers, false); + std::vector<int> sizes; + const Type* type = ¶m->fType; + while (type->kind() == Type::kArray_Kind) { + sizes.push_back(type->columns()); + type = &type->componentType(); + } + this->writeType(*type); this->write(" " + param->fName); + for (int s : sizes) { + if (s <= 0) { + this->write("[]"); + } else { + this->write("[" + to_string(s) + "]"); + } + } } - this->write(") "); - this->writeBlock(*f.fBody); - this->writeLine(); + this->writeLine(") {"); + + fFunctionHeader = ""; + std::ostream* oldOut = fOut; + std::stringstream buffer; + fOut = &buffer; + fIndentation++; + for (const auto& s : f.fBody->fStatements) { + this->writeStatement(*s); + this->writeLine(); + } + fIndentation--; + this->writeLine("}"); + + fOut = oldOut; + this->write(fFunctionHeader); + this->write(buffer.str()); } -void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) { - this->write(modifiers.description()); +void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, + bool globalContext) { + if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { + this->write("noperspective "); + } + if (modifiers.fFlags & Modifiers::kFlat_Flag) { + this->write("flat "); + } + std::string layout = modifiers.fLayout.description(); + if (layout.length()) { + this->write(layout + " "); + } + if ((modifiers.fFlags & Modifiers::kIn_Flag) && + (modifiers.fFlags & Modifiers::kOut_Flag)) { + this->write("inout "); + } else if (modifiers.fFlags & Modifiers::kIn_Flag) { + if (globalContext && fCaps.fVersion < 130) { + this->write(fProgramKind == Program::kVertex_Kind ? "attribute " + : "varying "); + } else { + this->write("in "); + } + } else if (modifiers.fFlags & Modifiers::kOut_Flag) { + if (globalContext && fCaps.fVersion < 130) { + this->write("varying "); + } else { + this->write("out "); + } + } + if (modifiers.fFlags & Modifiers::kUniform_Flag) { + this->write("uniform "); + } + if (modifiers.fFlags & Modifiers::kConst_Flag) { + this->write("const "); + } + if (fCaps.fUsesPrecisionModifiers) { + if (modifiers.fFlags & Modifiers::kLowp_Flag) { + this->write("lowp "); + } + if (modifiers.fFlags & Modifiers::kMediump_Flag) { + this->write("mediump "); + } + if (modifiers.fFlags & Modifiers::kHighp_Flag) { + this->write("highp "); + } + } } void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { if (intf.fVariable.fName == "gl_PerVertex") { return; } - this->writeModifiers(intf.fVariable.fModifiers); + this->writeModifiers(intf.fVariable.fModifiers, true); this->writeLine(intf.fVariable.fType.name() + " {"); fIndentation++; for (const auto& f : intf.fVariable.fType.fields()) { - this->writeModifiers(f.fModifiers); + this->writeModifiers(f.fModifiers, false); this->writeType(*f.fType); this->writeLine(" " + f.fName + ";"); } @@ -313,9 +434,9 @@ void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { this->writeLine("};"); } -void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) { +void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { ASSERT(decl.fVars.size() > 0); - this->writeModifiers(decl.fVars[0].fVar->fModifiers); + this->writeModifiers(decl.fVars[0].fVar->fModifiers, global); this->writeType(decl.fBaseType); std::string separator = " "; for (const auto& var : decl.fVars) { @@ -325,7 +446,9 @@ void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) { this->write(var.fVar->fName); for (const auto& size : var.fSizes) { this->write("["); - this->writeExpression(*size, kTopLevel_Precedence); + if (size) { + this->writeExpression(*size, kTopLevel_Precedence); + } this->write("]"); } if (var.fValue) { @@ -349,7 +472,7 @@ void GLSLCodeGenerator::writeStatement(const Statement& s) { this->writeReturnStatement((ReturnStatement&) s); break; case Statement::kVarDeclarations_Kind: - this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration); + this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false); break; case Statement::kIf_Kind: this->writeIfStatement((IfStatement&) s); @@ -444,22 +567,57 @@ void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) { ASSERT(fOut == nullptr); fOut = &out; + fProgramKind = program.fKind; this->write("#version " + to_string(fCaps.fVersion)); - if (fCaps.fStandard == GLCaps::kGLES_Standard) { + if (fCaps.fStandard == GLCaps::kGLES_Standard && fCaps.fVersion >= 300) { this->write(" es"); + } else if (fCaps.fIsCoreProfile) { + this->write(" core"); } this->writeLine(); for (const auto& e : program.fElements) { + if (e->fKind == ProgramElement::kExtension_Kind) { + this->writeExtension((Extension&) *e); + } + } + if (fCaps.fStandard == GLCaps::kGLES_Standard) { + this->write("precision "); + switch (program.fDefaultPrecision) { + case Modifiers::kLowp_Flag: + this->write("lowp"); + break; + case Modifiers::kMediump_Flag: + this->write("mediump"); + break; + case Modifiers::kHighp_Flag: + this->write("highp"); + break; + default: + ASSERT(false); + this->write("<error>"); + } + this->writeLine(" float;"); + } + for (const auto& e : program.fElements) { switch (e->fKind) { case ProgramElement::kExtension_Kind: - this->writeExtension((Extension&) *e); break; case ProgramElement::kVar_Kind: { VarDeclarations& decl = (VarDeclarations&) *e; - if (decl.fVars.size() > 0 && - decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin == -1) { - this->writeVarDeclarations(decl); - this->writeLine(); + if (decl.fVars.size() > 0) { + int builtin = decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin; + if (builtin == -1) { + // normal var + this->writeVarDeclarations(decl, true); + this->writeLine(); + } else if (builtin == SK_FRAGCOLOR_BUILTIN && + fCaps.fMustDeclareFragmentShaderOutput) { + this->write("out "); + if (fCaps.fUsesPrecisionModifiers) { + this->write("mediump "); + } + this->writeLine("vec4 sk_FragColor;"); + } } break; } @@ -469,6 +627,10 @@ void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) case ProgramElement::kFunction_Kind: this->writeFunction((FunctionDefinition&) *e); break; + case ProgramElement::kModifiers_Kind: + this->writeModifiers(((ModifiersDeclaration&) *e).fModifiers, true); + this->writeLine(";"); + break; default: printf("%s\n", e->description().c_str()); ABORT("unsupported program element"); |