Chromium Code Reviews| Index: src/sksl/SkSLGLSLCodeGenerator.cpp |
| diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp |
| index da0bcb903cf3508826e8a311f6f98338ba06f0a1..a8697b285b159c704b3441752f90ae98e5274a0d 100644 |
| --- a/src/sksl/SkSLGLSLCodeGenerator.cpp |
| +++ b/src/sksl/SkSLGLSLCodeGenerator.cpp |
| @@ -16,6 +16,8 @@ |
| #include "ir/SkSLIndexExpression.h" |
| #include "ir/SkSLVariableReference.h" |
| +#define SK_FRAGCOLOR_BUILTIN 10001 |
| + |
| namespace SkSL { |
| void GLSLCodeGenerator::write(const char* s) { |
| @@ -66,7 +68,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 +126,40 @@ 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 (abs(x) > y ? y : abs(x)) to avoid a Tegra3 compiler bug. Note that |
|
bsalomon
2016/09/08 19:51:37
Can we make it safe by introducing an intermediate
ethannicholas
2016/09/09 16:34:54
Done.
|
| +// this is unsafe when the expressions have side effects due to the double evaluation. |
| +void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { |
| + ASSERT(!fCaps.fCanUseMinAndAbsTogether); |
| + this->write("("); |
| + this->writeExpression(absExpr, kTopLevel_Precedence); |
| + this->write(" > "); |
| + this->writeExpression(otherExpr, kRelational_Precedence); |
| + this->write(" ? "); |
| + this->writeExpression(otherExpr, kTernary_Precedence); |
| + this->write(" : "); |
| + this->writeExpression(absExpr, kTernary_Precedence); |
| + this->write(")"); |
| +} |
| + |
| void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { |
| + if (!fCaps.fCanUseMinAndAbsTogether && c.fFunction.fName == "min") { |
| + ASSERT(c.fArguments.size() == 2); |
| + if (is_abs(*c.fArguments[0])) { |
| + writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); |
|
bsalomon
2016/09/08 19:51:37
this->
ethannicholas
2016/09/09 16:34:54
Done.
|
| + return; |
| + } |
| + if (is_abs(*c.fArguments[1])) { |
| + writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]); |
|
bsalomon
2016/09/08 19:51:37
this->
|
| + return; |
| + } |
| + } |
| this->write(c.fFunction.fName + "("); |
| const char* separator = ""; |
| for (const auto& arg : c.fArguments) { |
| @@ -147,7 +182,11 @@ 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) { |
| + this->write("gl_FragColor"); |
| + } else { |
| + this->write(ref.fVariable.fName); |
| + } |
| } |
| void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { |
| @@ -284,7 +323,7 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { |
| for (const auto& param : f.fDeclaration.fParameters) { |
| this->write(separator); |
| separator = ", "; |
| - this->writeModifiers(param->fModifiers); |
| + this->writeModifiers(param->fModifiers, false); |
| this->writeType(param->fType); |
| this->write(" " + param->fName); |
| } |
| @@ -293,19 +332,66 @@ void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { |
| this->writeLine(); |
| } |
| -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) { |
| + bool modifier = false; |
| + if (modifiers.fFlags & Modifiers::kLowp_Flag) { |
| + this->write("lowp "); |
| + modifier = true; |
| + } |
| + if (modifiers.fFlags & Modifiers::kHighp_Flag) { |
| + this->write("highp "); |
| + modifier = true; |
| + } |
| + if (!modifier) { |
| + this->write("mediump "); |
| + } |
| + } |
| } |
| 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 +399,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) { |
| @@ -349,7 +435,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,9 +530,12 @@ 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) { |
| this->write(" es"); |
| + } else if (fCaps.fIsCoreProfile) { |
| + this->write(" core"); |
| } |
| this->writeLine(); |
| for (const auto& e : program.fElements) { |
| @@ -456,10 +545,16 @@ void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) |
| 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->writeLine("out vec4 gl_FragColor;"); |
| + } |
| } |
| break; |
| } |