1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkSLGLSLCodeGenerator.h"
9 
10 #include "SkSLCompiler.h"
11 #include "ir/SkSLExpressionStatement.h"
12 #include "ir/SkSLExtension.h"
13 #include "ir/SkSLIndexExpression.h"
14 #include "ir/SkSLModifiersDeclaration.h"
15 #include "ir/SkSLNop.h"
16 #include "ir/SkSLVariableReference.h"
17 
18 namespace SkSL {
19 
write(const char * s)20 void GLSLCodeGenerator::write(const char* s) {
21     if (s[0] == 0) {
22         return;
23     }
24     if (fAtLineStart) {
25         for (int i = 0; i < fIndentation; i++) {
26             fOut->writeText("    ");
27         }
28     }
29     fOut->writeText(s);
30     fAtLineStart = false;
31 }
32 
writeLine(const char * s)33 void GLSLCodeGenerator::writeLine(const char* s) {
34     this->write(s);
35     fOut->writeText(fLineEnding);
36     fAtLineStart = true;
37 }
38 
write(const String & s)39 void GLSLCodeGenerator::write(const String& s) {
40     this->write(s.c_str());
41 }
42 
write(StringFragment s)43 void GLSLCodeGenerator::write(StringFragment s) {
44     if (!s.fLength) {
45         return;
46     }
47     if (fAtLineStart) {
48         for (int i = 0; i < fIndentation; i++) {
49             fOut->writeText("    ");
50         }
51     }
52     fOut->write(s.fChars, s.fLength);
53     fAtLineStart = false;
54 }
55 
writeLine(const String & s)56 void GLSLCodeGenerator::writeLine(const String& s) {
57     this->writeLine(s.c_str());
58 }
59 
writeLine()60 void GLSLCodeGenerator::writeLine() {
61     this->writeLine("");
62 }
63 
writeExtension(const Extension & ext)64 void GLSLCodeGenerator::writeExtension(const Extension& ext) {
65     this->write("#extension ");
66     this->write(ext.fName);
67     this->writeLine(" : enable");
68 }
69 
usesPrecisionModifiers() const70 bool GLSLCodeGenerator::usesPrecisionModifiers() const {
71     return fProgram.fSettings.fCaps->usesPrecisionModifiers();
72 }
73 
getTypeName(const Type & type)74 String GLSLCodeGenerator::getTypeName(const Type& type) {
75     switch (type.kind()) {
76         case Type::kVector_Kind: {
77             Type component = type.componentType();
78             String result;
79             if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
80                 result = "vec";
81             }
82             else if (component == *fContext.fDouble_Type) {
83                 result = "dvec";
84             }
85             else if (component == *fContext.fInt_Type || component == *fContext.fShort_Type) {
86                 result = "ivec";
87             }
88             else if (component == *fContext.fUInt_Type || component == *fContext.fUShort_Type) {
89                 result = "uvec";
90             }
91             else if (component == *fContext.fBool_Type) {
92                 result = "bvec";
93             }
94             else {
95                 ABORT("unsupported vector type");
96             }
97             result += to_string(type.columns());
98             return result;
99         }
100         case Type::kMatrix_Kind: {
101             String result;
102             Type component = type.componentType();
103             if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
104                 result = "mat";
105             }
106             else if (component == *fContext.fDouble_Type) {
107                 result = "dmat";
108             }
109             else {
110                 ABORT("unsupported matrix type");
111             }
112             result += to_string(type.columns());
113             if (type.columns() != type.rows()) {
114                 result += "x";
115                 result += to_string(type.rows());
116             }
117             return result;
118         }
119         case Type::kArray_Kind: {
120             String result = this->getTypeName(type.componentType()) + "[";
121             if (type.columns() != -1) {
122                 result += to_string(type.columns());
123             }
124             result += "]";
125             return result;
126         }
127         case Type::kScalar_Kind: {
128             if (type == *fContext.fHalf_Type) {
129                 return "float";
130             }
131             else if (type == *fContext.fShort_Type) {
132                 return "int";
133             }
134             else if (type == *fContext.fUShort_Type) {
135                 return "uint";
136             }
137             else {
138                 return type.name();
139             }
140             break;
141         }
142         default:
143             return type.name();
144     }
145 }
146 
writeType(const Type & type)147 void GLSLCodeGenerator::writeType(const Type& type) {
148     if (type.kind() == Type::kStruct_Kind) {
149         for (const Type* search : fWrittenStructs) {
150             if (*search == type) {
151                 // already written
152                 this->write(type.fName);
153                 return;
154             }
155         }
156         fWrittenStructs.push_back(&type);
157         this->write("struct ");
158         this->write(type.fName);
159         this->writeLine(" {");
160         fIndentation++;
161         for (const auto& f : type.fields()) {
162             this->writeModifiers(f.fModifiers, false);
163             this->writeTypePrecision(*f.fType);
164             // sizes (which must be static in structs) are part of the type name here
165             this->writeType(*f.fType);
166             this->write(" ");
167             this->write(f.fName);
168             this->writeLine(";");
169         }
170         fIndentation--;
171         this->write("}");
172     } else {
173         this->write(this->getTypeName(type));
174     }
175 }
176 
writeExpression(const Expression & expr,Precedence parentPrecedence)177 void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
178     switch (expr.fKind) {
179         case Expression::kBinary_Kind:
180             this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence);
181             break;
182         case Expression::kBoolLiteral_Kind:
183             this->writeBoolLiteral((BoolLiteral&) expr);
184             break;
185         case Expression::kConstructor_Kind:
186             this->writeConstructor((Constructor&) expr, parentPrecedence);
187             break;
188         case Expression::kIntLiteral_Kind:
189             this->writeIntLiteral((IntLiteral&) expr);
190             break;
191         case Expression::kFieldAccess_Kind:
192             this->writeFieldAccess(((FieldAccess&) expr));
193             break;
194         case Expression::kFloatLiteral_Kind:
195             this->writeFloatLiteral(((FloatLiteral&) expr));
196             break;
197         case Expression::kFunctionCall_Kind:
198             this->writeFunctionCall((FunctionCall&) expr);
199             break;
200         case Expression::kPrefix_Kind:
201             this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence);
202             break;
203         case Expression::kPostfix_Kind:
204             this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence);
205             break;
206         case Expression::kSetting_Kind:
207             this->writeSetting((Setting&) expr);
208             break;
209         case Expression::kSwizzle_Kind:
210             this->writeSwizzle((Swizzle&) expr);
211             break;
212         case Expression::kVariableReference_Kind:
213             this->writeVariableReference((VariableReference&) expr);
214             break;
215         case Expression::kTernary_Kind:
216             this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence);
217             break;
218         case Expression::kIndex_Kind:
219             this->writeIndexExpression((IndexExpression&) expr);
220             break;
221         default:
222             ABORT("unsupported expression: %s", expr.description().c_str());
223     }
224 }
225 
is_abs(Expression & expr)226 static bool is_abs(Expression& expr) {
227     if (expr.fKind != Expression::kFunctionCall_Kind) {
228         return false;
229     }
230     return ((FunctionCall&) expr).fFunction.fName == "abs";
231 }
232 
233 // turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
234 // Tegra3 compiler bug.
writeMinAbsHack(Expression & absExpr,Expression & otherExpr)235 void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
236     ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
237     String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
238     String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
239     this->fFunctionHeader += String("    ") + this->getTypePrecision(absExpr.fType) +
240                              this->getTypeName(absExpr.fType) + " " + tmpVar1 + ";\n";
241     this->fFunctionHeader += String("    ") + this->getTypePrecision(otherExpr.fType) +
242                              this->getTypeName(otherExpr.fType) + " " + tmpVar2 + ";\n";
243     this->write("((" + tmpVar1 + " = ");
244     this->writeExpression(absExpr, kTopLevel_Precedence);
245     this->write(") < (" + tmpVar2 + " = ");
246     this->writeExpression(otherExpr, kAssignment_Precedence);
247     this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
248 }
249 
writeInverseSqrtHack(const Expression & x)250 void GLSLCodeGenerator::writeInverseSqrtHack(const Expression& x) {
251     this->write("(1.0 / sqrt(");
252     this->writeExpression(x, kTopLevel_Precedence);
253     this->write("))");
254 }
255 
writeDeterminantHack(const Expression & mat)256 void GLSLCodeGenerator::writeDeterminantHack(const Expression& mat) {
257     String name;
258     if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) {
259         name = "_determinant2";
260         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
261             fWrittenIntrinsics.insert(name);
262             fExtraFunctions.writeText((
263                 "float " + name + "(mat2 m) {"
264                 "    return m[0][0] * m[1][1] - m[0][1] * m[1][0];"
265                 "}"
266             ).c_str());
267         }
268     }
269     else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) {
270         name = "_determinant3";
271         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
272             fWrittenIntrinsics.insert(name);
273             fExtraFunctions.writeText((
274                 "float " + name + "(mat3 m) {"
275                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
276                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
277                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
278                 "    float b01 = a22 * a11 - a12 * a21;"
279                 "    float b11 = -a22 * a10 + a12 * a20;"
280                 "    float b21 = a21 * a10 - a11 * a20;"
281                 "    return a00 * b01 + a01 * b11 + a02 * b21;"
282                 "}"
283             ).c_str());
284         }
285     }
286     else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) {
287         name = "_determinant3";
288         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
289             fWrittenIntrinsics.insert(name);
290             fExtraFunctions.writeText((
291                 "mat4 " + name + "(mat4 m) {"
292                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
293                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
294                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
295                 "    float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
296                 "    float b00 = a00 * a11 - a01 * a10;"
297                 "    float b01 = a00 * a12 - a02 * a10;"
298                 "    float b02 = a00 * a13 - a03 * a10;"
299                 "    float b03 = a01 * a12 - a02 * a11;"
300                 "    float b04 = a01 * a13 - a03 * a11;"
301                 "    float b05 = a02 * a13 - a03 * a12;"
302                 "    float b06 = a20 * a31 - a21 * a30;"
303                 "    float b07 = a20 * a32 - a22 * a30;"
304                 "    float b08 = a20 * a33 - a23 * a30;"
305                 "    float b09 = a21 * a32 - a22 * a31;"
306                 "    float b10 = a21 * a33 - a23 * a31;"
307                 "    float b11 = a22 * a33 - a23 * a32;"
308                 "    return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;"
309                 "}"
310             ).c_str());
311         }
312     }
313     else {
314         ASSERT(false);
315     }
316     this->write(name + "(");
317     this->writeExpression(mat, kTopLevel_Precedence);
318     this->write(")");
319 }
320 
writeInverseHack(const Expression & mat)321 void GLSLCodeGenerator::writeInverseHack(const Expression& mat) {
322     String name;
323     if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) {
324         name = "_inverse2";
325         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
326             fWrittenIntrinsics.insert(name);
327             fExtraFunctions.writeText((
328                 "mat2 " + name + "(mat2 m) {"
329                 "    return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / "
330                                "(m[0][0] * m[1][1] - m[0][1] * m[1][0]);"
331                 "}"
332             ).c_str());
333         }
334     }
335     else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) {
336         name = "_inverse3";
337         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
338             fWrittenIntrinsics.insert(name);
339             fExtraFunctions.writeText((
340                 "mat3 " +  name + "(mat3 m) {"
341                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
342                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
343                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
344                 "    float b01 = a22 * a11 - a12 * a21;"
345                 "    float b11 = -a22 * a10 + a12 * a20;"
346                 "    float b21 = a21 * a10 - a11 * a20;"
347                 "    float det = a00 * b01 + a01 * b11 + a02 * b21;"
348                 "    return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),"
349                 "                b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),"
350                 "                b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;"
351                 "}"
352             ).c_str());
353         }
354     }
355     else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) {
356         name = "_inverse4";
357         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
358             fWrittenIntrinsics.insert(name);
359             fExtraFunctions.writeText((
360                 "mat4 " + name + "(mat4 m) {"
361                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
362                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
363                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
364                 "    float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
365                 "    float b00 = a00 * a11 - a01 * a10;"
366                 "    float b01 = a00 * a12 - a02 * a10;"
367                 "    float b02 = a00 * a13 - a03 * a10;"
368                 "    float b03 = a01 * a12 - a02 * a11;"
369                 "    float b04 = a01 * a13 - a03 * a11;"
370                 "    float b05 = a02 * a13 - a03 * a12;"
371                 "    float b06 = a20 * a31 - a21 * a30;"
372                 "    float b07 = a20 * a32 - a22 * a30;"
373                 "    float b08 = a20 * a33 - a23 * a30;"
374                 "    float b09 = a21 * a32 - a22 * a31;"
375                 "    float b10 = a21 * a33 - a23 * a31;"
376                 "    float b11 = a22 * a33 - a23 * a32;"
377                 "    float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - "
378                 "                b04 * b07 + b05 * b06;"
379                 "    return mat4("
380                 "        a11 * b11 - a12 * b10 + a13 * b09,"
381                 "        a02 * b10 - a01 * b11 - a03 * b09,"
382                 "        a31 * b05 - a32 * b04 + a33 * b03,"
383                 "        a22 * b04 - a21 * b05 - a23 * b03,"
384                 "        a12 * b08 - a10 * b11 - a13 * b07,"
385                 "        a00 * b11 - a02 * b08 + a03 * b07,"
386                 "        a32 * b02 - a30 * b05 - a33 * b01,"
387                 "        a20 * b05 - a22 * b02 + a23 * b01,"
388                 "        a10 * b10 - a11 * b08 + a13 * b06,"
389                 "        a01 * b08 - a00 * b10 - a03 * b06,"
390                 "        a30 * b04 - a31 * b02 + a33 * b00,"
391                 "        a21 * b02 - a20 * b04 - a23 * b00,"
392                 "        a11 * b07 - a10 * b09 - a12 * b06,"
393                 "        a00 * b09 - a01 * b07 + a02 * b06,"
394                 "        a31 * b01 - a30 * b03 - a32 * b00,"
395                 "        a20 * b03 - a21 * b01 + a22 * b00) / det;"
396                 "}"
397             ).c_str());
398         }
399     }
400     else {
401         ASSERT(false);
402     }
403     this->write(name + "(");
404     this->writeExpression(mat, kTopLevel_Precedence);
405     this->write(")");
406 }
407 
writeTransposeHack(const Expression & mat)408 void GLSLCodeGenerator::writeTransposeHack(const Expression& mat) {
409     String name = "transpose" + to_string(mat.fType.columns()) + to_string(mat.fType.rows());
410     if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
411         fWrittenIntrinsics.insert(name);
412         String type = this->getTypeName(mat.fType);
413         const Type& base = mat.fType.componentType();
414         String transposed =  this->getTypeName(base.toCompound(fContext,
415                                                                mat.fType.rows(),
416                                                                mat.fType.columns()));
417         fExtraFunctions.writeText((transposed + " " + name + "(" + type + " m) {\nreturn " +
418                                   transposed + "(").c_str());
419         const char* separator = "";
420         for (int row = 0; row < mat.fType.rows(); ++row) {
421             for (int column = 0; column < mat.fType.columns(); ++column) {
422                 fExtraFunctions.writeText(separator);
423                 fExtraFunctions.writeText(("m[" + to_string(column) + "][" + to_string(row) +
424                                            "]").c_str());
425                 separator = ", ";
426             }
427         }
428         fExtraFunctions.writeText("); }");
429     }
430     this->write(name + "(");
431     this->writeExpression(mat, kTopLevel_Precedence);
432     this->write(")");
433 }
434 
writeFunctionCall(const FunctionCall & c)435 void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
436     if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" &&
437         c.fFunction.fBuiltin) {
438         ASSERT(c.fArguments.size() == 2);
439         if (is_abs(*c.fArguments[0])) {
440             this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
441             return;
442         }
443         if (is_abs(*c.fArguments[1])) {
444             // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will
445             // ever end up mattering, but it's worth calling out.
446             this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]);
447             return;
448         }
449     }
450     if (!fProgram.fSettings.fCaps->canUseFractForNegativeValues() && c.fFunction.fName == "fract" &&
451         c.fFunction.fBuiltin) {
452         ASSERT(c.fArguments.size() == 1);
453 
454         this->write("(0.5 - sign(");
455         this->writeExpression(*c.fArguments[0], kSequence_Precedence);
456         this->write(") * (0.5 - fract(abs(");
457         this->writeExpression(*c.fArguments[0], kSequence_Precedence);
458         this->write("))))");
459 
460         return;
461     }
462     if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
463         c.fFunction.fName == "atan" &&
464         c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
465         c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
466         const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
467         if (p.fOperator == Token::MINUS) {
468             this->write("atan(");
469             this->writeExpression(*c.fArguments[0], kSequence_Precedence);
470             this->write(", -1.0 * ");
471             this->writeExpression(*p.fOperand, kMultiplicative_Precedence);
472             this->write(")");
473             return;
474         }
475     }
476     if (c.fFunction.fBuiltin && c.fFunction.fName == "determinant" &&
477         fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
478         ASSERT(c.fArguments.size() == 1);
479         this->writeDeterminantHack(*c.fArguments[0]);
480         return;
481     }
482     if (c.fFunction.fBuiltin && c.fFunction.fName == "inverse" &&
483         fProgram.fSettings.fCaps->generation() < k140_GrGLSLGeneration) {
484         ASSERT(c.fArguments.size() == 1);
485         this->writeInverseHack(*c.fArguments[0]);
486         return;
487     }
488     if (c.fFunction.fBuiltin && c.fFunction.fName == "inverseSqrt" &&
489         fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
490         ASSERT(c.fArguments.size() == 1);
491         this->writeInverseSqrtHack(*c.fArguments[0]);
492         return;
493     }
494     if (c.fFunction.fBuiltin && c.fFunction.fName == "transpose" &&
495         fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
496         ASSERT(c.fArguments.size() == 1);
497         this->writeTransposeHack(*c.fArguments[0]);
498         return;
499     }
500     if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") &&
501         c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) {
502         ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport());
503         fHeader.writeText("#extension ");
504         fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString());
505         fHeader.writeText(" : require\n");
506         fFoundDerivatives = true;
507     }
508     bool isTextureFunctionWithBias = false;
509     if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) {
510         const char* dim = "";
511         bool proj = false;
512         switch (c.fArguments[0]->fType.dimensions()) {
513             case SpvDim1D:
514                 dim = "1D";
515                 isTextureFunctionWithBias = true;
516                 if (c.fArguments[1]->fType == *fContext.fFloat_Type) {
517                     proj = false;
518                 } else {
519                     ASSERT(c.fArguments[1]->fType == *fContext.fFloat2_Type);
520                     proj = true;
521                 }
522                 break;
523             case SpvDim2D:
524                 dim = "2D";
525                 if (c.fArguments[0]->fType != *fContext.fSamplerExternalOES_Type) {
526                     isTextureFunctionWithBias = true;
527                 }
528                 if (c.fArguments[1]->fType == *fContext.fFloat2_Type) {
529                     proj = false;
530                 } else {
531                     ASSERT(c.fArguments[1]->fType == *fContext.fFloat3_Type);
532                     proj = true;
533                 }
534                 break;
535             case SpvDim3D:
536                 dim = "3D";
537                 isTextureFunctionWithBias = true;
538                 if (c.fArguments[1]->fType == *fContext.fFloat3_Type) {
539                     proj = false;
540                 } else {
541                     ASSERT(c.fArguments[1]->fType == *fContext.fFloat4_Type);
542                     proj = true;
543                 }
544                 break;
545             case SpvDimCube:
546                 dim = "Cube";
547                 isTextureFunctionWithBias = true;
548                 proj = false;
549                 break;
550             case SpvDimRect:
551                 dim = "Rect";
552                 proj = false;
553                 break;
554             case SpvDimBuffer:
555                 ASSERT(false); // doesn't exist
556                 dim = "Buffer";
557                 proj = false;
558                 break;
559             case SpvDimSubpassData:
560                 ASSERT(false); // doesn't exist
561                 dim = "SubpassData";
562                 proj = false;
563                 break;
564         }
565         this->write("texture");
566         if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
567             this->write(dim);
568         }
569         if (proj) {
570             this->write("Proj");
571         }
572 
573     } else {
574         this->write(c.fFunction.fName);
575     }
576     this->write("(");
577     const char* separator = "";
578     for (const auto& arg : c.fArguments) {
579         this->write(separator);
580         separator = ", ";
581         this->writeExpression(*arg, kSequence_Precedence);
582     }
583     if (fProgram.fSettings.fSharpenTextures && isTextureFunctionWithBias) {
584         this->write(", -0.5");
585     }
586     this->write(")");
587 }
588 
writeConstructor(const Constructor & c,Precedence parentPrecedence)589 void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) {
590     if (c.fArguments.size() == 1 &&
591         this->getTypeName(c.fType) == this->getTypeName(c.fArguments[0]->fType)) {
592         // in cases like half(float), they're different types as far as SkSL is concerned but the
593         // same type as far as GLSL is concerned. We avoid a redundant float(float) by just writing
594         // out the inner expression here.
595         this->writeExpression(*c.fArguments[0], parentPrecedence);
596         return;
597     }
598     this->writeType(c.fType);
599     this->write("(");
600     const char* separator = "";
601     for (const auto& arg : c.fArguments) {
602         this->write(separator);
603         separator = ", ";
604         this->writeExpression(*arg, kSequence_Precedence);
605     }
606     this->write(")");
607 }
608 
writeFragCoord()609 void GLSLCodeGenerator::writeFragCoord() {
610     if (!fProgram.fSettings.fCaps->canUseFragCoord()) {
611         if (!fSetupFragCoordWorkaround) {
612             const char* precision = usesPrecisionModifiers() ? "highp " : "";
613             fFunctionHeader += precision;
614             fFunctionHeader += "    float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n";
615             fFunctionHeader += precision;
616             fFunctionHeader += "    vec4 sk_FragCoord_Resolved = "
617                 "vec4(sk_FragCoord_Workaround.xyz * sk_FragCoord_InvW, sk_FragCoord_InvW);\n";
618             // Ensure that we get exact .5 values for x and y.
619             fFunctionHeader += "    sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + "
620                                "vec2(.5);\n";
621             fSetupFragCoordWorkaround = true;
622         }
623         this->write("sk_FragCoord_Resolved");
624         return;
625     }
626 
627     // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
628     // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
629     // declaration varies in earlier GLSL specs. So it is simpler to omit it.
630     if (!fProgram.fSettings.fFlipY) {
631         this->write("gl_FragCoord");
632     } else if (const char* extension =
633                fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) {
634         if (!fSetupFragPositionGlobal) {
635             if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
636                 fHeader.writeText("#extension ");
637                 fHeader.writeText(extension);
638                 fHeader.writeText(" : require\n");
639             }
640             fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n");
641             fSetupFragPositionGlobal = true;
642         }
643         this->write("gl_FragCoord");
644     } else {
645         if (!fSetupFragPositionGlobal) {
646             // The Adreno compiler seems to be very touchy about access to "gl_FragCoord".
647             // Accessing glFragCoord.zw can cause a program to fail to link. Additionally,
648             // depending on the surrounding code, accessing .xy with a uniform involved can
649             // do the same thing. Copying gl_FragCoord.xy into a temp float2 beforehand
650             // (and only accessing .xy) seems to "fix" things.
651             const char* precision = usesPrecisionModifiers() ? "highp " : "";
652             fHeader.writeText("uniform ");
653             fHeader.writeText(precision);
654             fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n");
655             fSetupFragPositionGlobal = true;
656         }
657         if (!fSetupFragPositionLocal) {
658             const char* precision = usesPrecisionModifiers() ? "highp " : "";
659             fFunctionHeader += precision;
660             fFunctionHeader += "    vec2 _sktmpCoord = gl_FragCoord.xy;\n";
661             fFunctionHeader += precision;
662             fFunctionHeader += "    vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME
663                                " - _sktmpCoord.y, 1.0, 1.0);\n";
664             fSetupFragPositionLocal = true;
665         }
666         this->write("sk_FragCoord");
667     }
668 }
669 
writeVariableReference(const VariableReference & ref)670 void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
671     switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
672         case SK_FRAGCOLOR_BUILTIN:
673             if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
674                 this->write("sk_FragColor");
675             } else {
676                 this->write("gl_FragColor");
677             }
678             break;
679         case SK_FRAGCOORD_BUILTIN:
680             this->writeFragCoord();
681             break;
682         case SK_VERTEXID_BUILTIN:
683             this->write("gl_VertexID");
684             break;
685         case SK_INSTANCEID_BUILTIN:
686             this->write("gl_InstanceID");
687             break;
688         case SK_CLIPDISTANCE_BUILTIN:
689             this->write("gl_ClipDistance");
690             break;
691         case SK_IN_BUILTIN:
692             this->write("gl_in");
693             break;
694         case SK_INVOCATIONID_BUILTIN:
695             this->write("gl_InvocationID");
696             break;
697         default:
698             this->write(ref.fVariable.fName);
699     }
700 }
701 
writeIndexExpression(const IndexExpression & expr)702 void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
703     this->writeExpression(*expr.fBase, kPostfix_Precedence);
704     this->write("[");
705     this->writeExpression(*expr.fIndex, kTopLevel_Precedence);
706     this->write("]");
707 }
708 
is_sk_position(const FieldAccess & f)709 bool is_sk_position(const FieldAccess& f) {
710     return "sk_Position" == f.fBase->fType.fields()[f.fFieldIndex].fName;
711 }
712 
writeFieldAccess(const FieldAccess & f)713 void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
714     if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) {
715         this->writeExpression(*f.fBase, kPostfix_Precedence);
716         this->write(".");
717     }
718     switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) {
719         case SK_CLIPDISTANCE_BUILTIN:
720             this->write("gl_ClipDistance");
721             break;
722         default:
723             StringFragment name = f.fBase->fType.fields()[f.fFieldIndex].fName;
724             if (name == "sk_Position") {
725                 this->write("gl_Position");
726             } else if (name == "sk_PointSize") {
727                 this->write("gl_PointSize");
728             } else {
729                 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName);
730             }
731     }
732 }
733 
writeSwizzle(const Swizzle & swizzle)734 void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
735     this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
736     this->write(".");
737     for (int c : swizzle.fComponents) {
738         this->write(&("x\0y\0z\0w\0"[c * 2]));
739     }
740 }
741 
GetBinaryPrecedence(Token::Kind op)742 GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) {
743     switch (op) {
744         case Token::STAR:         // fall through
745         case Token::SLASH:        // fall through
746         case Token::PERCENT:      return GLSLCodeGenerator::kMultiplicative_Precedence;
747         case Token::PLUS:         // fall through
748         case Token::MINUS:        return GLSLCodeGenerator::kAdditive_Precedence;
749         case Token::SHL:          // fall through
750         case Token::SHR:          return GLSLCodeGenerator::kShift_Precedence;
751         case Token::LT:           // fall through
752         case Token::GT:           // fall through
753         case Token::LTEQ:         // fall through
754         case Token::GTEQ:         return GLSLCodeGenerator::kRelational_Precedence;
755         case Token::EQEQ:         // fall through
756         case Token::NEQ:          return GLSLCodeGenerator::kEquality_Precedence;
757         case Token::BITWISEAND:   return GLSLCodeGenerator::kBitwiseAnd_Precedence;
758         case Token::BITWISEXOR:   return GLSLCodeGenerator::kBitwiseXor_Precedence;
759         case Token::BITWISEOR:    return GLSLCodeGenerator::kBitwiseOr_Precedence;
760         case Token::LOGICALAND:   return GLSLCodeGenerator::kLogicalAnd_Precedence;
761         case Token::LOGICALXOR:   return GLSLCodeGenerator::kLogicalXor_Precedence;
762         case Token::LOGICALOR:    return GLSLCodeGenerator::kLogicalOr_Precedence;
763         case Token::EQ:           // fall through
764         case Token::PLUSEQ:       // fall through
765         case Token::MINUSEQ:      // fall through
766         case Token::STAREQ:       // fall through
767         case Token::SLASHEQ:      // fall through
768         case Token::PERCENTEQ:    // fall through
769         case Token::SHLEQ:        // fall through
770         case Token::SHREQ:        // fall through
771         case Token::LOGICALANDEQ: // fall through
772         case Token::LOGICALXOREQ: // fall through
773         case Token::LOGICALOREQ:  // fall through
774         case Token::BITWISEANDEQ: // fall through
775         case Token::BITWISEXOREQ: // fall through
776         case Token::BITWISEOREQ:  return GLSLCodeGenerator::kAssignment_Precedence;
777         case Token::COMMA:        return GLSLCodeGenerator::kSequence_Precedence;
778         default: ABORT("unsupported binary operator");
779     }
780 }
781 
writeBinaryExpression(const BinaryExpression & b,Precedence parentPrecedence)782 void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
783                                               Precedence parentPrecedence) {
784     Precedence precedence = GetBinaryPrecedence(b.fOperator);
785     if (precedence >= parentPrecedence) {
786         this->write("(");
787     }
788     bool positionWorkaround = Compiler::IsAssignment(b.fOperator) &&
789                               Expression::kFieldAccess_Kind == b.fLeft->fKind &&
790                               is_sk_position((FieldAccess&) *b.fLeft) &&
791                               !strstr(b.fRight->description().c_str(), "sk_RTAdjust") &&
792                               !fProgram.fSettings.fCaps->canUseFragCoord();
793     if (positionWorkaround) {
794         this->write("sk_FragCoord_Workaround = (");
795     }
796     this->writeExpression(*b.fLeft, precedence);
797     this->write(" ");
798     this->write(Compiler::OperatorName(b.fOperator));
799     this->write(" ");
800     this->writeExpression(*b.fRight, precedence);
801     if (positionWorkaround) {
802         this->write(")");
803     }
804     if (precedence >= parentPrecedence) {
805         this->write(")");
806     }
807 }
808 
writeTernaryExpression(const TernaryExpression & t,Precedence parentPrecedence)809 void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
810                                                Precedence parentPrecedence) {
811     if (kTernary_Precedence >= parentPrecedence) {
812         this->write("(");
813     }
814     this->writeExpression(*t.fTest, kTernary_Precedence);
815     this->write(" ? ");
816     this->writeExpression(*t.fIfTrue, kTernary_Precedence);
817     this->write(" : ");
818     this->writeExpression(*t.fIfFalse, kTernary_Precedence);
819     if (kTernary_Precedence >= parentPrecedence) {
820         this->write(")");
821     }
822 }
823 
writePrefixExpression(const PrefixExpression & p,Precedence parentPrecedence)824 void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
825                                               Precedence parentPrecedence) {
826     if (kPrefix_Precedence >= parentPrecedence) {
827         this->write("(");
828     }
829     this->write(Compiler::OperatorName(p.fOperator));
830     this->writeExpression(*p.fOperand, kPrefix_Precedence);
831     if (kPrefix_Precedence >= parentPrecedence) {
832         this->write(")");
833     }
834 }
835 
writePostfixExpression(const PostfixExpression & p,Precedence parentPrecedence)836 void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
837                                                Precedence parentPrecedence) {
838     if (kPostfix_Precedence >= parentPrecedence) {
839         this->write("(");
840     }
841     this->writeExpression(*p.fOperand, kPostfix_Precedence);
842     this->write(Compiler::OperatorName(p.fOperator));
843     if (kPostfix_Precedence >= parentPrecedence) {
844         this->write(")");
845     }
846 }
847 
writeBoolLiteral(const BoolLiteral & b)848 void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
849     this->write(b.fValue ? "true" : "false");
850 }
851 
writeIntLiteral(const IntLiteral & i)852 void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
853     if (i.fType == *fContext.fUInt_Type) {
854         this->write(to_string(i.fValue & 0xffffffff) + "u");
855     } else if (i.fType == *fContext.fUShort_Type) {
856         this->write(to_string(i.fValue & 0xffff) + "u");
857      } else {
858         this->write(to_string((int32_t) i.fValue));
859     }
860 }
861 
writeFloatLiteral(const FloatLiteral & f)862 void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
863     this->write(to_string(f.fValue));
864 }
865 
writeSetting(const Setting & s)866 void GLSLCodeGenerator::writeSetting(const Setting& s) {
867     ABORT("internal error; setting was not folded to a constant during compilation\n");
868 }
869 
writeFunction(const FunctionDefinition & f)870 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
871     this->writeTypePrecision(f.fDeclaration.fReturnType);
872     this->writeType(f.fDeclaration.fReturnType);
873     this->write(" " + f.fDeclaration.fName + "(");
874     const char* separator = "";
875     for (const auto& param : f.fDeclaration.fParameters) {
876         this->write(separator);
877         separator = ", ";
878         this->writeModifiers(param->fModifiers, false);
879         std::vector<int> sizes;
880         const Type* type = &param->fType;
881         while (type->kind() == Type::kArray_Kind) {
882             sizes.push_back(type->columns());
883             type = &type->componentType();
884         }
885         this->writeTypePrecision(*type);
886         this->writeType(*type);
887         this->write(" " + param->fName);
888         for (int s : sizes) {
889             if (s <= 0) {
890                 this->write("[]");
891             } else {
892                 this->write("[" + to_string(s) + "]");
893             }
894         }
895     }
896     this->writeLine(") {");
897 
898     fFunctionHeader = "";
899     OutputStream* oldOut = fOut;
900     StringStream buffer;
901     fOut = &buffer;
902     fIndentation++;
903     this->writeStatements(((Block&) *f.fBody).fStatements);
904     fIndentation--;
905     this->writeLine("}");
906 
907     fOut = oldOut;
908     this->write(fFunctionHeader);
909     this->write(buffer.str());
910 }
911 
writeModifiers(const Modifiers & modifiers,bool globalContext)912 void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
913                                        bool globalContext) {
914     if (modifiers.fFlags & Modifiers::kFlat_Flag) {
915         this->write("flat ");
916     }
917     if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
918         this->write("noperspective ");
919     }
920     String layout = modifiers.fLayout.description();
921     if (layout.size()) {
922         this->write(layout + " ");
923     }
924     if (modifiers.fFlags & Modifiers::kReadOnly_Flag) {
925         this->write("readonly ");
926     }
927     if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) {
928         this->write("writeonly ");
929     }
930     if (modifiers.fFlags & Modifiers::kCoherent_Flag) {
931         this->write("coherent ");
932     }
933     if (modifiers.fFlags & Modifiers::kVolatile_Flag) {
934         this->write("volatile ");
935     }
936     if (modifiers.fFlags & Modifiers::kRestrict_Flag) {
937         this->write("restrict ");
938     }
939     if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
940         (modifiers.fFlags & Modifiers::kOut_Flag)) {
941         this->write("inout ");
942     } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
943         if (globalContext &&
944             fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
945             this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
946                                                               : "varying ");
947         } else {
948             this->write("in ");
949         }
950     } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
951         if (globalContext &&
952             fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
953             this->write("varying ");
954         } else {
955             this->write("out ");
956         }
957     }
958     if (modifiers.fFlags & Modifiers::kUniform_Flag) {
959         this->write("uniform ");
960     }
961     if (modifiers.fFlags & Modifiers::kConst_Flag) {
962         this->write("const ");
963     }
964     if (usesPrecisionModifiers()) {
965         if (modifiers.fFlags & Modifiers::kLowp_Flag) {
966             this->write("lowp ");
967         }
968         if (modifiers.fFlags & Modifiers::kMediump_Flag) {
969             this->write("mediump ");
970         }
971         if (modifiers.fFlags & Modifiers::kHighp_Flag) {
972             this->write("highp ");
973         }
974     }
975 }
976 
writeInterfaceBlock(const InterfaceBlock & intf)977 void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
978     if (intf.fTypeName == "sk_PerVertex") {
979         return;
980     }
981     this->writeModifiers(intf.fVariable.fModifiers, true);
982     this->writeLine(intf.fTypeName + " {");
983     fIndentation++;
984     const Type* structType = &intf.fVariable.fType;
985     while (structType->kind() == Type::kArray_Kind) {
986         structType = &structType->componentType();
987     }
988     for (const auto& f : structType->fields()) {
989         this->writeModifiers(f.fModifiers, false);
990         this->writeTypePrecision(*f.fType);
991         this->writeType(*f.fType);
992         this->writeLine(" " + f.fName + ";");
993     }
994     fIndentation--;
995     this->write("}");
996     if (intf.fInstanceName.size()) {
997         this->write(" ");
998         this->write(intf.fInstanceName);
999         for (const auto& size : intf.fSizes) {
1000             this->write("[");
1001             if (size) {
1002                 this->writeExpression(*size, kTopLevel_Precedence);
1003             }
1004             this->write("]");
1005         }
1006     }
1007     this->writeLine(";");
1008 }
1009 
writeVarInitializer(const Variable & var,const Expression & value)1010 void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
1011     this->writeExpression(value, kTopLevel_Precedence);
1012 }
1013 
getTypePrecision(const Type & type)1014 const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
1015     if (usesPrecisionModifiers()) {
1016         switch (type.kind()) {
1017             case Type::kScalar_Kind:
1018                 if (type == *fContext.fHalf_Type || type == *fContext.fShort_Type ||
1019                         type == *fContext.fUShort_Type) {
1020                     return fProgram.fSettings.fForceHighPrecision ? "highp " : "mediump ";
1021                 }
1022                 if (type == *fContext.fFloat_Type || type == *fContext.fInt_Type ||
1023                         type == *fContext.fUInt_Type) {
1024                     return "highp ";
1025                 }
1026                 return "";
1027             case Type::kVector_Kind: // fall through
1028             case Type::kMatrix_Kind:
1029                 return this->getTypePrecision(type.componentType());
1030             default:
1031                 break;
1032         }
1033     }
1034     return "";
1035 }
1036 
writeTypePrecision(const Type & type)1037 void GLSLCodeGenerator::writeTypePrecision(const Type& type) {
1038     this->write(this->getTypePrecision(type));
1039 }
1040 
writeVarDeclarations(const VarDeclarations & decl,bool global)1041 void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
1042     if (!decl.fVars.size()) {
1043         return;
1044     }
1045     bool wroteType = false;
1046     for (const auto& stmt : decl.fVars) {
1047         VarDeclaration& var = (VarDeclaration&) *stmt;
1048         if (wroteType) {
1049             this->write(", ");
1050         } else {
1051             this->writeModifiers(var.fVar->fModifiers, global);
1052             this->writeTypePrecision(decl.fBaseType);
1053             this->writeType(decl.fBaseType);
1054             this->write(" ");
1055             wroteType = true;
1056         }
1057         this->write(var.fVar->fName);
1058         for (const auto& size : var.fSizes) {
1059             this->write("[");
1060             if (size) {
1061                 this->writeExpression(*size, kTopLevel_Precedence);
1062             }
1063             this->write("]");
1064         }
1065         if (var.fValue) {
1066             this->write(" = ");
1067             this->writeVarInitializer(*var.fVar, *var.fValue);
1068         }
1069         if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) {
1070             if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) {
1071                 fHeader.writeText("#extension ");
1072                 fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString());
1073                 fHeader.writeText(" : require\n");
1074             }
1075             fFoundImageDecl = true;
1076         }
1077     }
1078     if (wroteType) {
1079         this->write(";");
1080     }
1081 }
1082 
writeStatement(const Statement & s)1083 void GLSLCodeGenerator::writeStatement(const Statement& s) {
1084     switch (s.fKind) {
1085         case Statement::kBlock_Kind:
1086             this->writeBlock((Block&) s);
1087             break;
1088         case Statement::kExpression_Kind:
1089             this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence);
1090             this->write(";");
1091             break;
1092         case Statement::kReturn_Kind:
1093             this->writeReturnStatement((ReturnStatement&) s);
1094             break;
1095         case Statement::kVarDeclarations_Kind:
1096             this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
1097             break;
1098         case Statement::kIf_Kind:
1099             this->writeIfStatement((IfStatement&) s);
1100             break;
1101         case Statement::kFor_Kind:
1102             this->writeForStatement((ForStatement&) s);
1103             break;
1104         case Statement::kWhile_Kind:
1105             this->writeWhileStatement((WhileStatement&) s);
1106             break;
1107         case Statement::kDo_Kind:
1108             this->writeDoStatement((DoStatement&) s);
1109             break;
1110         case Statement::kSwitch_Kind:
1111             this->writeSwitchStatement((SwitchStatement&) s);
1112             break;
1113         case Statement::kBreak_Kind:
1114             this->write("break;");
1115             break;
1116         case Statement::kContinue_Kind:
1117             this->write("continue;");
1118             break;
1119         case Statement::kDiscard_Kind:
1120             this->write("discard;");
1121             break;
1122         case Statement::kNop_Kind:
1123             this->write(";");
1124             break;
1125         default:
1126             ABORT("unsupported statement: %s", s.description().c_str());
1127     }
1128 }
1129 
writeStatements(const std::vector<std::unique_ptr<Statement>> & statements)1130 void GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statement>>& statements) {
1131     for (const auto& s : statements) {
1132         if (!s->isEmpty()) {
1133             this->writeStatement(*s);
1134             this->writeLine();
1135         }
1136     }
1137 }
1138 
writeBlock(const Block & b)1139 void GLSLCodeGenerator::writeBlock(const Block& b) {
1140     this->writeLine("{");
1141     fIndentation++;
1142     this->writeStatements(b.fStatements);
1143     fIndentation--;
1144     this->write("}");
1145 }
1146 
writeIfStatement(const IfStatement & stmt)1147 void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
1148     this->write("if (");
1149     this->writeExpression(*stmt.fTest, kTopLevel_Precedence);
1150     this->write(") ");
1151     this->writeStatement(*stmt.fIfTrue);
1152     if (stmt.fIfFalse) {
1153         this->write(" else ");
1154         this->writeStatement(*stmt.fIfFalse);
1155     }
1156 }
1157 
writeForStatement(const ForStatement & f)1158 void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
1159     this->write("for (");
1160     if (f.fInitializer && !f.fInitializer->isEmpty()) {
1161         this->writeStatement(*f.fInitializer);
1162     } else {
1163         this->write("; ");
1164     }
1165     if (f.fTest) {
1166         this->writeExpression(*f.fTest, kTopLevel_Precedence);
1167     }
1168     this->write("; ");
1169     if (f.fNext) {
1170         this->writeExpression(*f.fNext, kTopLevel_Precedence);
1171     }
1172     this->write(") ");
1173     this->writeStatement(*f.fStatement);
1174 }
1175 
writeWhileStatement(const WhileStatement & w)1176 void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1177     this->write("while (");
1178     this->writeExpression(*w.fTest, kTopLevel_Precedence);
1179     this->write(") ");
1180     this->writeStatement(*w.fStatement);
1181 }
1182 
writeDoStatement(const DoStatement & d)1183 void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
1184     this->write("do ");
1185     this->writeStatement(*d.fStatement);
1186     this->write(" while (");
1187     this->writeExpression(*d.fTest, kTopLevel_Precedence);
1188     this->write(");");
1189 }
1190 
writeSwitchStatement(const SwitchStatement & s)1191 void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
1192     this->write("switch (");
1193     this->writeExpression(*s.fValue, kTopLevel_Precedence);
1194     this->writeLine(") {");
1195     fIndentation++;
1196     for (const auto& c : s.fCases) {
1197         if (c->fValue) {
1198             this->write("case ");
1199             this->writeExpression(*c->fValue, kTopLevel_Precedence);
1200             this->writeLine(":");
1201         } else {
1202             this->writeLine("default:");
1203         }
1204         fIndentation++;
1205         for (const auto& stmt : c->fStatements) {
1206             this->writeStatement(*stmt);
1207             this->writeLine();
1208         }
1209         fIndentation--;
1210     }
1211     fIndentation--;
1212     this->write("}");
1213 }
1214 
writeReturnStatement(const ReturnStatement & r)1215 void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1216     this->write("return");
1217     if (r.fExpression) {
1218         this->write(" ");
1219         this->writeExpression(*r.fExpression, kTopLevel_Precedence);
1220     }
1221     this->write(";");
1222 }
1223 
writeHeader()1224 void GLSLCodeGenerator::writeHeader() {
1225     this->write(fProgram.fSettings.fCaps->versionDeclString());
1226     this->writeLine();
1227     for (const auto& e : fProgram.fElements) {
1228         if (e->fKind == ProgramElement::kExtension_Kind) {
1229             this->writeExtension((Extension&) *e);
1230         }
1231     }
1232     if (!fProgram.fSettings.fCaps->canUseFragCoord()) {
1233         Layout layout;
1234         switch (fProgram.fKind) {
1235             case Program::kVertex_Kind: {
1236                 Modifiers modifiers(layout, Modifiers::kOut_Flag | Modifiers::kHighp_Flag);
1237                 this->writeModifiers(modifiers, true);
1238                 this->write("vec4 sk_FragCoord_Workaround;\n");
1239                 break;
1240             }
1241             case Program::kFragment_Kind: {
1242                 Modifiers modifiers(layout, Modifiers::kIn_Flag | Modifiers::kHighp_Flag);
1243                 this->writeModifiers(modifiers, true);
1244                 this->write("vec4 sk_FragCoord_Workaround;\n");
1245                 break;
1246             }
1247             default:
1248                 break;
1249         }
1250     }
1251 }
1252 
writeProgramElement(const ProgramElement & e)1253 void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
1254     switch (e.fKind) {
1255         case ProgramElement::kExtension_Kind:
1256             break;
1257         case ProgramElement::kVar_Kind: {
1258             VarDeclarations& decl = (VarDeclarations&) e;
1259             if (decl.fVars.size() > 0) {
1260                 int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin;
1261                 if (builtin == -1) {
1262                     // normal var
1263                     this->writeVarDeclarations(decl, true);
1264                     this->writeLine();
1265                 } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
1266                            fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
1267                     this->write("out ");
1268                     if (usesPrecisionModifiers()) {
1269                         this->write("mediump ");
1270                     }
1271                     this->writeLine("vec4 sk_FragColor;");
1272                 }
1273             }
1274             break;
1275         }
1276         case ProgramElement::kInterfaceBlock_Kind:
1277             this->writeInterfaceBlock((InterfaceBlock&) e);
1278             break;
1279         case ProgramElement::kFunction_Kind:
1280             this->writeFunction((FunctionDefinition&) e);
1281             break;
1282         case ProgramElement::kModifiers_Kind: {
1283             const Modifiers& modifiers = ((ModifiersDeclaration&) e).fModifiers;
1284             if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) {
1285                 if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) {
1286                     fHeader.writeText("#extension ");
1287                     fHeader.writeText(fProgram.fSettings.fCaps->gsInvocationsExtensionString());
1288                     fHeader.writeText(" : require\n");
1289                 }
1290                 fFoundGSInvocations = true;
1291             }
1292             this->writeModifiers(modifiers, true);
1293             this->writeLine(";");
1294             break;
1295         }
1296         case ProgramElement::kEnum_Kind:
1297             break;
1298         default:
1299             printf("%s\n", e.description().c_str());
1300             ABORT("unsupported program element");
1301     }
1302 }
1303 
generateCode()1304 bool GLSLCodeGenerator::generateCode() {
1305     OutputStream* rawOut = fOut;
1306     fOut = &fHeader;
1307     fProgramKind = fProgram.fKind;
1308     this->writeHeader();
1309     if (Program::kGeometry_Kind == fProgramKind &&
1310         fProgram.fSettings.fCaps->geometryShaderExtensionString()) {
1311         fHeader.writeText("#extension ");
1312         fHeader.writeText(fProgram.fSettings.fCaps->geometryShaderExtensionString());
1313         fHeader.writeText(" : require\n");
1314     }
1315     StringStream body;
1316     fOut = &body;
1317     for (const auto& e : fProgram.fElements) {
1318         this->writeProgramElement(*e);
1319     }
1320     fOut = rawOut;
1321 
1322     write_stringstream(fHeader, *rawOut);
1323     if (this->usesPrecisionModifiers()) {
1324         this->writeLine("precision mediump float;");
1325     }
1326     write_stringstream(fExtraFunctions, *rawOut);
1327     write_stringstream(body, *rawOut);
1328     return true;
1329 }
1330 
1331 }
1332