Update rive-cpp to 2.0 version
[platform/core/uifw/rive-tizen.git] / submodule / skia / src / sksl / codegen / SkSLGLSLCodeGenerator.cpp
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 "src/sksl/codegen/SkSLGLSLCodeGenerator.h"
9
10 #include "include/core/SkSpan.h"
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkSLDefines.h"
13 #include "include/private/SkSLLayout.h"
14 #include "include/private/SkSLModifiers.h"
15 #include "include/private/SkSLProgramElement.h"
16 #include "include/private/SkSLStatement.h"
17 #include "include/private/SkSLString.h"
18 #include "include/private/SkTArray.h"
19 #include "include/sksl/SkSLErrorReporter.h"
20 #include "include/sksl/SkSLPosition.h"
21 #include "src/sksl/SkSLBuiltinTypes.h"
22 #include "src/sksl/SkSLCompiler.h"
23 #include "src/sksl/SkSLGLSL.h"
24 #include "src/sksl/SkSLOutputStream.h"
25 #include "src/sksl/SkSLProgramSettings.h"
26 #include "src/sksl/SkSLUtil.h"
27 #include "src/sksl/ir/SkSLBinaryExpression.h"
28 #include "src/sksl/ir/SkSLBlock.h"
29 #include "src/sksl/ir/SkSLConstructor.h"
30 #include "src/sksl/ir/SkSLConstructorArrayCast.h"
31 #include "src/sksl/ir/SkSLConstructorDiagonalMatrix.h"
32 #include "src/sksl/ir/SkSLDoStatement.h"
33 #include "src/sksl/ir/SkSLExpression.h"
34 #include "src/sksl/ir/SkSLExpressionStatement.h"
35 #include "src/sksl/ir/SkSLExtension.h"
36 #include "src/sksl/ir/SkSLFieldAccess.h"
37 #include "src/sksl/ir/SkSLForStatement.h"
38 #include "src/sksl/ir/SkSLFunctionCall.h"
39 #include "src/sksl/ir/SkSLFunctionDeclaration.h"
40 #include "src/sksl/ir/SkSLFunctionDefinition.h"
41 #include "src/sksl/ir/SkSLFunctionPrototype.h"
42 #include "src/sksl/ir/SkSLIfStatement.h"
43 #include "src/sksl/ir/SkSLIndexExpression.h"
44 #include "src/sksl/ir/SkSLInterfaceBlock.h"
45 #include "src/sksl/ir/SkSLLiteral.h"
46 #include "src/sksl/ir/SkSLModifiersDeclaration.h"
47 #include "src/sksl/ir/SkSLPostfixExpression.h"
48 #include "src/sksl/ir/SkSLPrefixExpression.h"
49 #include "src/sksl/ir/SkSLProgram.h"
50 #include "src/sksl/ir/SkSLReturnStatement.h"
51 #include "src/sksl/ir/SkSLSetting.h"
52 #include "src/sksl/ir/SkSLStructDefinition.h"
53 #include "src/sksl/ir/SkSLSwitchCase.h"
54 #include "src/sksl/ir/SkSLSwitchStatement.h"
55 #include "src/sksl/ir/SkSLSwizzle.h"
56 #include "src/sksl/ir/SkSLTernaryExpression.h"
57 #include "src/sksl/ir/SkSLType.h"
58 #include "src/sksl/ir/SkSLVarDeclarations.h"
59 #include "src/sksl/ir/SkSLVariable.h"
60 #include "src/sksl/ir/SkSLVariableReference.h"
61 #include "src/sksl/spirv.h"
62
63 #include <memory>
64 #include <vector>
65
66 namespace SkSL {
67
68 void GLSLCodeGenerator::write(std::string_view s) {
69     if (!s.length()) {
70         return;
71     }
72     if (fAtLineStart) {
73         for (int i = 0; i < fIndentation; i++) {
74             fOut->writeText("    ");
75         }
76     }
77     fOut->write(s.data(), s.length());
78     fAtLineStart = false;
79 }
80
81 void GLSLCodeGenerator::writeLine(std::string_view s) {
82     this->write(s);
83     fOut->writeText("\n");
84     fAtLineStart = true;
85 }
86
87 void GLSLCodeGenerator::finishLine() {
88     if (!fAtLineStart) {
89         this->writeLine();
90     }
91 }
92
93 void GLSLCodeGenerator::writeExtension(std::string_view name, bool require) {
94     fExtensions.writeText("#extension ");
95     fExtensions.write(name.data(), name.length());
96     fExtensions.writeText(require ? " : require\n" : " : enable\n");
97 }
98
99 bool GLSLCodeGenerator::usesPrecisionModifiers() const {
100     return this->caps().usesPrecisionModifiers();
101 }
102
103 // Returns the name of the type with array dimensions, e.g. `float[2]`.
104 std::string GLSLCodeGenerator::getTypeName(const Type& raw) {
105     const Type& type = raw.resolve();
106     switch (type.typeKind()) {
107         case Type::TypeKind::kVector: {
108             const Type& component = type.componentType();
109             std::string result;
110             if (component.matches(*fContext.fTypes.fFloat) ||
111                 component.matches(*fContext.fTypes.fHalf)) {
112                 result = "vec";
113             }
114             else if (component.isSigned()) {
115                 result = "ivec";
116             }
117             else if (component.isUnsigned()) {
118                 result = "uvec";
119             }
120             else if (component.matches(*fContext.fTypes.fBool)) {
121                 result = "bvec";
122             }
123             else {
124                 SK_ABORT("unsupported vector type");
125             }
126             result += std::to_string(type.columns());
127             return result;
128         }
129         case Type::TypeKind::kMatrix: {
130             std::string result;
131             const Type& component = type.componentType();
132             if (component.matches(*fContext.fTypes.fFloat) ||
133                 component.matches(*fContext.fTypes.fHalf)) {
134                 result = "mat";
135             }
136             else {
137                 SK_ABORT("unsupported matrix type");
138             }
139             result += std::to_string(type.columns());
140             if (type.columns() != type.rows()) {
141                 result += "x";
142                 result += std::to_string(type.rows());
143             }
144             return result;
145         }
146         case Type::TypeKind::kArray: {
147             std::string baseTypeName = this->getTypeName(type.componentType());
148             return String::printf("%s[%d]", baseTypeName.c_str(), type.columns());
149         }
150         case Type::TypeKind::kScalar: {
151             if (type.matches(*fContext.fTypes.fHalf)) {
152                 return "float";
153             }
154             else if (type.matches(*fContext.fTypes.fShort)) {
155                 return "int";
156             }
157             else if (type.matches(*fContext.fTypes.fUShort)) {
158                 return "uint";
159             }
160             else {
161                 return std::string(type.name());
162             }
163             break;
164         }
165         default:
166             return std::string(type.name());
167     }
168 }
169
170 void GLSLCodeGenerator::writeStructDefinition(const StructDefinition& s) {
171     const Type& type = s.type();
172     this->write("struct ");
173     this->write(type.name());
174     this->writeLine(" {");
175     fIndentation++;
176     for (const auto& f : type.fields()) {
177         this->writeModifiers(f.fModifiers, false);
178         this->writeTypePrecision(*f.fType);
179         const Type& baseType = f.fType->isArray() ? f.fType->componentType() : *f.fType;
180         this->writeType(baseType);
181         this->write(" ");
182         this->write(f.fName);
183         if (f.fType->isArray()) {
184             this->write("[" + std::to_string(f.fType->columns()) + "]");
185         }
186         this->writeLine(";");
187     }
188     fIndentation--;
189     this->writeLine("};");
190 }
191
192 void GLSLCodeGenerator::writeType(const Type& type) {
193     this->write(this->getTypeName(type));
194 }
195
196 void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
197     switch (expr.kind()) {
198         case Expression::Kind::kBinary:
199             this->writeBinaryExpression(expr.as<BinaryExpression>(), parentPrecedence);
200             break;
201         case Expression::Kind::kConstructorDiagonalMatrix:
202             this->writeConstructorDiagonalMatrix(expr.as<ConstructorDiagonalMatrix>(),
203                                                  parentPrecedence);
204             break;
205         case Expression::Kind::kConstructorArrayCast:
206             this->writeExpression(*expr.as<ConstructorArrayCast>().argument(), parentPrecedence);
207             break;
208         case Expression::Kind::kConstructorArray:
209         case Expression::Kind::kConstructorCompound:
210         case Expression::Kind::kConstructorMatrixResize:
211         case Expression::Kind::kConstructorSplat:
212         case Expression::Kind::kConstructorStruct:
213             this->writeAnyConstructor(expr.asAnyConstructor(), parentPrecedence);
214             break;
215         case Expression::Kind::kConstructorScalarCast:
216         case Expression::Kind::kConstructorCompoundCast:
217             this->writeCastConstructor(expr.asAnyConstructor(), parentPrecedence);
218             break;
219         case Expression::Kind::kFieldAccess:
220             this->writeFieldAccess(expr.as<FieldAccess>());
221             break;
222         case Expression::Kind::kFunctionCall:
223             this->writeFunctionCall(expr.as<FunctionCall>());
224             break;
225         case Expression::Kind::kLiteral:
226             this->writeLiteral(expr.as<Literal>());
227             break;
228         case Expression::Kind::kPrefix:
229             this->writePrefixExpression(expr.as<PrefixExpression>(), parentPrecedence);
230             break;
231         case Expression::Kind::kPostfix:
232             this->writePostfixExpression(expr.as<PostfixExpression>(), parentPrecedence);
233             break;
234         case Expression::Kind::kSetting:
235             this->writeSetting(expr.as<Setting>());
236             break;
237         case Expression::Kind::kSwizzle:
238             this->writeSwizzle(expr.as<Swizzle>());
239             break;
240         case Expression::Kind::kVariableReference:
241             this->writeVariableReference(expr.as<VariableReference>());
242             break;
243         case Expression::Kind::kTernary:
244             this->writeTernaryExpression(expr.as<TernaryExpression>(), parentPrecedence);
245             break;
246         case Expression::Kind::kIndex:
247             this->writeIndexExpression(expr.as<IndexExpression>());
248             break;
249         default:
250             SkDEBUGFAILF("unsupported expression: %s", expr.description().c_str());
251             break;
252     }
253 }
254
255 static bool is_abs(Expression& expr) {
256     return expr.is<FunctionCall>() &&
257            expr.as<FunctionCall>().function().intrinsicKind() == k_abs_IntrinsicKind;
258 }
259
260 // turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
261 // Tegra3 compiler bug.
262 void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
263     SkASSERT(!this->caps().canUseMinAndAbsTogether());
264     std::string tmpVar1 = "minAbsHackVar" + std::to_string(fVarCount++);
265     std::string tmpVar2 = "minAbsHackVar" + std::to_string(fVarCount++);
266     this->fFunctionHeader += std::string("    ") + this->getTypePrecision(absExpr.type()) +
267                              this->getTypeName(absExpr.type()) + " " + tmpVar1 + ";\n";
268     this->fFunctionHeader += std::string("    ") + this->getTypePrecision(otherExpr.type()) +
269                              this->getTypeName(otherExpr.type()) + " " + tmpVar2 + ";\n";
270     this->write("((" + tmpVar1 + " = ");
271     this->writeExpression(absExpr, Precedence::kTopLevel);
272     this->write(") < (" + tmpVar2 + " = ");
273     this->writeExpression(otherExpr, Precedence::kAssignment);
274     this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
275 }
276
277 void GLSLCodeGenerator::writeInverseSqrtHack(const Expression& x) {
278     this->write("(1.0 / sqrt(");
279     this->writeExpression(x, Precedence::kTopLevel);
280     this->write("))");
281 }
282
283 void GLSLCodeGenerator::writeDeterminantHack(const Expression& mat) {
284     std::string name;
285     const Type& type = mat.type();
286     if (type.matches(*fContext.fTypes.fFloat2x2) || type.matches(*fContext.fTypes.fHalf2x2)) {
287         name = "_determinant2";
288         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
289             fWrittenIntrinsics.insert(name);
290             fExtraFunctions.writeText((
291                 "float " + name + "(mat2 m) {"
292                 "    return m[0][0] * m[1][1] - m[0][1] * m[1][0];"
293                 "}"
294             ).c_str());
295         }
296     }
297     else if (type.matches(*fContext.fTypes.fFloat3x3) || type.matches(*fContext.fTypes.fHalf3x3)) {
298         name = "_determinant3";
299         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
300             fWrittenIntrinsics.insert(name);
301             fExtraFunctions.writeText((
302                 "float " + name + "(mat3 m) {"
303                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
304                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
305                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
306                 "    float b01 = a22 * a11 - a12 * a21;"
307                 "    float b11 = -a22 * a10 + a12 * a20;"
308                 "    float b21 = a21 * a10 - a11 * a20;"
309                 "    return a00 * b01 + a01 * b11 + a02 * b21;"
310                 "}"
311             ).c_str());
312         }
313     }
314     else if (type.matches(*fContext.fTypes.fFloat4x4) || type.matches(*fContext.fTypes.fHalf4x4)) {
315         name = "_determinant4";
316         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
317             fWrittenIntrinsics.insert(name);
318             fExtraFunctions.writeText((
319                 "mat4 " + name + "(mat4 m) {"
320                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
321                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
322                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
323                 "    float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
324                 "    float b00 = a00 * a11 - a01 * a10;"
325                 "    float b01 = a00 * a12 - a02 * a10;"
326                 "    float b02 = a00 * a13 - a03 * a10;"
327                 "    float b03 = a01 * a12 - a02 * a11;"
328                 "    float b04 = a01 * a13 - a03 * a11;"
329                 "    float b05 = a02 * a13 - a03 * a12;"
330                 "    float b06 = a20 * a31 - a21 * a30;"
331                 "    float b07 = a20 * a32 - a22 * a30;"
332                 "    float b08 = a20 * a33 - a23 * a30;"
333                 "    float b09 = a21 * a32 - a22 * a31;"
334                 "    float b10 = a21 * a33 - a23 * a31;"
335                 "    float b11 = a22 * a33 - a23 * a32;"
336                 "    return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;"
337                 "}"
338             ).c_str());
339         }
340     }
341     else {
342         SkASSERT(false);
343     }
344     this->write(name + "(");
345     this->writeExpression(mat, Precedence::kTopLevel);
346     this->write(")");
347 }
348
349 void GLSLCodeGenerator::writeInverseHack(const Expression& mat) {
350     std::string name;
351     const Type& type = mat.type();
352     if (type.matches(*fContext.fTypes.fFloat2x2) || type.matches(*fContext.fTypes.fHalf2x2)) {
353         name = "_inverse2";
354         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
355             fWrittenIntrinsics.insert(name);
356             fExtraFunctions.writeText((
357                 "mat2 " + name + "(mat2 m) {"
358                 "    return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / "
359                                "(m[0][0] * m[1][1] - m[0][1] * m[1][0]);"
360                 "}"
361             ).c_str());
362         }
363     }
364     else if (type.matches(*fContext.fTypes.fFloat3x3) || type.matches(*fContext.fTypes.fHalf3x3)) {
365         name = "_inverse3";
366         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
367             fWrittenIntrinsics.insert(name);
368             fExtraFunctions.writeText((
369                 "mat3 " +  name + "(mat3 m) {"
370                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
371                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
372                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
373                 "    float b01 = a22 * a11 - a12 * a21;"
374                 "    float b11 = -a22 * a10 + a12 * a20;"
375                 "    float b21 = a21 * a10 - a11 * a20;"
376                 "    float det = a00 * b01 + a01 * b11 + a02 * b21;"
377                 "    return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),"
378                 "                b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),"
379                 "                b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;"
380                 "}"
381             ).c_str());
382         }
383     }
384     else if (type.matches(*fContext.fTypes.fFloat4x4) || type.matches(*fContext.fTypes.fHalf4x4)) {
385         name = "_inverse4";
386         if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
387             fWrittenIntrinsics.insert(name);
388             fExtraFunctions.writeText((
389                 "mat4 " + name + "(mat4 m) {"
390                 "    float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
391                 "    float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
392                 "    float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
393                 "    float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
394                 "    float b00 = a00 * a11 - a01 * a10;"
395                 "    float b01 = a00 * a12 - a02 * a10;"
396                 "    float b02 = a00 * a13 - a03 * a10;"
397                 "    float b03 = a01 * a12 - a02 * a11;"
398                 "    float b04 = a01 * a13 - a03 * a11;"
399                 "    float b05 = a02 * a13 - a03 * a12;"
400                 "    float b06 = a20 * a31 - a21 * a30;"
401                 "    float b07 = a20 * a32 - a22 * a30;"
402                 "    float b08 = a20 * a33 - a23 * a30;"
403                 "    float b09 = a21 * a32 - a22 * a31;"
404                 "    float b10 = a21 * a33 - a23 * a31;"
405                 "    float b11 = a22 * a33 - a23 * a32;"
406                 "    float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - "
407                 "                b04 * b07 + b05 * b06;"
408                 "    return mat4("
409                 "        a11 * b11 - a12 * b10 + a13 * b09,"
410                 "        a02 * b10 - a01 * b11 - a03 * b09,"
411                 "        a31 * b05 - a32 * b04 + a33 * b03,"
412                 "        a22 * b04 - a21 * b05 - a23 * b03,"
413                 "        a12 * b08 - a10 * b11 - a13 * b07,"
414                 "        a00 * b11 - a02 * b08 + a03 * b07,"
415                 "        a32 * b02 - a30 * b05 - a33 * b01,"
416                 "        a20 * b05 - a22 * b02 + a23 * b01,"
417                 "        a10 * b10 - a11 * b08 + a13 * b06,"
418                 "        a01 * b08 - a00 * b10 - a03 * b06,"
419                 "        a30 * b04 - a31 * b02 + a33 * b00,"
420                 "        a21 * b02 - a20 * b04 - a23 * b00,"
421                 "        a11 * b07 - a10 * b09 - a12 * b06,"
422                 "        a00 * b09 - a01 * b07 + a02 * b06,"
423                 "        a31 * b01 - a30 * b03 - a32 * b00,"
424                 "        a20 * b03 - a21 * b01 + a22 * b00) / det;"
425                 "}"
426             ).c_str());
427         }
428     }
429     else {
430         SkASSERT(false);
431     }
432     this->write(name + "(");
433     this->writeExpression(mat, Precedence::kTopLevel);
434     this->write(")");
435 }
436
437 void GLSLCodeGenerator::writeTransposeHack(const Expression& mat) {
438     const Type& type = mat.type();
439     std::string name = "transpose" + std::to_string(type.columns()) + std::to_string(type.rows());
440     if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
441         fWrittenIntrinsics.insert(name);
442         std::string typeName = this->getTypeName(type);
443         const Type& base = type.componentType();
444         std::string transposed =  this->getTypeName(base.toCompound(fContext,
445                                                                type.rows(),
446                                                                type.columns()));
447         fExtraFunctions.writeText((transposed + " " + name + "(" + typeName + " m) {\nreturn " +
448                                   transposed + "(").c_str());
449         const char* separator = "";
450         for (int row = 0; row < type.rows(); ++row) {
451             for (int column = 0; column < type.columns(); ++column) {
452                 fExtraFunctions.writeText(separator);
453                 fExtraFunctions.writeText(("m[" + std::to_string(column) + "][" +
454                                            std::to_string(row) + "]").c_str());
455                 separator = ", ";
456             }
457         }
458         fExtraFunctions.writeText("); }");
459     }
460     this->write(name + "(");
461     this->writeExpression(mat, Precedence::kTopLevel);
462     this->write(")");
463 }
464
465 void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
466     const FunctionDeclaration& function = c.function();
467     const ExpressionArray& arguments = c.arguments();
468     bool isTextureFunctionWithBias = false;
469     bool nameWritten = false;
470     const char* closingParen = ")";
471     switch (c.function().intrinsicKind()) {
472         case k_abs_IntrinsicKind: {
473             if (!this->caps().emulateAbsIntFunction())
474                 break;
475             SkASSERT(arguments.size() == 1);
476             if (!arguments[0]->type().matches(*fContext.fTypes.fInt)) {
477                 break;
478             }
479             // abs(int) on Intel OSX is incorrect, so emulate it:
480             std::string name = "_absemulation";
481             this->write(name);
482             nameWritten = true;
483             if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
484                 fWrittenIntrinsics.insert(name);
485                 fExtraFunctions.writeText((
486                     "int " + name + "(int x) {\n"
487                     "    return x * sign(x);\n"
488                     "}\n"
489                 ).c_str());
490             }
491             break;
492         }
493         case k_atan_IntrinsicKind:
494             if (this->caps().mustForceNegatedAtanParamToFloat() &&
495                 arguments.size() == 2 &&
496                 arguments[1]->kind() == Expression::Kind::kPrefix) {
497                 const PrefixExpression& p = (PrefixExpression&) *arguments[1];
498                 if (p.getOperator().kind() == Operator::Kind::MINUS) {
499                     this->write("atan(");
500                     this->writeExpression(*arguments[0], Precedence::kSequence);
501                     this->write(", -1.0 * ");
502                     this->writeExpression(*p.operand(), Precedence::kMultiplicative);
503                     this->write(")");
504                     return;
505                 }
506             }
507             break;
508         case k_ldexp_IntrinsicKind:
509             if (this->caps().mustForceNegatedLdexpParamToMultiply() &&
510                 arguments.size() == 2 &&
511                 arguments[1]->is<PrefixExpression>()) {
512                 const PrefixExpression& p = arguments[1]->as<PrefixExpression>();
513                 if (p.getOperator().kind() == Operator::Kind::MINUS) {
514                     this->write("ldexp(");
515                     this->writeExpression(*arguments[0], Precedence::kSequence);
516                     this->write(", ");
517                     this->writeExpression(*p.operand(), Precedence::kMultiplicative);
518                     this->write(" * -1)");
519                     return;
520                 }
521             }
522             break;
523         case k_dFdy_IntrinsicKind:
524             // Flipping Y also negates the Y derivatives.
525             closingParen = "))";
526             this->write("(");
527             if (!fProgram.fConfig->fSettings.fForceNoRTFlip) {
528                 this->write(SKSL_RTFLIP_NAME ".y * ");
529             }
530             this->write("dFdy");
531             nameWritten = true;
532             [[fallthrough]];
533         case k_dFdx_IntrinsicKind:
534         case k_fwidth_IntrinsicKind:
535             if (!fFoundDerivatives &&
536                 this->caps().shaderDerivativeExtensionString()) {
537                 this->writeExtension(this->caps().shaderDerivativeExtensionString());
538                 fFoundDerivatives = true;
539             }
540             break;
541         case k_determinant_IntrinsicKind:
542             if (!this->caps().builtinDeterminantSupport()) {
543                 SkASSERT(arguments.size() == 1);
544                 this->writeDeterminantHack(*arguments[0]);
545                 return;
546             }
547             break;
548         case k_fma_IntrinsicKind:
549             if (!this->caps().builtinFMASupport()) {
550                 SkASSERT(arguments.size() == 3);
551                 this->write("((");
552                 this->writeExpression(*arguments[0], Precedence::kSequence);
553                 this->write(") * (");
554                 this->writeExpression(*arguments[1], Precedence::kSequence);
555                 this->write(") + (");
556                 this->writeExpression(*arguments[2], Precedence::kSequence);
557                 this->write("))");
558                 return;
559             }
560             break;
561         case k_fract_IntrinsicKind:
562             if (!this->caps().canUseFractForNegativeValues()) {
563                 SkASSERT(arguments.size() == 1);
564                 this->write("(0.5 - sign(");
565                 this->writeExpression(*arguments[0], Precedence::kSequence);
566                 this->write(") * (0.5 - fract(abs(");
567                 this->writeExpression(*arguments[0], Precedence::kSequence);
568                 this->write("))))");
569                 return;
570             }
571             break;
572         case k_inverse_IntrinsicKind:
573             if (this->caps().generation() < SkSL::GLSLGeneration::k140) {
574                 SkASSERT(arguments.size() == 1);
575                 this->writeInverseHack(*arguments[0]);
576                 return;
577             }
578             break;
579         case k_inversesqrt_IntrinsicKind:
580             if (this->caps().generation() < SkSL::GLSLGeneration::k130) {
581                 SkASSERT(arguments.size() == 1);
582                 this->writeInverseSqrtHack(*arguments[0]);
583                 return;
584             }
585             break;
586         case k_min_IntrinsicKind:
587             if (!this->caps().canUseMinAndAbsTogether()) {
588                 SkASSERT(arguments.size() == 2);
589                 if (is_abs(*arguments[0])) {
590                     this->writeMinAbsHack(*arguments[0], *arguments[1]);
591                     return;
592                 }
593                 if (is_abs(*arguments[1])) {
594                     // note that this violates the GLSL left-to-right evaluation semantics.
595                     // I doubt it will ever end up mattering, but it's worth calling out.
596                     this->writeMinAbsHack(*arguments[1], *arguments[0]);
597                     return;
598                 }
599             }
600             break;
601         case k_pow_IntrinsicKind:
602             if (!this->caps().removePowWithConstantExponent()) {
603                 break;
604             }
605             // pow(x, y) on some NVIDIA drivers causes crashes if y is a
606             // constant.  It's hard to tell what constitutes "constant" here
607             // so just replace in all cases.
608
609             // Change pow(x, y) into exp2(y * log2(x))
610             this->write("exp2(");
611             this->writeExpression(*arguments[1], Precedence::kMultiplicative);
612             this->write(" * log2(");
613             this->writeExpression(*arguments[0], Precedence::kSequence);
614             this->write("))");
615             return;
616         case k_saturate_IntrinsicKind:
617             SkASSERT(arguments.size() == 1);
618             this->write("clamp(");
619             this->writeExpression(*arguments[0], Precedence::kSequence);
620             this->write(", 0.0, 1.0)");
621             return;
622         case k_sample_IntrinsicKind: {
623             const char* dim = "";
624             bool proj = false;
625             const Type& arg0Type = arguments[0]->type();
626             const Type& arg1Type = arguments[1]->type();
627             switch (arg0Type.dimensions()) {
628                 case SpvDim1D:
629                     dim = "1D";
630                     isTextureFunctionWithBias = true;
631                     if (arg1Type.matches(*fContext.fTypes.fFloat)) {
632                         proj = false;
633                     } else {
634                         SkASSERT(arg1Type.matches(*fContext.fTypes.fFloat2));
635                         proj = true;
636                     }
637                     break;
638                 case SpvDim2D:
639                     dim = "2D";
640                     if (!arg0Type.matches(*fContext.fTypes.fSamplerExternalOES)) {
641                         isTextureFunctionWithBias = true;
642                     }
643                     if (arg1Type.matches(*fContext.fTypes.fFloat2)) {
644                         proj = false;
645                     } else {
646                         SkASSERT(arg1Type.matches(*fContext.fTypes.fFloat3));
647                         proj = true;
648                     }
649                     break;
650                 case SpvDim3D:
651                     dim = "3D";
652                     isTextureFunctionWithBias = true;
653                     if (arg1Type.matches(*fContext.fTypes.fFloat3)) {
654                         proj = false;
655                     } else {
656                         SkASSERT(arg1Type.matches(*fContext.fTypes.fFloat4));
657                         proj = true;
658                     }
659                     break;
660                 case SpvDimCube:
661                     dim = "Cube";
662                     isTextureFunctionWithBias = true;
663                     proj = false;
664                     break;
665                 case SpvDimRect:
666                     dim = "2DRect";
667                     proj = false;
668                     break;
669                 case SpvDimBuffer:
670                     SkASSERT(false); // doesn't exist
671                     dim = "Buffer";
672                     proj = false;
673                     break;
674                 case SpvDimSubpassData:
675                     SkASSERT(false); // doesn't exist
676                     dim = "SubpassData";
677                     proj = false;
678                     break;
679             }
680             this->write("texture");
681             if (this->caps().generation() < SkSL::GLSLGeneration::k130) {
682                 this->write(dim);
683             }
684             if (proj) {
685                 this->write("Proj");
686             }
687             nameWritten = true;
688             break;
689         }
690         case k_transpose_IntrinsicKind:
691             if (this->caps().generation() < SkSL::GLSLGeneration::k130) {
692                 SkASSERT(arguments.size() == 1);
693                 this->writeTransposeHack(*arguments[0]);
694                 return;
695             }
696             break;
697         default:
698             break;
699     }
700
701     if (!nameWritten) {
702         this->write(function.mangledName());
703     }
704     this->write("(");
705     const char* separator = "";
706     for (const auto& arg : arguments) {
707         this->write(separator);
708         separator = ", ";
709         this->writeExpression(*arg, Precedence::kSequence);
710     }
711     if (fProgram.fConfig->fSettings.fSharpenTextures && isTextureFunctionWithBias) {
712         this->write(String::printf(", %g", kSharpenTexturesBias));
713     }
714     this->write(closingParen);
715 }
716
717 void GLSLCodeGenerator::writeConstructorDiagonalMatrix(const ConstructorDiagonalMatrix& c,
718                                                        Precedence parentPrecedence) {
719     if (c.type().columns() == 4 && c.type().rows() == 2) {
720         // Due to a longstanding bug in glslang and Mesa, several GPU drivers generate diagonal 4x2
721         // matrices incorrectly. (skia:12003, https://github.com/KhronosGroup/glslang/pull/2646)
722         // We can work around this issue by multiplying a scalar by the identity matrix.
723         // In practice, this doesn't come up naturally in real code and we don't know every affected
724         // driver, so we just apply this workaround everywhere.
725         this->write("(");
726         this->writeType(c.type());
727         this->write("(1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0) * ");
728         this->writeExpression(*c.argument(), Precedence::kMultiplicative);
729         this->write(")");
730         return;
731     }
732     this->writeAnyConstructor(c, parentPrecedence);
733 }
734
735 void GLSLCodeGenerator::writeCastConstructor(const AnyConstructor& c, Precedence parentPrecedence) {
736     const auto arguments = c.argumentSpan();
737     SkASSERT(arguments.size() == 1);
738
739     const Expression& argument = *arguments.front();
740     if ((this->getTypeName(c.type()) == this->getTypeName(argument.type()) ||
741          (argument.type().matches(*fContext.fTypes.fFloatLiteral)))) {
742         // In cases like half(float), they're different types as far as SkSL is concerned but
743         // the same type as far as GLSL is concerned. We avoid a redundant float(float) by just
744         // writing out the inner expression here.
745         this->writeExpression(argument, parentPrecedence);
746         return;
747     }
748
749     // This cast should be emitted as-is.
750     return this->writeAnyConstructor(c, parentPrecedence);
751 }
752
753 void GLSLCodeGenerator::writeAnyConstructor(const AnyConstructor& c, Precedence parentPrecedence) {
754     this->writeType(c.type());
755     this->write("(");
756     const char* separator = "";
757     for (const auto& arg : c.argumentSpan()) {
758         this->write(separator);
759         separator = ", ";
760         this->writeExpression(*arg, Precedence::kSequence);
761     }
762     this->write(")");
763 }
764
765 void GLSLCodeGenerator::writeFragCoord() {
766     if (!this->caps().canUseFragCoord()) {
767         if (!fSetupFragCoordWorkaround) {
768             const char* precision = usesPrecisionModifiers() ? "highp " : "";
769             fFunctionHeader += precision;
770             fFunctionHeader += "    float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n";
771             fFunctionHeader += precision;
772             fFunctionHeader += "    vec4 sk_FragCoord_Resolved = "
773                 "vec4(sk_FragCoord_Workaround.xyz * sk_FragCoord_InvW, sk_FragCoord_InvW);\n";
774             // Ensure that we get exact .5 values for x and y.
775             fFunctionHeader += "    sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + "
776                                "vec2(.5);\n";
777             fSetupFragCoordWorkaround = true;
778         }
779         this->write("sk_FragCoord_Resolved");
780         return;
781     }
782
783     if (!fSetupFragPosition) {
784         fFunctionHeader += this->usesPrecisionModifiers() ? "highp " : "";
785         fFunctionHeader += "    vec4 sk_FragCoord = vec4("
786                 "gl_FragCoord.x, ";
787         if (fProgram.fConfig->fSettings.fForceNoRTFlip) {
788             fFunctionHeader += "gl_FragCoord.y, ";
789         } else {
790             fFunctionHeader += SKSL_RTFLIP_NAME ".x + " SKSL_RTFLIP_NAME ".y * gl_FragCoord.y, ";
791         }
792         fFunctionHeader +=
793                 "gl_FragCoord.z, "
794                 "gl_FragCoord.w);\n";
795         fSetupFragPosition = true;
796     }
797     this->write("sk_FragCoord");
798 }
799
800 void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
801     switch (ref.variable()->modifiers().fLayout.fBuiltin) {
802         case SK_FRAGCOLOR_BUILTIN:
803             if (this->caps().mustDeclareFragmentShaderOutput()) {
804                 this->write("sk_FragColor");
805             } else {
806                 this->write("gl_FragColor");
807             }
808             break;
809         case SK_SECONDARYFRAGCOLOR_BUILTIN:
810             this->write("gl_SecondaryFragColorEXT");
811             break;
812         case SK_FRAGCOORD_BUILTIN:
813             this->writeFragCoord();
814             break;
815         case SK_CLOCKWISE_BUILTIN:
816             if (!fSetupClockwise) {
817                 fFunctionHeader += "    bool sk_Clockwise = gl_FrontFacing;\n";
818                 if (!fProgram.fConfig->fSettings.fForceNoRTFlip) {
819                     fFunctionHeader += "    if (" SKSL_RTFLIP_NAME ".y < 0.0) {\n"
820                                        "        sk_Clockwise = !sk_Clockwise;\n"
821                                        "    }\n";
822                 }
823                 fSetupClockwise = true;
824             }
825             this->write("sk_Clockwise");
826             break;
827         case SK_VERTEXID_BUILTIN:
828             this->write("gl_VertexID");
829             break;
830         case SK_INSTANCEID_BUILTIN:
831             this->write("gl_InstanceID");
832             break;
833         case SK_LASTFRAGCOLOR_BUILTIN:
834             if (this->caps().fbFetchSupport()) {
835                 this->write(this->caps().fbFetchColorName());
836             } else {
837                 fContext.fErrors->error(ref.fPosition,
838                                         "sk_LastFragColor requires framebuffer fetch support");
839             }
840             break;
841         default:
842             this->write(ref.variable()->name());
843             break;
844     }
845 }
846
847 void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
848     this->writeExpression(*expr.base(), Precedence::kPostfix);
849     this->write("[");
850     this->writeExpression(*expr.index(), Precedence::kTopLevel);
851     this->write("]");
852 }
853
854 bool is_sk_position(const FieldAccess& f) {
855     return f.base()->type().fields()[f.fieldIndex()].fModifiers.fLayout.fBuiltin ==
856            SK_POSITION_BUILTIN;
857 }
858
859 void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
860     if (f.ownerKind() == FieldAccess::OwnerKind::kDefault) {
861         this->writeExpression(*f.base(), Precedence::kPostfix);
862         this->write(".");
863     }
864     const Type& baseType = f.base()->type();
865     int builtin = baseType.fields()[f.fieldIndex()].fModifiers.fLayout.fBuiltin;
866     if (builtin == SK_POSITION_BUILTIN) {
867         this->write("gl_Position");
868     } else if (builtin == SK_POINTSIZE_BUILTIN) {
869         this->write("gl_PointSize");
870     } else {
871         this->write(baseType.fields()[f.fieldIndex()].fName);
872     }
873 }
874
875 void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
876     this->writeExpression(*swizzle.base(), Precedence::kPostfix);
877     this->write(".");
878     for (int c : swizzle.components()) {
879         SkASSERT(c >= 0 && c <= 3);
880         this->write(&("x\0y\0z\0w\0"[c * 2]));
881     }
882 }
883
884 void GLSLCodeGenerator::writeMatrixComparisonWorkaround(const BinaryExpression& b) {
885     const Expression& left = *b.left();
886     const Expression& right = *b.right();
887     Operator op = b.getOperator();
888
889     SkASSERT(op.kind() == Operator::Kind::EQEQ || op.kind() == Operator::Kind::NEQ);
890     SkASSERT(left.type().isMatrix());
891     SkASSERT(right.type().isMatrix());
892
893     std::string tempMatrix1 = "_tempMatrix" + std::to_string(fVarCount++);
894     std::string tempMatrix2 = "_tempMatrix" + std::to_string(fVarCount++);
895
896     this->fFunctionHeader += std::string("    ") + this->getTypePrecision(left.type()) +
897                              this->getTypeName(left.type()) + " " + tempMatrix1 + ";\n    " +
898                              this->getTypePrecision(right.type()) +
899                              this->getTypeName(right.type()) + " " + tempMatrix2 + ";\n";
900     this->write("((" + tempMatrix1 + " = ");
901     this->writeExpression(left, Precedence::kAssignment);
902     this->write("), (" + tempMatrix2 + " = ");
903     this->writeExpression(right, Precedence::kAssignment);
904     this->write("), (" + tempMatrix1);
905     this->write(op.operatorName());
906     this->write(tempMatrix2 + "))");
907 }
908
909 void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
910                                               Precedence parentPrecedence) {
911     const Expression& left = *b.left();
912     const Expression& right = *b.right();
913     Operator op = b.getOperator();
914     if (this->caps().unfoldShortCircuitAsTernary() &&
915             (op.kind() == Operator::Kind::LOGICALAND || op.kind() == Operator::Kind::LOGICALOR)) {
916         this->writeShortCircuitWorkaroundExpression(b, parentPrecedence);
917         return;
918     }
919
920     if (this->caps().rewriteMatrixComparisons() &&
921             left.type().isMatrix() && right.type().isMatrix() &&
922             (op.kind() == Operator::Kind::EQEQ || op.kind() == Operator::Kind::NEQ)) {
923         this->writeMatrixComparisonWorkaround(b);
924         return;
925     }
926
927     Precedence precedence = op.getBinaryPrecedence();
928     if (precedence >= parentPrecedence) {
929         this->write("(");
930     }
931     bool positionWorkaround = ProgramConfig::IsVertex(fProgram.fConfig->fKind) &&
932                               op.isAssignment() &&
933                               left.is<FieldAccess>() &&
934                               is_sk_position(left.as<FieldAccess>()) &&
935                               !right.containsRTAdjust() &&
936                               !this->caps().canUseFragCoord();
937     if (positionWorkaround) {
938         this->write("sk_FragCoord_Workaround = (");
939     }
940     this->writeExpression(left, precedence);
941     this->write(op.operatorName());
942     this->writeExpression(right, precedence);
943     if (positionWorkaround) {
944         this->write(")");
945     }
946     if (precedence >= parentPrecedence) {
947         this->write(")");
948     }
949 }
950
951 void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpression& b,
952                                                               Precedence parentPrecedence) {
953     if (Precedence::kTernary >= parentPrecedence) {
954         this->write("(");
955     }
956
957     // Transform:
958     // a && b  =>   a ? b : false
959     // a || b  =>   a ? true : b
960     this->writeExpression(*b.left(), Precedence::kTernary);
961     this->write(" ? ");
962     if (b.getOperator().kind() == Operator::Kind::LOGICALAND) {
963         this->writeExpression(*b.right(), Precedence::kTernary);
964     } else {
965         Literal boolTrue(Position(), /*value=*/1, fContext.fTypes.fBool.get());
966         this->writeLiteral(boolTrue);
967     }
968     this->write(" : ");
969     if (b.getOperator().kind() == Operator::Kind::LOGICALAND) {
970         Literal boolFalse(Position(), /*value=*/0, fContext.fTypes.fBool.get());
971         this->writeLiteral(boolFalse);
972     } else {
973         this->writeExpression(*b.right(), Precedence::kTernary);
974     }
975     if (Precedence::kTernary >= parentPrecedence) {
976         this->write(")");
977     }
978 }
979
980 void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
981                                                Precedence parentPrecedence) {
982     if (Precedence::kTernary >= parentPrecedence) {
983         this->write("(");
984     }
985     this->writeExpression(*t.test(), Precedence::kTernary);
986     this->write(" ? ");
987     this->writeExpression(*t.ifTrue(), Precedence::kTernary);
988     this->write(" : ");
989     this->writeExpression(*t.ifFalse(), Precedence::kTernary);
990     if (Precedence::kTernary >= parentPrecedence) {
991         this->write(")");
992     }
993 }
994
995 void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
996                                               Precedence parentPrecedence) {
997     if (Precedence::kPrefix >= parentPrecedence) {
998         this->write("(");
999     }
1000     this->write(p.getOperator().tightOperatorName());
1001     this->writeExpression(*p.operand(), Precedence::kPrefix);
1002     if (Precedence::kPrefix >= parentPrecedence) {
1003         this->write(")");
1004     }
1005 }
1006
1007 void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
1008                                                Precedence parentPrecedence) {
1009     if (Precedence::kPostfix >= parentPrecedence) {
1010         this->write("(");
1011     }
1012     this->writeExpression(*p.operand(), Precedence::kPostfix);
1013     this->write(p.getOperator().tightOperatorName());
1014     if (Precedence::kPostfix >= parentPrecedence) {
1015         this->write(")");
1016     }
1017 }
1018
1019 void GLSLCodeGenerator::writeLiteral(const Literal& l) {
1020     const Type& type = l.type();
1021     if (type.isFloat()) {
1022         this->write(skstd::to_string(l.floatValue()));
1023         return;
1024     }
1025     if (type.isInteger()) {
1026         if (type.matches(*fContext.fTypes.fUInt)) {
1027             this->write(std::to_string(l.intValue() & 0xffffffff) + "u");
1028         } else if (type.matches(*fContext.fTypes.fUShort)) {
1029             this->write(std::to_string(l.intValue() & 0xffff) + "u");
1030         } else {
1031             this->write(std::to_string(l.intValue()));
1032         }
1033         return;
1034     }
1035     SkASSERT(type.isBoolean());
1036     this->write(l.boolValue() ? "true" : "false");
1037 }
1038
1039 void GLSLCodeGenerator::writeSetting(const Setting& s) {
1040     SK_ABORT("internal error; setting was not folded to a constant during compilation\n");
1041 }
1042
1043 void GLSLCodeGenerator::writeFunctionDeclaration(const FunctionDeclaration& f) {
1044     this->writeTypePrecision(f.returnType());
1045     this->writeType(f.returnType());
1046     this->write(" " + f.mangledName() + "(");
1047     const char* separator = "";
1048     for (const auto& param : f.parameters()) {
1049         // This is a workaround for our test files. They use the runtime effect signature, so main
1050         // takes a coords parameter. The IR generator tags those with a builtin ID (sk_FragCoord),
1051         // and we omit them from the declaration here, so the function is valid GLSL.
1052         if (f.isMain() && param->modifiers().fLayout.fBuiltin != -1) {
1053             continue;
1054         }
1055         this->write(separator);
1056         separator = ", ";
1057         this->writeModifiers(param->modifiers(), false);
1058         std::vector<int> sizes;
1059         const Type* type = &param->type();
1060         if (type->isArray()) {
1061             sizes.push_back(type->columns());
1062             type = &type->componentType();
1063         }
1064         this->writeTypePrecision(*type);
1065         this->writeType(*type);
1066         this->write(" " + std::string(param->name()));
1067         for (int s : sizes) {
1068             this->write("[" + std::to_string(s) + "]");
1069         }
1070     }
1071     this->write(")");
1072 }
1073
1074 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
1075     fSetupFragPosition = false;
1076     fSetupFragCoordWorkaround = false;
1077
1078     this->writeFunctionDeclaration(f.declaration());
1079     this->writeLine(" {");
1080     fIndentation++;
1081
1082     fFunctionHeader.clear();
1083     OutputStream* oldOut = fOut;
1084     StringStream buffer;
1085     fOut = &buffer;
1086     for (const std::unique_ptr<Statement>& stmt : f.body()->as<Block>().children()) {
1087         if (!stmt->isEmpty()) {
1088             this->writeStatement(*stmt);
1089             this->finishLine();
1090         }
1091     }
1092
1093     fIndentation--;
1094     this->writeLine("}");
1095
1096     fOut = oldOut;
1097     this->write(fFunctionHeader);
1098     this->write(buffer.str());
1099 }
1100
1101 void GLSLCodeGenerator::writeFunctionPrototype(const FunctionPrototype& f) {
1102     this->writeFunctionDeclaration(f.declaration());
1103     this->writeLine(";");
1104 }
1105
1106 void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
1107                                        bool globalContext) {
1108     std::string layout = modifiers.fLayout.description();
1109     if (layout.size()) {
1110         this->write(layout + " ");
1111     }
1112
1113     // For GLSL 4.1 and below, qualifier-order matters! These are written out in Modifier-bit order.
1114     if (modifiers.fFlags & Modifiers::kFlat_Flag) {
1115         this->write("flat ");
1116     }
1117     if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
1118         this->write("noperspective ");
1119     }
1120
1121     if (modifiers.fFlags & Modifiers::kConst_Flag) {
1122         this->write("const ");
1123     }
1124     if (modifiers.fFlags & Modifiers::kUniform_Flag) {
1125         this->write("uniform ");
1126     }
1127     if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
1128         (modifiers.fFlags & Modifiers::kOut_Flag)) {
1129         this->write("inout ");
1130     } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
1131         if (globalContext && this->caps().generation() < SkSL::GLSLGeneration::k130) {
1132             this->write(ProgramConfig::IsVertex(fProgram.fConfig->fKind) ? "attribute "
1133                                                                          : "varying ");
1134         } else {
1135             this->write("in ");
1136         }
1137     } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
1138         if (globalContext &&
1139             this->caps().generation() < SkSL::GLSLGeneration::k130) {
1140             this->write("varying ");
1141         } else {
1142             this->write("out ");
1143         }
1144     }
1145
1146 }
1147
1148 void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
1149     if (intf.typeName() == "sk_PerVertex") {
1150         return;
1151     }
1152     this->writeModifiers(intf.variable().modifiers(), true);
1153     this->writeLine(std::string(intf.typeName()) + " {");
1154     fIndentation++;
1155     const Type* structType = &intf.variable().type();
1156     if (structType->isArray()) {
1157         structType = &structType->componentType();
1158     }
1159     for (const auto& f : structType->fields()) {
1160         this->writeModifiers(f.fModifiers, false);
1161         this->writeTypePrecision(*f.fType);
1162         this->writeType(*f.fType);
1163         this->writeLine(" " + std::string(f.fName) + ";");
1164     }
1165     fIndentation--;
1166     this->write("}");
1167     if (intf.instanceName().size()) {
1168         this->write(" ");
1169         this->write(intf.instanceName());
1170         if (intf.arraySize() > 0) {
1171             this->write("[");
1172             this->write(std::to_string(intf.arraySize()));
1173             this->write("]");
1174         }
1175     }
1176     this->writeLine(";");
1177 }
1178
1179 void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
1180     this->writeExpression(value, Precedence::kTopLevel);
1181 }
1182
1183 const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
1184     if (usesPrecisionModifiers()) {
1185         switch (type.typeKind()) {
1186             case Type::TypeKind::kScalar:
1187                 if (type.matches(*fContext.fTypes.fShort) ||
1188                     type.matches(*fContext.fTypes.fUShort)) {
1189                     if (fProgram.fConfig->fSettings.fForceHighPrecision ||
1190                             this->caps().incompleteShortIntPrecision()) {
1191                         return "highp ";
1192                     }
1193                     return "mediump ";
1194                 }
1195                 if (type.matches(*fContext.fTypes.fHalf)) {
1196                     return fProgram.fConfig->fSettings.fForceHighPrecision ? "highp " : "mediump ";
1197                 }
1198                 if (type.matches(*fContext.fTypes.fFloat) || type.matches(*fContext.fTypes.fInt) ||
1199                         type.matches(*fContext.fTypes.fUInt)) {
1200                     return "highp ";
1201                 }
1202                 return "";
1203             case Type::TypeKind::kVector: // fall through
1204             case Type::TypeKind::kMatrix:
1205             case Type::TypeKind::kArray:
1206                 return this->getTypePrecision(type.componentType());
1207             default:
1208                 break;
1209         }
1210     }
1211     return "";
1212 }
1213
1214 void GLSLCodeGenerator::writeTypePrecision(const Type& type) {
1215     this->write(this->getTypePrecision(type));
1216 }
1217
1218 void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& var, bool global) {
1219     this->writeModifiers(var.var().modifiers(), global);
1220     this->writeTypePrecision(var.baseType());
1221     this->writeType(var.baseType());
1222     this->write(" ");
1223     this->write(var.var().name());
1224     if (var.arraySize() > 0) {
1225         this->write("[");
1226         this->write(std::to_string(var.arraySize()));
1227         this->write("]");
1228     }
1229     if (var.value()) {
1230         this->write(" = ");
1231         this->writeVarInitializer(var.var(), *var.value());
1232     }
1233     if (!fFoundExternalSamplerDecl &&
1234         var.var().type().matches(*fContext.fTypes.fSamplerExternalOES)) {
1235         if (this->caps().externalTextureExtensionString()) {
1236             this->writeExtension(this->caps().externalTextureExtensionString());
1237         }
1238         if (this->caps().secondExternalTextureExtensionString()) {
1239             this->writeExtension(this->caps().secondExternalTextureExtensionString());
1240         }
1241         fFoundExternalSamplerDecl = true;
1242     }
1243     if (!fFoundRectSamplerDecl && var.var().type().matches(*fContext.fTypes.fSampler2DRect)) {
1244         fFoundRectSamplerDecl = true;
1245     }
1246     this->write(";");
1247 }
1248
1249 void GLSLCodeGenerator::writeStatement(const Statement& s) {
1250     switch (s.kind()) {
1251         case Statement::Kind::kBlock:
1252             this->writeBlock(s.as<Block>());
1253             break;
1254         case Statement::Kind::kExpression:
1255             this->writeExpressionStatement(s.as<ExpressionStatement>());
1256             break;
1257         case Statement::Kind::kReturn:
1258             this->writeReturnStatement(s.as<ReturnStatement>());
1259             break;
1260         case Statement::Kind::kVarDeclaration:
1261             this->writeVarDeclaration(s.as<VarDeclaration>(), false);
1262             break;
1263         case Statement::Kind::kIf:
1264             this->writeIfStatement(s.as<IfStatement>());
1265             break;
1266         case Statement::Kind::kFor:
1267             this->writeForStatement(s.as<ForStatement>());
1268             break;
1269         case Statement::Kind::kDo:
1270             this->writeDoStatement(s.as<DoStatement>());
1271             break;
1272         case Statement::Kind::kSwitch:
1273             this->writeSwitchStatement(s.as<SwitchStatement>());
1274             break;
1275         case Statement::Kind::kBreak:
1276             this->write("break;");
1277             break;
1278         case Statement::Kind::kContinue:
1279             this->write("continue;");
1280             break;
1281         case Statement::Kind::kDiscard:
1282             this->write("discard;");
1283             break;
1284         case Statement::Kind::kNop:
1285             this->write(";");
1286             break;
1287         default:
1288             SkDEBUGFAILF("unsupported statement: %s", s.description().c_str());
1289             break;
1290     }
1291 }
1292
1293 void GLSLCodeGenerator::writeBlock(const Block& b) {
1294     // Write scope markers if this block is a scope, or if the block is empty (since we need to emit
1295     // something here to make the code valid).
1296     bool isScope = b.isScope() || b.isEmpty();
1297     if (isScope) {
1298         this->writeLine("{");
1299         fIndentation++;
1300     }
1301     for (const std::unique_ptr<Statement>& stmt : b.children()) {
1302         if (!stmt->isEmpty()) {
1303             this->writeStatement(*stmt);
1304             this->finishLine();
1305         }
1306     }
1307     if (isScope) {
1308         fIndentation--;
1309         this->write("}");
1310     }
1311 }
1312
1313 void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
1314     this->write("if (");
1315     this->writeExpression(*stmt.test(), Precedence::kTopLevel);
1316     this->write(") ");
1317     this->writeStatement(*stmt.ifTrue());
1318     if (stmt.ifFalse()) {
1319         this->write(" else ");
1320         this->writeStatement(*stmt.ifFalse());
1321     }
1322 }
1323
1324 void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
1325     // Emit loops of the form 'for(;test;)' as 'while(test)', which is probably how they started
1326     if (!f.initializer() && f.test() && !f.next()) {
1327         this->write("while (");
1328         this->writeExpression(*f.test(), Precedence::kTopLevel);
1329         this->write(") ");
1330         this->writeStatement(*f.statement());
1331         return;
1332     }
1333
1334     this->write("for (");
1335     if (f.initializer() && !f.initializer()->isEmpty()) {
1336         this->writeStatement(*f.initializer());
1337     } else {
1338         this->write("; ");
1339     }
1340     if (f.test()) {
1341         if (this->caps().addAndTrueToLoopCondition()) {
1342             std::unique_ptr<Expression> and_true(new BinaryExpression(
1343                     Position(), f.test()->clone(), Operator::Kind::LOGICALAND,
1344                     Literal::MakeBool(fContext, Position(), /*value=*/true),
1345                     fContext.fTypes.fBool.get()));
1346             this->writeExpression(*and_true, Precedence::kTopLevel);
1347         } else {
1348             this->writeExpression(*f.test(), Precedence::kTopLevel);
1349         }
1350     }
1351     this->write("; ");
1352     if (f.next()) {
1353         this->writeExpression(*f.next(), Precedence::kTopLevel);
1354     }
1355     this->write(") ");
1356     this->writeStatement(*f.statement());
1357 }
1358
1359 void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
1360     if (!this->caps().rewriteDoWhileLoops()) {
1361         this->write("do ");
1362         this->writeStatement(*d.statement());
1363         this->write(" while (");
1364         this->writeExpression(*d.test(), Precedence::kTopLevel);
1365         this->write(");");
1366         return;
1367     }
1368
1369     // Otherwise, do the do while loop workaround, to rewrite loops of the form:
1370     //     do {
1371     //         CODE;
1372     //     } while (CONDITION)
1373     //
1374     // to loops of the form
1375     //     bool temp = false;
1376     //     while (true) {
1377     //         if (temp) {
1378     //             if (!CONDITION) {
1379     //                 break;
1380     //             }
1381     //         }
1382     //         temp = true;
1383     //         CODE;
1384     //     }
1385     std::string tmpVar = "_tmpLoopSeenOnce" + std::to_string(fVarCount++);
1386     this->write("bool ");
1387     this->write(tmpVar);
1388     this->writeLine(" = false;");
1389     this->writeLine("while (true) {");
1390     fIndentation++;
1391     this->write("if (");
1392     this->write(tmpVar);
1393     this->writeLine(") {");
1394     fIndentation++;
1395     this->write("if (!");
1396     this->writeExpression(*d.test(), Precedence::kPrefix);
1397     this->writeLine(") {");
1398     fIndentation++;
1399     this->writeLine("break;");
1400     fIndentation--;
1401     this->writeLine("}");
1402     fIndentation--;
1403     this->writeLine("}");
1404     this->write(tmpVar);
1405     this->writeLine(" = true;");
1406     this->writeStatement(*d.statement());
1407     this->finishLine();
1408     fIndentation--;
1409     this->write("}");
1410 }
1411
1412 void GLSLCodeGenerator::writeExpressionStatement(const ExpressionStatement& s) {
1413     if (fProgram.fConfig->fSettings.fOptimize && !s.expression()->hasSideEffects()) {
1414         // Don't emit dead expressions.
1415         return;
1416     }
1417     this->writeExpression(*s.expression(), Precedence::kTopLevel);
1418     this->write(";");
1419 }
1420
1421 void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
1422     if (this->caps().rewriteSwitchStatements()) {
1423         std::string fallthroughVar = "_tmpSwitchFallthrough" + std::to_string(fVarCount++);
1424         std::string valueVar = "_tmpSwitchValue" + std::to_string(fVarCount++);
1425         std::string loopVar = "_tmpSwitchLoop" + std::to_string(fVarCount++);
1426         this->write("int ");
1427         this->write(valueVar);
1428         this->write(" = ");
1429         this->writeExpression(*s.value(), Precedence::kAssignment);
1430         this->write(", ");
1431         this->write(fallthroughVar);
1432         this->writeLine(" = 0;");
1433         this->write("for (int ");
1434         this->write(loopVar);
1435         this->write(" = 0; ");
1436         this->write(loopVar);
1437         this->write(" < 1; ");
1438         this->write(loopVar);
1439         this->writeLine("++) {");
1440         fIndentation++;
1441
1442         bool firstCase = true;
1443         for (const std::unique_ptr<Statement>& stmt : s.cases()) {
1444             const SwitchCase& c = stmt->as<SwitchCase>();
1445             if (!c.isDefault()) {
1446                 this->write("if ((");
1447                 if (firstCase) {
1448                     firstCase = false;
1449                 } else {
1450                     this->write(fallthroughVar);
1451                     this->write(" > 0) || (");
1452                 }
1453                 this->write(valueVar);
1454                 this->write(" == ");
1455                 this->write(std::to_string(c.value()));
1456                 this->writeLine(")) {");
1457                 fIndentation++;
1458
1459                 // We write the entire case-block statement here, and then set `switchFallthrough`
1460                 // to 1. If the case-block had a break statement in it, we break out of the outer
1461                 // for-loop entirely, meaning the `switchFallthrough` assignment never occurs, nor
1462                 // does any code after it inside the switch. We've forbidden `continue` statements
1463                 // inside switch case-blocks entirely, so we don't need to consider their effect on
1464                 // control flow; see the Finalizer in FunctionDefinition::Convert.
1465                 this->writeStatement(*c.statement());
1466                 this->finishLine();
1467                 this->write(fallthroughVar);
1468                 this->write(" = 1;");
1469                 this->writeLine();
1470
1471                 fIndentation--;
1472                 this->writeLine("}");
1473             } else {
1474                 // This is the default case. Since it's always last, we can just dump in the code.
1475                 this->writeStatement(*c.statement());
1476                 this->finishLine();
1477             }
1478         }
1479
1480         fIndentation--;
1481         this->writeLine("}");
1482         return;
1483     }
1484
1485     this->write("switch (");
1486     this->writeExpression(*s.value(), Precedence::kTopLevel);
1487     this->writeLine(") {");
1488     fIndentation++;
1489     // If a switch contains only a `default` case and nothing else, this confuses some drivers and
1490     // can lead to a crash. Adding a real case before the default seems to work around the bug,
1491     // and doesn't change the meaning of the switch. (skia:12465)
1492     if (s.cases().size() == 1 && s.cases().front()->as<SwitchCase>().isDefault()) {
1493         this->writeLine("case 0:");
1494     }
1495     for (const std::unique_ptr<Statement>& stmt : s.cases()) {
1496         const SwitchCase& c = stmt->as<SwitchCase>();
1497         if (c.isDefault()) {
1498             this->writeLine("default:");
1499         } else {
1500             this->write("case ");
1501             this->write(std::to_string(c.value()));
1502             this->writeLine(":");
1503         }
1504         if (!c.statement()->isEmpty()) {
1505             fIndentation++;
1506             this->writeStatement(*c.statement());
1507             this->finishLine();
1508             fIndentation--;
1509         }
1510     }
1511     fIndentation--;
1512     this->finishLine();
1513     this->write("}");
1514 }
1515
1516 void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1517     this->write("return");
1518     if (r.expression()) {
1519         this->write(" ");
1520         this->writeExpression(*r.expression(), Precedence::kTopLevel);
1521     }
1522     this->write(";");
1523 }
1524
1525 void GLSLCodeGenerator::writeHeader() {
1526     if (this->caps().versionDeclString()) {
1527         this->write(this->caps().versionDeclString());
1528         this->finishLine();
1529     }
1530 }
1531
1532 void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
1533     switch (e.kind()) {
1534         case ProgramElement::Kind::kExtension:
1535             this->writeExtension(e.as<Extension>().name());
1536             break;
1537         case ProgramElement::Kind::kGlobalVar: {
1538             const VarDeclaration& decl =
1539                                    e.as<GlobalVarDeclaration>().declaration()->as<VarDeclaration>();
1540             int builtin = decl.var().modifiers().fLayout.fBuiltin;
1541             if (builtin == -1) {
1542                 // normal var
1543                 this->writeVarDeclaration(decl, true);
1544                 this->finishLine();
1545             } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
1546                        this->caps().mustDeclareFragmentShaderOutput()) {
1547                 if (fProgram.fConfig->fSettings.fFragColorIsInOut) {
1548                     this->write("inout ");
1549                 } else {
1550                     this->write("out ");
1551                 }
1552                 if (usesPrecisionModifiers()) {
1553                     this->write("mediump ");
1554                 }
1555                 this->writeLine("vec4 sk_FragColor;");
1556             }
1557             break;
1558         }
1559         case ProgramElement::Kind::kInterfaceBlock:
1560             this->writeInterfaceBlock(e.as<InterfaceBlock>());
1561             break;
1562         case ProgramElement::Kind::kFunction:
1563             this->writeFunction(e.as<FunctionDefinition>());
1564             break;
1565         case ProgramElement::Kind::kFunctionPrototype:
1566             this->writeFunctionPrototype(e.as<FunctionPrototype>());
1567             break;
1568         case ProgramElement::Kind::kModifiers: {
1569             const Modifiers& modifiers = e.as<ModifiersDeclaration>().modifiers();
1570             this->writeModifiers(modifiers, true);
1571             this->writeLine(";");
1572             break;
1573         }
1574         case ProgramElement::Kind::kStructDefinition:
1575             this->writeStructDefinition(e.as<StructDefinition>());
1576             break;
1577         default:
1578             SkDEBUGFAILF("unsupported program element %s\n", e.description().c_str());
1579             break;
1580     }
1581 }
1582
1583 void GLSLCodeGenerator::writeInputVars() {
1584     if (fProgram.fInputs.fUseFlipRTUniform) {
1585         const char* precision = usesPrecisionModifiers() ? "highp " : "";
1586         fGlobals.writeText("uniform ");
1587         fGlobals.writeText(precision);
1588         fGlobals.writeText("vec2 " SKSL_RTFLIP_NAME ";\n");
1589     }
1590 }
1591
1592 bool GLSLCodeGenerator::generateCode() {
1593     this->writeHeader();
1594     OutputStream* rawOut = fOut;
1595     StringStream body;
1596     fOut = &body;
1597     // Write all the program elements except for functions.
1598     for (const ProgramElement* e : fProgram.elements()) {
1599         if (!e->is<FunctionDefinition>()) {
1600             this->writeProgramElement(*e);
1601         }
1602     }
1603     // Write the functions last.
1604     // Why don't we write things in their original order? Because the Inliner likes to move function
1605     // bodies around. After inlining, code can inadvertently move upwards, above ProgramElements
1606     // that the code relies on.
1607     for (const ProgramElement* e : fProgram.elements()) {
1608         if (e->is<FunctionDefinition>()) {
1609             this->writeProgramElement(*e);
1610         }
1611     }
1612     fOut = rawOut;
1613
1614     write_stringstream(fExtensions, *rawOut);
1615     this->writeInputVars();
1616     write_stringstream(fGlobals, *rawOut);
1617
1618     if (!this->caps().canUseFragCoord()) {
1619         Layout layout;
1620         if (ProgramConfig::IsVertex(fProgram.fConfig->fKind)) {
1621             Modifiers modifiers(layout, Modifiers::kOut_Flag);
1622             this->writeModifiers(modifiers, true);
1623             if (this->usesPrecisionModifiers()) {
1624                 this->write("highp ");
1625             }
1626             this->write("vec4 sk_FragCoord_Workaround;\n");
1627         } else if (ProgramConfig::IsFragment(fProgram.fConfig->fKind)) {
1628             Modifiers modifiers(layout, Modifiers::kIn_Flag);
1629             this->writeModifiers(modifiers, true);
1630             if (this->usesPrecisionModifiers()) {
1631                 this->write("highp ");
1632             }
1633             this->write("vec4 sk_FragCoord_Workaround;\n");
1634         }
1635     }
1636
1637     if (this->usesPrecisionModifiers()) {
1638         const char* precision =
1639                 fProgram.fConfig->fSettings.fForceHighPrecision ? "highp" : "mediump";
1640         this->write(String::printf("precision %s float;\n", precision));
1641         this->write(String::printf("precision %s sampler2D;\n", precision));
1642         if (fFoundExternalSamplerDecl && !this->caps().noDefaultPrecisionForExternalSamplers()) {
1643             this->write(String::printf("precision %s samplerExternalOES;\n", precision));
1644         }
1645         if (fFoundRectSamplerDecl) {
1646             this->write(String::printf("precision %s sampler2DRect;\n", precision));
1647         }
1648     }
1649     write_stringstream(fExtraFunctions, *rawOut);
1650     write_stringstream(body, *rawOut);
1651     return fContext.fErrors->errorCount() == 0;
1652 }
1653
1654 }  // namespace SkSL