1f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas/* 2f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * Copyright 2016 Google Inc. 3f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * 4f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * Use of this source code is governed by a BSD-style license that can be 5f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas * found in the LICENSE file. 6f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas */ 764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel 8f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "SkSLGLSLCodeGenerator.h" 9f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 10f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "GLSL.std.450.h" 11f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 12941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas#include "SkSLCompiler.h" 13f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLExpressionStatement.h" 14f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLExtension.h" 15f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLIndexExpression.h" 165961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas#include "ir/SkSLModifiersDeclaration.h" 17cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas#include "ir/SkSLNop.h" 18f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas#include "ir/SkSLVariableReference.h" 19f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 20f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasnamespace SkSL { 21f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 22f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::write(const char* s) { 23f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (s[0] == 0) { 24f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return; 25f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 26f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (fAtLineStart) { 27f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (int i = 0; i < fIndentation; i++) { 289e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fOut->writeText(" "); 29f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 30f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 319e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fOut->writeText(s); 32f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fAtLineStart = false; 33f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 34f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 35f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeLine(const char* s) { 36f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(s); 37762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fOut->writeText(fLineEnding); 38f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fAtLineStart = true; 39f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 40f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 410df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasvoid GLSLCodeGenerator::write(const String& s) { 42f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(s.c_str()); 43f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 44f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 450df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasvoid GLSLCodeGenerator::writeLine(const String& s) { 46f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(s.c_str()); 47f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 48f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 49f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeLine() { 50f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(""); 51f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 52f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 53f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeExtension(const Extension& ext) { 54f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine("#extension " + ext.fName + " : enable"); 55f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 56f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 57f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeType(const Type& type) { 58f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (type.kind() == Type::kStruct_Kind) { 59f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const Type* search : fWrittenStructs) { 60f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (*search == type) { 61f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // already written 62f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(type.name()); 63f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return; 64f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 65f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 66f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fWrittenStructs.push_back(&type); 67f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine("struct " + type.name() + " {"); 68f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation++; 69f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& f : type.fields()) { 705961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(f.fModifiers, false); 71f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas // sizes (which must be static in structs) are part of the type name here 720730be7c303ac415484b15ef44ff1dce077a93b8ethannicholas this->writeType(*f.fType); 73f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(" " + f.fName + ";"); 74f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 75f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation--; 7619671772c1a03bd973fae54dead4defc9ee1d4c3Ethan Nicholas this->write("}"); 77f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 78f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(type.name()); 79f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 80f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 81f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 82f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) { 83f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas switch (expr.fKind) { 84f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kBinary_Kind: 85f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence); 86f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 87f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kBoolLiteral_Kind: 88f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeBoolLiteral((BoolLiteral&) expr); 89f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 90f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kConstructor_Kind: 91f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeConstructor((Constructor&) expr); 92f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 93f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kIntLiteral_Kind: 94f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeIntLiteral((IntLiteral&) expr); 95f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 96f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kFieldAccess_Kind: 97f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeFieldAccess(((FieldAccess&) expr)); 98f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 99f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kFloatLiteral_Kind: 100f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeFloatLiteral(((FloatLiteral&) expr)); 101f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 102f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kFunctionCall_Kind: 103f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeFunctionCall((FunctionCall&) expr); 104f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 105f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kPrefix_Kind: 106f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence); 107f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 108f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kPostfix_Kind: 109f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence); 110f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 111762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case Expression::kSetting_Kind: 112762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeSetting((Setting&) expr); 113762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 114f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kSwizzle_Kind: 115f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeSwizzle((Swizzle&) expr); 116f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 117f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kVariableReference_Kind: 118f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeVariableReference((VariableReference&) expr); 119f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 120f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kTernary_Kind: 121f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence); 122f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 123f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Expression::kIndex_Kind: 124f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeIndexExpression((IndexExpression&) expr); 125f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 126f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas default: 127f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ABORT("unsupported expression: %s", expr.description().c_str()); 128f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 129f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 130f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 1315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasstatic bool is_abs(Expression& expr) { 1325961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (expr.fKind != Expression::kFunctionCall_Kind) { 1335961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return false; 1345961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1355961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return ((FunctionCall&) expr).fFunction.fName == "abs"; 1365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas} 1375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 138941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a 1395961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas// Tegra3 compiler bug. 1405961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasvoid GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) { 141941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()); 1420df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++); 1430df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++); 1445961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n"; 1455961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n"; 1465961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("((" + tmpVar1 + " = "); 1475961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExpression(absExpr, kTopLevel_Precedence); 1485961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(") < (" + tmpVar2 + " = "); 1495961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExpression(otherExpr, kAssignment_Precedence); 1505961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")"); 1515961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas} 1525961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 153f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { 154941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" && 155941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fBuiltin) { 1565961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ASSERT(c.fArguments.size() == 2); 1575961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (is_abs(*c.fArguments[0])) { 1585961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]); 1595961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return; 1605961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1615961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (is_abs(*c.fArguments[1])) { 1625961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will 1635961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas // ever end up mattering, but it's worth calling out. 1645961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]); 1655961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas return; 1665961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 1675961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 168941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() && 169941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fName == "atan" && 170941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fBuiltin && c.fArguments.size() == 2 && 171ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas c.fArguments[1]->fKind == Expression::kPrefix_Kind) { 172ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1]; 173ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas if (p.fOperator == Token::MINUS) { 174ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->write("atan("); 175ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->writeExpression(*c.fArguments[0], kSequence_Precedence); 176ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->write(", -1.0 * "); 177ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->writeExpression(*p.fOperand, kMultiplicative_Precedence); 178ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas this->write(")"); 179ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas return; 180ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas } 181ad146f6ef5d2de94bd2d8c678757a6274844d20eethannicholas } 182941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") && 183941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) { 184941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport()); 1859e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText("#extension "); 186941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString()); 1879e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText(" : require\n"); 188ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas fFoundDerivatives = true; 189ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas } 1902b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) { 1912b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas const char* dim = ""; 1922b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas bool proj = false; 1932b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas switch (c.fArguments[0]->fType.dimensions()) { 1942b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim1D: 1952b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "1D"; 1962b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fFloat_Type) { 1972b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 1982b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 1992b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec2_Type); 2002b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = true; 2012b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2022b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2032b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim2D: 2042b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "2D"; 2052b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fVec2_Type) { 2062b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2072b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 2082b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec3_Type); 2092b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = true; 2102b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2112b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2122b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDim3D: 2132b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "3D"; 2142b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (c.fArguments[1]->fType == *fContext.fVec3_Type) { 2152b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2162b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 2172b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(c.fArguments[1]->fType == *fContext.fVec4_Type); 2182b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = true; 2192b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2202b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2212b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimCube: 2222b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "Cube"; 2232b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2242b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2252b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimRect: 2262b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "Rect"; 2272b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2282b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2292b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimBuffer: 2302b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(false); // doesn't exist 2312b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "Buffer"; 2322b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2332b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2342b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas case SpvDimSubpassData: 2352b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas ASSERT(false); // doesn't exist 2362b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas dim = "SubpassData"; 2372b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas proj = false; 2382b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas break; 2392b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2402b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write("texture"); 241941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) { 2422b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write(dim); 2432b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2442b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas if (proj) { 2452b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write("Proj"); 2462b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2472b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas 2482b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } else { 2492b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write(c.fFunction.fName); 2502b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas } 2512b3dab62bccdbf6244aef9103e9e739147af8616Ethan Nicholas this->write("("); 252f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas const char* separator = ""; 253f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& arg : c.fArguments) { 254f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(separator); 255f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas separator = ", "; 256f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*arg, kSequence_Precedence); 257f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 258f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 259f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 260f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 261f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeConstructor(const Constructor& c) { 262f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(c.fType.name() + "("); 263f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas const char* separator = ""; 264f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& arg : c.fArguments) { 265f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(separator); 266f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas separator = ", "; 267f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*arg, kSequence_Precedence); 268f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 269f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 270f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 271f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 272941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid GLSLCodeGenerator::writeFragCoord() { 273941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers 274941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the 275941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // declaration varies in earlier GLSL specs. So it is simpler to omit it. 276941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fProgram.fSettings.fFlipY) { 277941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("gl_FragCoord"); 278941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } else if (const char* extension = 279941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) { 280941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fSetupFragPositionGlobal) { 281941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) { 282941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("#extension "); 283941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(extension); 284941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(" : require\n"); 285941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 286941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n"); 287941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fSetupFragPositionGlobal = true; 2885961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 289941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("gl_FragCoord"); 2905961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 291941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fSetupFragPositionGlobal) { 292941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // The Adreno compiler seems to be very touchy about access to "gl_FragCoord". 293941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // Accessing glFragCoord.zw can cause a program to fail to link. Additionally, 294941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // depending on the surrounding code, accessing .xy with a uniform involved can 295941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand 296941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas // (and only accessing .xy) seems to "fix" things. 297941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp " 298941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas : ""; 299941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("uniform "); 300941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(precision); 301941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n"); 302941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fSetupFragPositionGlobal = true; 303941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 304941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (!fSetupFragPositionLocal) { 305941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp " 306941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas : ""; 307941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += precision; 308941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += " vec2 _sktmpCoord = gl_FragCoord.xy;\n"; 309941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += precision; 310941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fFunctionHeader += " vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME 311941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas " - _sktmpCoord.y, 1.0, 1.0);\n"; 312941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fSetupFragPositionLocal = true; 313941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 314941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("sk_FragCoord"); 315941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 316941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas} 317941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas 318941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas 319941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholasvoid GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { 320941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas switch (ref.fVariable.fModifiers.fLayout.fBuiltin) { 321941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas case SK_FRAGCOLOR_BUILTIN: 322941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 323941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("sk_FragColor"); 324941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } else { 325941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write("gl_FragColor"); 326941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas } 327941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas break; 328941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas case SK_FRAGCOORD_BUILTIN: 329941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->writeFragCoord(); 330941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas break; 331a51740c4f879b3c15877975118ef7588b99eaaeaEthan Nicholas case SK_VERTEXID_BUILTIN: 332a51740c4f879b3c15877975118ef7588b99eaaeaEthan Nicholas this->write("gl_VertexID"); 333a51740c4f879b3c15877975118ef7588b99eaaeaEthan Nicholas break; 33467d64605d3421404a94c0717fdff194730579873Ethan Nicholas case SK_CLIPDISTANCE_BUILTIN: 33567d64605d3421404a94c0717fdff194730579873Ethan Nicholas this->write("gl_ClipDistance"); 33667d64605d3421404a94c0717fdff194730579873Ethan Nicholas break; 33752cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas case SK_IN_BUILTIN: 33852cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas this->write("gl_in"); 33952cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas break; 34052cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas case SK_INVOCATIONID_BUILTIN: 34152cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas this->write("gl_InvocationID"); 34252cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas break; 343941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas default: 344941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write(ref.fVariable.fName); 3455961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 346f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 347f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 348f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { 349f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*expr.fBase, kPostfix_Precedence); 350f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("["); 351f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*expr.fIndex, kTopLevel_Precedence); 352f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("]"); 353f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 354f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 355f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { 356f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) { 357f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*f.fBase, kPostfix_Precedence); 358f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("."); 359f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 36067d64605d3421404a94c0717fdff194730579873Ethan Nicholas switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) { 36167d64605d3421404a94c0717fdff194730579873Ethan Nicholas case SK_CLIPDISTANCE_BUILTIN: 36267d64605d3421404a94c0717fdff194730579873Ethan Nicholas this->write("gl_ClipDistance"); 36367d64605d3421404a94c0717fdff194730579873Ethan Nicholas break; 36467d64605d3421404a94c0717fdff194730579873Ethan Nicholas default: 36567d64605d3421404a94c0717fdff194730579873Ethan Nicholas this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); 36667d64605d3421404a94c0717fdff194730579873Ethan Nicholas } 367f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 368f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 369f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { 370f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*swizzle.fBase, kPostfix_Precedence); 371f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("."); 372f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (int c : swizzle.fComponents) { 373f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(&("x\0y\0z\0w\0"[c * 2])); 374f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 375f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 376f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 377762466e9fe0478bcf11fba532998e81e33b3069eEthan NicholasGLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) { 378f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas switch (op) { 379f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::STAR: // fall through 380f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SLASH: // fall through 381f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence; 382f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PLUS: // fall through 383f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence; 384f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHL: // fall through 385f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; 386f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LT: // fall through 387f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::GT: // fall through 388f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LTEQ: // fall through 389f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence; 390f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::EQEQ: // fall through 391f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence; 392f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence; 393f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence; 394f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence; 395f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence; 396f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence; 397f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence; 398f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::EQ: // fall through 399f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PLUSEQ: // fall through 400f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::MINUSEQ: // fall through 401f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::STAREQ: // fall through 402f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SLASHEQ: // fall through 403f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::PERCENTEQ: // fall through 404f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHLEQ: // fall through 405f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::SHREQ: // fall through 406f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALANDEQ: // fall through 407f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALXOREQ: // fall through 408f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::LOGICALOREQ: // fall through 409f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEANDEQ: // fall through 410f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEXOREQ: // fall through 411f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence; 4124b330dfd3334bf24bf93043acfcd31590a3cdbbfEthan Nicholas case Token::COMMA: return GLSLCodeGenerator::kSequence_Precedence; 413f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas default: ABORT("unsupported binary operator"); 414f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 415f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 416f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 4170df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasvoid GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, 418f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 419762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas Precedence precedence = GetBinaryPrecedence(b.fOperator); 420f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (precedence >= parentPrecedence) { 421f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 422f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 423f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*b.fLeft, precedence); 424f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" " + Token::OperatorName(b.fOperator) + " "); 425f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*b.fRight, precedence); 426f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (precedence >= parentPrecedence) { 427f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 428f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 429f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 430f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 4310df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasvoid GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, 432f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 433f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kTernary_Precedence >= parentPrecedence) { 434f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 435f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 436f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*t.fTest, kTernary_Precedence); 437f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" ? "); 438f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*t.fIfTrue, kTernary_Precedence); 439f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" : "); 440f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*t.fIfFalse, kTernary_Precedence); 441f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kTernary_Precedence >= parentPrecedence) { 442f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 443f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 444f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 445f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 4460df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasvoid GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, 447f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 448f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPrefix_Precedence >= parentPrecedence) { 449f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 450f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 451f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(Token::OperatorName(p.fOperator)); 452f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*p.fOperand, kPrefix_Precedence); 453f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPrefix_Precedence >= parentPrecedence) { 454f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 455f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 456f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 457f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 4580df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholasvoid GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, 459f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas Precedence parentPrecedence) { 460f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPostfix_Precedence >= parentPrecedence) { 461f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("("); 462f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 463f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*p.fOperand, kPostfix_Precedence); 464f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(Token::OperatorName(p.fOperator)); 465f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (kPostfix_Precedence >= parentPrecedence) { 466f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(")"); 467f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 468f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 469f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 470f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { 471f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(b.fValue ? "true" : "false"); 472f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 473f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 474f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { 4755961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (i.fType == *fContext.fUInt_Type) { 4765961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(to_string(i.fValue & 0xffffffff) + "u"); 4775961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 4785961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(to_string((int32_t) i.fValue)); 4795961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 480f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 481f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 482f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { 483f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(to_string(f.fValue)); 484f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 485f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 486762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasvoid GLSLCodeGenerator::writeSetting(const Setting& s) { 487762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas ABORT("internal error; setting was not folded to a constant during compilation\n"); 488762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 489762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 490f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { 491f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeType(f.fDeclaration.fReturnType); 492f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" " + f.fDeclaration.fName + "("); 493f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas const char* separator = ""; 494f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas for (const auto& param : f.fDeclaration.fParameters) { 495f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(separator); 496f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas separator = ", "; 4975961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(param->fModifiers, false); 4985961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas std::vector<int> sizes; 4995961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas const Type* type = ¶m->fType; 5005961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas while (type->kind() == Type::kArray_Kind) { 5015961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas sizes.push_back(type->columns()); 5025961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas type = &type->componentType(); 5035961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5045961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeType(*type); 505f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" " + param->fName); 5065961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas for (int s : sizes) { 5075961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (s <= 0) { 5085961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("[]"); 5095961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 5105961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("[" + to_string(s) + "]"); 5115961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5125961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 513f008b0a59f45c0d4bea3e66faf3b01805009ec89ethannicholas } 5145961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine(") {"); 5155961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 5165961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fFunctionHeader = ""; 5170df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas OutputStream* oldOut = fOut; 5180df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas StringStream buffer; 5195961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fOut = &buffer; 5205961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fIndentation++; 521cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->writeStatements(((Block&) *f.fBody).fStatements); 5225961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fIndentation--; 5235961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine("}"); 5245961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas 5255961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas fOut = oldOut; 5265961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(fFunctionHeader); 527762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->write(buffer.str()); 528f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 529f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 53064773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Danielvoid GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers, 5315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas bool globalContext) { 532f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kFlat_Flag) { 533f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("flat "); 534f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 5355961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) { 5365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("noperspective "); 5375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5380df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas String layout = modifiers.fLayout.description(); 5398da9e940721168143d6296f578b6d7423de55d69Ethan Nicholas if (layout.size()) { 5408da9e940721168143d6296f578b6d7423de55d69Ethan Nicholas this->write(layout + " "); 5418da9e940721168143d6296f578b6d7423de55d69Ethan Nicholas } 542f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kReadOnly_Flag) { 543f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("readonly "); 544f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 545f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) { 546f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("writeonly "); 547f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 548f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kCoherent_Flag) { 549f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("coherent "); 550f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 551f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kVolatile_Flag) { 552f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("volatile "); 553f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon } 554f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon if (modifiers.fFlags & Modifiers::kRestrict_Flag) { 555f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon this->write("restrict "); 5565961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 55764773e6c9f61fb319f597a8d7dd7ee377d51a43aGreg Daniel if ((modifiers.fFlags & Modifiers::kIn_Flag) && 5585961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas (modifiers.fFlags & Modifiers::kOut_Flag)) { 5595961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("inout "); 5605961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if (modifiers.fFlags & Modifiers::kIn_Flag) { 561941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (globalContext && 562941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 5635961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write(fProgramKind == Program::kVertex_Kind ? "attribute " 5645961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas : "varying "); 5655961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 5665961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("in "); 5675961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5685961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else if (modifiers.fFlags & Modifiers::kOut_Flag) { 569941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (globalContext && 570941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) { 5715961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("varying "); 5725961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } else { 5735961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("out "); 5745961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5755961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5765961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kUniform_Flag) { 5775961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("uniform "); 5785961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5795961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kConst_Flag) { 5805961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("const "); 5815961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 582941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 5835961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kLowp_Flag) { 5845961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("lowp "); 5855961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5865961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kMediump_Flag) { 5875961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("mediump "); 5885961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5895961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (modifiers.fFlags & Modifiers::kHighp_Flag) { 5905961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("highp "); 5915961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 5925961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 593f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 594f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 595f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { 59652cad15d0b4443b763a7d41ec8d1131a7638f866Ethan Nicholas if (intf.fTypeName == "sk_PerVertex") { 597f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas return; 598f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 5995961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(intf.fVariable.fModifiers, true); 60050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->writeLine(intf.fTypeName + " {"); 601f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation++; 60250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas const Type* structType = &intf.fVariable.fType; 60350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas while (structType->kind() == Type::kArray_Kind) { 60450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas structType = &structType->componentType(); 60550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 60650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas for (const auto& f : structType->fields()) { 6075961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeModifiers(f.fModifiers, false); 6080730be7c303ac415484b15ef44ff1dce077a93b8ethannicholas this->writeType(*f.fType); 609f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(" " + f.fName + ";"); 610f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 611f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation--; 61250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write("}"); 61350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas if (intf.fInstanceName.size()) { 61450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write(" "); 61550afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write(intf.fInstanceName); 61650afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas for (const auto& size : intf.fSizes) { 61750afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write("["); 61850afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas if (size) { 61950afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->writeExpression(*size, kTopLevel_Precedence); 62050afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 62150afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->write("]"); 62250afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 62350afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas } 62450afc1765511a8d4850fe97aacf8714b609bfd5aEthan Nicholas this->writeLine(";"); 625f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 626f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 627762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasvoid GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) { 628762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeExpression(value, kTopLevel_Precedence); 629762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 630762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 6315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholasvoid GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) { 632f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ASSERT(decl.fVars.size() > 0); 633b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas bool wroteType = false; 634b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas for (const auto& stmt : decl.fVars) { 635b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas VarDeclaration& var = (VarDeclaration&) *stmt; 636b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (wroteType) { 637b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas this->write(", "); 638b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas } else { 639b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas this->writeModifiers(var.fVar->fModifiers, global); 640b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas this->writeType(decl.fBaseType); 641b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas this->write(" "); 642b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas wroteType = true; 643b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas } 644b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas this->write(var.fVar->fName); 645b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas for (const auto& size : var.fSizes) { 646f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("["); 6475961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (size) { 6485961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExpression(*size, kTopLevel_Precedence); 6495961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 650f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("]"); 651f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 652b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (var.fValue) { 653f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" = "); 654762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeVarInitializer(*var.fVar, *var.fValue); 655f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 656b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) { 657941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) { 6589e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText("#extension "); 659941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString()); 6609e1138d56665d13641f8805cd72ae81adc255f79Ethan Nicholas fHeader.writeText(" : require\n"); 6612a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon } 6622a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon fFoundImageDecl = true; 6632a51de82ceb6790f329b9f4cc85e61f34fc2d0d4Brian Salomon } 664f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 665b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas if (wroteType) { 666b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas this->write(";"); 667b4dc419f0bc3140cb4e0f5a2fe4db46c4306df86Ethan Nicholas } 668f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 669f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 670f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeStatement(const Statement& s) { 671f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas switch (s.fKind) { 672f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kBlock_Kind: 673f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeBlock((Block&) s); 674f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 675f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kExpression_Kind: 676f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence); 677f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(";"); 678f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 6790df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas case Statement::kReturn_Kind: 680f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeReturnStatement((ReturnStatement&) s); 681f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 68214fe8cc16d2a98d5a96f818e4d0b7127ecad59e2ethannicholas case Statement::kVarDeclarations_Kind: 6835961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false); 684f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 685f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kIf_Kind: 686f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeIfStatement((IfStatement&) s); 687f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 688f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kFor_Kind: 689f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeForStatement((ForStatement&) s); 690f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 691f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kWhile_Kind: 692f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeWhileStatement((WhileStatement&) s); 693f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 694f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kDo_Kind: 695f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeDoStatement((DoStatement&) s); 696f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 697af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas case Statement::kSwitch_Kind: 698af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeSwitchStatement((SwitchStatement&) s); 699af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas break; 700f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kBreak_Kind: 701f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("break;"); 702f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 703f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kContinue_Kind: 704f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("continue;"); 705f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 706f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas case Statement::kDiscard_Kind: 707f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("discard;"); 708f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas break; 709cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas case Statement::kNop_Kind: 710cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->write(";"); 711cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas break; 712f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas default: 713f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas ABORT("unsupported statement: %s", s.description().c_str()); 714f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 715f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 716f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 717cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholasvoid GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statement>>& statements) { 718cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas for (const auto& s : statements) { 719cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas if (!s->isEmpty()) { 720cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->writeStatement(*s); 721cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->writeLine(); 722cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 723cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas } 724cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas} 725cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas 726f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeBlock(const Block& b) { 727f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine("{"); 728f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation++; 729cb67096b61f699b047fe8635984db1ac708a7b99Ethan Nicholas this->writeStatements(b.fStatements); 730f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas fIndentation--; 731f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("}"); 732f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 733f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 734f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { 735f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("if ("); 736f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*stmt.fTest, kTopLevel_Precedence); 737f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(") "); 738f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*stmt.fIfTrue); 739f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (stmt.fIfFalse) { 740f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" else "); 741f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*stmt.fIfFalse); 742f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 743f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 744f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 745f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeForStatement(const ForStatement& f) { 746f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("for ("); 747b310fd597fc37dee888cfd5a760c4e156af08a6dEthan Nicholas if (f.fInitializer && !f.fInitializer->isEmpty()) { 748f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*f.fInitializer); 749f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } else { 750f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("; "); 751f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 752f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (f.fTest) { 753f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*f.fTest, kTopLevel_Precedence); 754f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 755f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("; "); 756f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (f.fNext) { 757f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*f.fNext, kTopLevel_Precedence); 758f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 759f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(") "); 760f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*f.fStatement); 761f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 762f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 763f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) { 764f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("while ("); 765f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*w.fTest, kTopLevel_Precedence); 766f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(") "); 767f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*w.fStatement); 768f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 769f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 770f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { 771f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("do "); 772f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeStatement(*d.fStatement); 773f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" while ("); 774f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*d.fTest, kTopLevel_Precedence); 775f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(");"); 776f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 777f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 778af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholasvoid GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) { 779af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->write("switch ("); 780af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeExpression(*s.fValue, kTopLevel_Precedence); 781af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine(") {"); 782af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation++; 783af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas for (const auto& c : s.fCases) { 784af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas if (c->fValue) { 785af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->write("case "); 786af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeExpression(*c->fValue, kTopLevel_Precedence); 787af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine(":"); 788af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } else { 789af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine("default:"); 790af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 791af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation++; 792af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas for (const auto& stmt : c->fStatements) { 793af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeStatement(*stmt); 794af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->writeLine(); 795af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 796af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation--; 797af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas } 798af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas fIndentation--; 799af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas this->write("}"); 800af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas} 801af19769831f1c4c3b90c85aa9f8851cd8bbf86d5Ethan Nicholas 802f789b3893579b773bb4d7be6c2c65311500b53bbethannicholasvoid GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { 803f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write("return"); 804f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas if (r.fExpression) { 805f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(" "); 806f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeExpression(*r.fExpression, kTopLevel_Precedence); 807f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 808f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->write(";"); 809f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 810f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 811762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasvoid GLSLCodeGenerator::writeHeader() { 812941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas this->write(fProgram.fSettings.fCaps->versionDeclString()); 813f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas this->writeLine(); 814941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas for (const auto& e : fProgram.fElements) { 8155961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas if (e->fKind == ProgramElement::kExtension_Kind) { 8165961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeExtension((Extension&) *e); 8175961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 8185961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 819762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 820762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 821762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasvoid GLSLCodeGenerator::writePrecisionModifier() { 822941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 8235961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("precision "); 824941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas switch (fProgram.fDefaultPrecision) { 8255961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Modifiers::kLowp_Flag: 8265961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("lowp"); 8275961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 8285961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Modifiers::kMediump_Flag: 8295961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("mediump"); 8305961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 8315961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas case Modifiers::kHighp_Flag: 8325961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("highp"); 8335961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas break; 8345961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas default: 8355961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas ASSERT(false); 8365961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->write("<error>"); 8375961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 8385961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas this->writeLine(" float;"); 8395961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 840762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 841762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 842762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasvoid GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) { 843762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas switch (e.fKind) { 844762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case ProgramElement::kExtension_Kind: 845762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 846762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case ProgramElement::kVar_Kind: { 847762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas VarDeclarations& decl = (VarDeclarations&) e; 848762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas if (decl.fVars.size() > 0) { 849762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin; 850762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas if (builtin == -1) { 851762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas // normal var 852762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeVarDeclarations(decl, true); 853762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeLine(); 854762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas } else if (builtin == SK_FRAGCOLOR_BUILTIN && 855762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) { 856762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->write("out "); 857762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) { 858762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->write("mediump "); 8595961bc9278a00e56dacdd9408d0744b5a0a3b493ethannicholas } 860762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeLine("vec4 sk_FragColor;"); 861f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 862f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 863762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 864f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 865762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case ProgramElement::kInterfaceBlock_Kind: 866762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeInterfaceBlock((InterfaceBlock&) e); 867762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 868762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case ProgramElement::kFunction_Kind: 869762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeFunction((FunctionDefinition&) e); 870762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 871762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas case ProgramElement::kModifiers_Kind: 872762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeModifiers(((ModifiersDeclaration&) e).fModifiers, true); 873762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeLine(";"); 874762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas break; 875762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas default: 876762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas printf("%s\n", e.description().c_str()); 877762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas ABORT("unsupported program element"); 878762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas } 879762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas} 880762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas 881762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholasbool GLSLCodeGenerator::generateCode() { 882762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas OutputStream* rawOut = fOut; 883762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fOut = &fHeader; 884762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fProgramKind = fProgram.fKind; 885762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeHeader(); 886762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas StringStream body; 887762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fOut = &body; 888762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writePrecisionModifier(); 889762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas for (const auto& e : fProgram.fElements) { 890762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas this->writeProgramElement(*e); 891f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas } 892762466e9fe0478bcf11fba532998e81e33b3069eEthan Nicholas fOut = rawOut; 893ddb37d67ba4db42fa5c6012b58d0f4985b454dc0ethannicholas 8940df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas write_stringstream(fHeader, *rawOut); 8950df1b04db87c3d86ee0b0bd6aa2cb5b6be32cac2Ethan Nicholas write_stringstream(body, *rawOut); 896941e7e2c9567ab1d8a3b2d1b0e3db71ee5eb75c9Ethan Nicholas return true; 897f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 898f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas 899f789b3893579b773bb4d7be6c2c65311500b53bbethannicholas} 900