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/SkSLGLSLCodeGenerator.h"
9
10#include "src/sksl/SkSLCompiler.h"
11#include "src/sksl/ir/SkSLExpressionStatement.h"
12#include "src/sksl/ir/SkSLExtension.h"
13#include "src/sksl/ir/SkSLIndexExpression.h"
14#include "src/sksl/ir/SkSLModifiersDeclaration.h"
15#include "src/sksl/ir/SkSLNop.h"
16#include "src/sksl/ir/SkSLVariableReference.h"
17
18#ifndef SKSL_STANDALONE
19#include "include/private/SkOnce.h"
20#endif
21
22namespace SkSL {
23
24void GLSLCodeGenerator::write(const char* s) {
25 if (s[0] == 0) {
26 return;
27 }
28 if (fAtLineStart) {
29 for (int i = 0; i < fIndentation; i++) {
30 fOut->writeText(" ");
31 }
32 }
33 fOut->writeText(s);
34 fAtLineStart = false;
35}
36
37void GLSLCodeGenerator::writeLine(const char* s) {
38 this->write(s);
39 fOut->writeText(fLineEnding);
40 fAtLineStart = true;
41}
42
43void GLSLCodeGenerator::write(const String& s) {
44 this->write(s.c_str());
45}
46
47void GLSLCodeGenerator::write(StringFragment s) {
48 if (!s.fLength) {
49 return;
50 }
51 if (fAtLineStart) {
52 for (int i = 0; i < fIndentation; i++) {
53 fOut->writeText(" ");
54 }
55 }
56 fOut->write(s.fChars, s.fLength);
57 fAtLineStart = false;
58}
59
60void GLSLCodeGenerator::writeLine(const String& s) {
61 this->writeLine(s.c_str());
62}
63
64void GLSLCodeGenerator::writeLine() {
65 this->writeLine("");
66}
67
68void GLSLCodeGenerator::writeExtension(const String& name) {
69 this->writeExtension(name, true);
70}
71
72void GLSLCodeGenerator::writeExtension(const String& name, bool require) {
73 fExtensions.writeText("#extension ");
74 fExtensions.write(name.c_str(), name.length());
75 fExtensions.writeText(require ? " : require\n" : " : enable\n");
76}
77
78bool GLSLCodeGenerator::usesPrecisionModifiers() const {
79 return fProgram.fSettings.fCaps->usesPrecisionModifiers();
80}
81
82String GLSLCodeGenerator::getTypeName(const Type& type) {
83 switch (type.kind()) {
84 case Type::kVector_Kind: {
85 Type component = type.componentType();
86 String result;
87 if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
88 result = "vec";
89 }
90 else if (component == *fContext.fDouble_Type) {
91 result = "dvec";
92 }
93 else if (component.isSigned()) {
94 result = "ivec";
95 }
96 else if (component.isUnsigned()) {
97 result = "uvec";
98 }
99 else if (component == *fContext.fBool_Type) {
100 result = "bvec";
101 }
102 else {
103 ABORT("unsupported vector type");
104 }
105 result += to_string(type.columns());
106 return result;
107 }
108 case Type::kMatrix_Kind: {
109 String result;
110 Type component = type.componentType();
111 if (component == *fContext.fFloat_Type || component == *fContext.fHalf_Type) {
112 result = "mat";
113 }
114 else if (component == *fContext.fDouble_Type) {
115 result = "dmat";
116 }
117 else {
118 ABORT("unsupported matrix type");
119 }
120 result += to_string(type.columns());
121 if (type.columns() != type.rows()) {
122 result += "x";
123 result += to_string(type.rows());
124 }
125 return result;
126 }
127 case Type::kArray_Kind: {
128 String result = this->getTypeName(type.componentType()) + "[";
129 if (type.columns() != -1) {
130 result += to_string(type.columns());
131 }
132 result += "]";
133 return result;
134 }
135 case Type::kScalar_Kind: {
136 if (type == *fContext.fHalf_Type) {
137 return "float";
138 }
139 else if (type == *fContext.fShort_Type) {
140 return "int";
141 }
142 else if (type == *fContext.fUShort_Type) {
143 return "uint";
144 }
145 else if (type == *fContext.fByte_Type) {
146 return "int";
147 }
148 else if (type == *fContext.fUByte_Type) {
149 return "uint";
150 }
151 else {
152 return type.name();
153 }
154 break;
155 }
156 case Type::kEnum_Kind:
157 return "int";
158 default:
159 return type.name();
160 }
161}
162
163void GLSLCodeGenerator::writeType(const Type& type) {
164 if (type.kind() == Type::kStruct_Kind) {
165 for (const Type* search : fWrittenStructs) {
166 if (*search == type) {
167 // already written
168 this->write(type.fName);
169 return;
170 }
171 }
172 fWrittenStructs.push_back(&type);
173 this->write("struct ");
174 this->write(type.fName);
175 this->writeLine(" {");
176 fIndentation++;
177 for (const auto& f : type.fields()) {
178 this->writeModifiers(f.fModifiers, false);
179 this->writeTypePrecision(*f.fType);
180 // sizes (which must be static in structs) are part of the type name here
181 this->writeType(*f.fType);
182 this->write(" ");
183 this->write(f.fName);
184 this->writeLine(";");
185 }
186 fIndentation--;
187 this->write("}");
188 } else {
189 this->write(this->getTypeName(type));
190 }
191}
192
193void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
194 switch (expr.fKind) {
195 case Expression::kBinary_Kind:
196 this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence);
197 break;
198 case Expression::kBoolLiteral_Kind:
199 this->writeBoolLiteral((BoolLiteral&) expr);
200 break;
201 case Expression::kConstructor_Kind:
202 this->writeConstructor((Constructor&) expr, parentPrecedence);
203 break;
204 case Expression::kIntLiteral_Kind:
205 this->writeIntLiteral((IntLiteral&) expr);
206 break;
207 case Expression::kFieldAccess_Kind:
208 this->writeFieldAccess(((FieldAccess&) expr));
209 break;
210 case Expression::kFloatLiteral_Kind:
211 this->writeFloatLiteral(((FloatLiteral&) expr));
212 break;
213 case Expression::kFunctionCall_Kind:
214 this->writeFunctionCall((FunctionCall&) expr);
215 break;
216 case Expression::kPrefix_Kind:
217 this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence);
218 break;
219 case Expression::kPostfix_Kind:
220 this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence);
221 break;
222 case Expression::kSetting_Kind:
223 this->writeSetting((Setting&) expr);
224 break;
225 case Expression::kSwizzle_Kind:
226 this->writeSwizzle((Swizzle&) expr);
227 break;
228 case Expression::kVariableReference_Kind:
229 this->writeVariableReference((VariableReference&) expr);
230 break;
231 case Expression::kTernary_Kind:
232 this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence);
233 break;
234 case Expression::kIndex_Kind:
235 this->writeIndexExpression((IndexExpression&) expr);
236 break;
237 default:
238#ifdef SK_DEBUG
239 ABORT("unsupported expression: %s", expr.description().c_str());
240#endif
241 break;
242 }
243}
244
245static bool is_abs(Expression& expr) {
246 if (expr.fKind != Expression::kFunctionCall_Kind) {
247 return false;
248 }
249 return ((FunctionCall&) expr).fFunction.fName == "abs";
250}
251
252// turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
253// Tegra3 compiler bug.
254void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
255 SkASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
256 String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
257 String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
258 this->fFunctionHeader += String(" ") + this->getTypePrecision(absExpr.fType) +
259 this->getTypeName(absExpr.fType) + " " + tmpVar1 + ";\n";
260 this->fFunctionHeader += String(" ") + this->getTypePrecision(otherExpr.fType) +
261 this->getTypeName(otherExpr.fType) + " " + tmpVar2 + ";\n";
262 this->write("((" + tmpVar1 + " = ");
263 this->writeExpression(absExpr, kTopLevel_Precedence);
264 this->write(") < (" + tmpVar2 + " = ");
265 this->writeExpression(otherExpr, kAssignment_Precedence);
266 this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
267}
268
269void GLSLCodeGenerator::writeInverseSqrtHack(const Expression& x) {
270 this->write("(1.0 / sqrt(");
271 this->writeExpression(x, kTopLevel_Precedence);
272 this->write("))");
273}
274
275void GLSLCodeGenerator::writeDeterminantHack(const Expression& mat) {
276 String name;
277 if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) {
278 name = "_determinant2";
279 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
280 fWrittenIntrinsics.insert(name);
281 fExtraFunctions.writeText((
282 "float " + name + "(mat2 m) {"
283 " return m[0][0] * m[1][1] - m[0][1] * m[1][0];"
284 "}"
285 ).c_str());
286 }
287 }
288 else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) {
289 name = "_determinant3";
290 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
291 fWrittenIntrinsics.insert(name);
292 fExtraFunctions.writeText((
293 "float " + name + "(mat3 m) {"
294 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
295 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
296 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
297 " float b01 = a22 * a11 - a12 * a21;"
298 " float b11 = -a22 * a10 + a12 * a20;"
299 " float b21 = a21 * a10 - a11 * a20;"
300 " return a00 * b01 + a01 * b11 + a02 * b21;"
301 "}"
302 ).c_str());
303 }
304 }
305 else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) {
306 name = "_determinant3";
307 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
308 fWrittenIntrinsics.insert(name);
309 fExtraFunctions.writeText((
310 "mat4 " + name + "(mat4 m) {"
311 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
312 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
313 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
314 " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
315 " float b00 = a00 * a11 - a01 * a10;"
316 " float b01 = a00 * a12 - a02 * a10;"
317 " float b02 = a00 * a13 - a03 * a10;"
318 " float b03 = a01 * a12 - a02 * a11;"
319 " float b04 = a01 * a13 - a03 * a11;"
320 " float b05 = a02 * a13 - a03 * a12;"
321 " float b06 = a20 * a31 - a21 * a30;"
322 " float b07 = a20 * a32 - a22 * a30;"
323 " float b08 = a20 * a33 - a23 * a30;"
324 " float b09 = a21 * a32 - a22 * a31;"
325 " float b10 = a21 * a33 - a23 * a31;"
326 " float b11 = a22 * a33 - a23 * a32;"
327 " return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;"
328 "}"
329 ).c_str());
330 }
331 }
332 else {
333 SkASSERT(false);
334 }
335 this->write(name + "(");
336 this->writeExpression(mat, kTopLevel_Precedence);
337 this->write(")");
338}
339
340void GLSLCodeGenerator::writeInverseHack(const Expression& mat) {
341 String name;
342 if (mat.fType == *fContext.fFloat2x2_Type || mat.fType == *fContext.fHalf2x2_Type) {
343 name = "_inverse2";
344 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
345 fWrittenIntrinsics.insert(name);
346 fExtraFunctions.writeText((
347 "mat2 " + name + "(mat2 m) {"
348 " return mat2(m[1][1], -m[0][1], -m[1][0], m[0][0]) / "
349 "(m[0][0] * m[1][1] - m[0][1] * m[1][0]);"
350 "}"
351 ).c_str());
352 }
353 }
354 else if (mat.fType == *fContext.fFloat3x3_Type || mat.fType == *fContext.fHalf3x3_Type) {
355 name = "_inverse3";
356 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
357 fWrittenIntrinsics.insert(name);
358 fExtraFunctions.writeText((
359 "mat3 " + name + "(mat3 m) {"
360 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2];"
361 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2];"
362 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2];"
363 " float b01 = a22 * a11 - a12 * a21;"
364 " float b11 = -a22 * a10 + a12 * a20;"
365 " float b21 = a21 * a10 - a11 * a20;"
366 " float det = a00 * b01 + a01 * b11 + a02 * b21;"
367 " return mat3(b01, (-a22 * a01 + a02 * a21), (a12 * a01 - a02 * a11),"
368 " b11, (a22 * a00 - a02 * a20), (-a12 * a00 + a02 * a10),"
369 " b21, (-a21 * a00 + a01 * a20), (a11 * a00 - a01 * a10)) / det;"
370 "}"
371 ).c_str());
372 }
373 }
374 else if (mat.fType == *fContext.fFloat4x4_Type || mat.fType == *fContext.fHalf4x4_Type) {
375 name = "_inverse4";
376 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
377 fWrittenIntrinsics.insert(name);
378 fExtraFunctions.writeText((
379 "mat4 " + name + "(mat4 m) {"
380 " float a00 = m[0][0], a01 = m[0][1], a02 = m[0][2], a03 = m[0][3];"
381 " float a10 = m[1][0], a11 = m[1][1], a12 = m[1][2], a13 = m[1][3];"
382 " float a20 = m[2][0], a21 = m[2][1], a22 = m[2][2], a23 = m[2][3];"
383 " float a30 = m[3][0], a31 = m[3][1], a32 = m[3][2], a33 = m[3][3];"
384 " float b00 = a00 * a11 - a01 * a10;"
385 " float b01 = a00 * a12 - a02 * a10;"
386 " float b02 = a00 * a13 - a03 * a10;"
387 " float b03 = a01 * a12 - a02 * a11;"
388 " float b04 = a01 * a13 - a03 * a11;"
389 " float b05 = a02 * a13 - a03 * a12;"
390 " float b06 = a20 * a31 - a21 * a30;"
391 " float b07 = a20 * a32 - a22 * a30;"
392 " float b08 = a20 * a33 - a23 * a30;"
393 " float b09 = a21 * a32 - a22 * a31;"
394 " float b10 = a21 * a33 - a23 * a31;"
395 " float b11 = a22 * a33 - a23 * a32;"
396 " float det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - "
397 " b04 * b07 + b05 * b06;"
398 " return mat4("
399 " a11 * b11 - a12 * b10 + a13 * b09,"
400 " a02 * b10 - a01 * b11 - a03 * b09,"
401 " a31 * b05 - a32 * b04 + a33 * b03,"
402 " a22 * b04 - a21 * b05 - a23 * b03,"
403 " a12 * b08 - a10 * b11 - a13 * b07,"
404 " a00 * b11 - a02 * b08 + a03 * b07,"
405 " a32 * b02 - a30 * b05 - a33 * b01,"
406 " a20 * b05 - a22 * b02 + a23 * b01,"
407 " a10 * b10 - a11 * b08 + a13 * b06,"
408 " a01 * b08 - a00 * b10 - a03 * b06,"
409 " a30 * b04 - a31 * b02 + a33 * b00,"
410 " a21 * b02 - a20 * b04 - a23 * b00,"
411 " a11 * b07 - a10 * b09 - a12 * b06,"
412 " a00 * b09 - a01 * b07 + a02 * b06,"
413 " a31 * b01 - a30 * b03 - a32 * b00,"
414 " a20 * b03 - a21 * b01 + a22 * b00) / det;"
415 "}"
416 ).c_str());
417 }
418 }
419 else {
420 SkASSERT(false);
421 }
422 this->write(name + "(");
423 this->writeExpression(mat, kTopLevel_Precedence);
424 this->write(")");
425}
426
427void GLSLCodeGenerator::writeTransposeHack(const Expression& mat) {
428 String name = "transpose" + to_string(mat.fType.columns()) + to_string(mat.fType.rows());
429 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
430 fWrittenIntrinsics.insert(name);
431 String type = this->getTypeName(mat.fType);
432 const Type& base = mat.fType.componentType();
433 String transposed = this->getTypeName(base.toCompound(fContext,
434 mat.fType.rows(),
435 mat.fType.columns()));
436 fExtraFunctions.writeText((transposed + " " + name + "(" + type + " m) {\nreturn " +
437 transposed + "(").c_str());
438 const char* separator = "";
439 for (int row = 0; row < mat.fType.rows(); ++row) {
440 for (int column = 0; column < mat.fType.columns(); ++column) {
441 fExtraFunctions.writeText(separator);
442 fExtraFunctions.writeText(("m[" + to_string(column) + "][" + to_string(row) +
443 "]").c_str());
444 separator = ", ";
445 }
446 }
447 fExtraFunctions.writeText("); }");
448 }
449 this->write(name + "(");
450 this->writeExpression(mat, kTopLevel_Precedence);
451 this->write(")");
452}
453
454std::unordered_map<StringFragment, GLSLCodeGenerator::FunctionClass>*
455 GLSLCodeGenerator::fFunctionClasses = nullptr;
456
457void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
458#ifdef SKSL_STANDALONE
459 if (!fFunctionClasses) {
460#else
461 static SkOnce once;
462 once([] {
463#endif
464 fFunctionClasses = new std::unordered_map<StringFragment, FunctionClass>();
465 (*fFunctionClasses)["abs"] = FunctionClass::kAbs;
466 (*fFunctionClasses)["atan"] = FunctionClass::kAtan;
467 (*fFunctionClasses)["determinant"] = FunctionClass::kDeterminant;
468 (*fFunctionClasses)["dFdx"] = FunctionClass::kDFdx;
469 (*fFunctionClasses)["dFdy"] = FunctionClass::kDFdy;
470 (*fFunctionClasses)["fwidth"] = FunctionClass::kFwidth;
471 (*fFunctionClasses)["fma"] = FunctionClass::kFMA;
472 (*fFunctionClasses)["fract"] = FunctionClass::kFract;
473 (*fFunctionClasses)["inverse"] = FunctionClass::kInverse;
474 (*fFunctionClasses)["inverseSqrt"] = FunctionClass::kInverseSqrt;
475 (*fFunctionClasses)["min"] = FunctionClass::kMin;
476 (*fFunctionClasses)["pow"] = FunctionClass::kPow;
477 (*fFunctionClasses)["saturate"] = FunctionClass::kSaturate;
478 (*fFunctionClasses)["sample"] = FunctionClass::kTexture;
479 (*fFunctionClasses)["transpose"] = FunctionClass::kTranspose;
480 }
481#ifndef SKSL_STANDALONE
482 );
483#endif
484 const auto found = c.fFunction.fBuiltin ? fFunctionClasses->find(c.fFunction.fName) :
485 fFunctionClasses->end();
486 bool isTextureFunctionWithBias = false;
487 bool nameWritten = false;
488 if (found != fFunctionClasses->end()) {
489 switch (found->second) {
490 case FunctionClass::kAbs: {
491 if (!fProgram.fSettings.fCaps->emulateAbsIntFunction())
492 break;
493 SkASSERT(c.fArguments.size() == 1);
494 if (c.fArguments[0]->fType != *fContext.fInt_Type)
495 break;
496 // abs(int) on Intel OSX is incorrect, so emulate it:
497 String name = "_absemulation";
498 this->write(name);
499 nameWritten = true;
500 if (fWrittenIntrinsics.find(name) == fWrittenIntrinsics.end()) {
501 fWrittenIntrinsics.insert(name);
502 fExtraFunctions.writeText((
503 "int " + name + "(int x) {\n"
504 " return x * sign(x);\n"
505 "}\n"
506 ).c_str());
507 }
508 break;
509 }
510 case FunctionClass::kAtan:
511 if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
512 c.fArguments.size() == 2 &&
513 c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
514 const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
515 if (p.fOperator == Token::MINUS) {
516 this->write("atan(");
517 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
518 this->write(", -1.0 * ");
519 this->writeExpression(*p.fOperand, kMultiplicative_Precedence);
520 this->write(")");
521 return;
522 }
523 }
524 break;
525 case FunctionClass::kDFdy:
526 if (fProgram.fSettings.fFlipY) {
527 // Flipping Y also negates the Y derivatives.
528 this->write("-dFdy");
529 nameWritten = true;
530 }
531 // fallthru
532 case FunctionClass::kDFdx:
533 case FunctionClass::kFwidth:
534 if (!fFoundDerivatives &&
535 fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) {
536 SkASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport());
537 this->writeExtension(fProgram.fSettings.fCaps->shaderDerivativeExtensionString());
538 fFoundDerivatives = true;
539 }
540 break;
541 case FunctionClass::kDeterminant:
542 if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
543 SkASSERT(c.fArguments.size() == 1);
544 this->writeDeterminantHack(*c.fArguments[0]);
545 return;
546 }
547 break;
548 case FunctionClass::kFMA:
549 if (!fProgram.fSettings.fCaps->builtinFMASupport()) {
550 SkASSERT(c.fArguments.size() == 3);
551 this->write("((");
552 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
553 this->write(") * (");
554 this->writeExpression(*c.fArguments[1], kSequence_Precedence);
555 this->write(") + (");
556 this->writeExpression(*c.fArguments[2], kSequence_Precedence);
557 this->write("))");
558 return;
559 }
560 break;
561 case FunctionClass::kFract:
562 if (!fProgram.fSettings.fCaps->canUseFractForNegativeValues()) {
563 SkASSERT(c.fArguments.size() == 1);
564 this->write("(0.5 - sign(");
565 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
566 this->write(") * (0.5 - fract(abs(");
567 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
568 this->write("))))");
569 return;
570 }
571 break;
572 case FunctionClass::kInverse:
573 if (fProgram.fSettings.fCaps->generation() < k140_GrGLSLGeneration) {
574 SkASSERT(c.fArguments.size() == 1);
575 this->writeInverseHack(*c.fArguments[0]);
576 return;
577 }
578 break;
579 case FunctionClass::kInverseSqrt:
580 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
581 SkASSERT(c.fArguments.size() == 1);
582 this->writeInverseSqrtHack(*c.fArguments[0]);
583 return;
584 }
585 break;
586 case FunctionClass::kMin:
587 if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether()) {
588 SkASSERT(c.fArguments.size() == 2);
589 if (is_abs(*c.fArguments[0])) {
590 this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
591 return;
592 }
593 if (is_abs(*c.fArguments[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(*c.fArguments[1], *c.fArguments[0]);
597 return;
598 }
599 }
600 break;
601 case FunctionClass::kPow:
602 if (!fProgram.fSettings.fCaps->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(*c.fArguments[1], kMultiplicative_Precedence);
612 this->write(" * log2(");
613 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
614 this->write("))");
615 return;
616 case FunctionClass::kSaturate:
617 SkASSERT(c.fArguments.size() == 1);
618 this->write("clamp(");
619 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
620 this->write(", 0.0, 1.0)");
621 return;
622 case FunctionClass::kTexture: {
623 const char* dim = "";
624 bool proj = false;
625 switch (c.fArguments[0]->fType.dimensions()) {
626 case SpvDim1D:
627 dim = "1D";
628 isTextureFunctionWithBias = true;
629 if (c.fArguments[1]->fType == *fContext.fFloat_Type) {
630 proj = false;
631 } else {
632 SkASSERT(c.fArguments[1]->fType == *fContext.fFloat2_Type);
633 proj = true;
634 }
635 break;
636 case SpvDim2D:
637 dim = "2D";
638 if (c.fArguments[0]->fType != *fContext.fSamplerExternalOES_Type) {
639 isTextureFunctionWithBias = true;
640 }
641 if (c.fArguments[1]->fType == *fContext.fFloat2_Type) {
642 proj = false;
643 } else {
644 SkASSERT(c.fArguments[1]->fType == *fContext.fFloat3_Type);
645 proj = true;
646 }
647 break;
648 case SpvDim3D:
649 dim = "3D";
650 isTextureFunctionWithBias = true;
651 if (c.fArguments[1]->fType == *fContext.fFloat3_Type) {
652 proj = false;
653 } else {
654 SkASSERT(c.fArguments[1]->fType == *fContext.fFloat4_Type);
655 proj = true;
656 }
657 break;
658 case SpvDimCube:
659 dim = "Cube";
660 isTextureFunctionWithBias = true;
661 proj = false;
662 break;
663 case SpvDimRect:
664 dim = "2DRect";
665 proj = false;
666 break;
667 case SpvDimBuffer:
668 SkASSERT(false); // doesn't exist
669 dim = "Buffer";
670 proj = false;
671 break;
672 case SpvDimSubpassData:
673 SkASSERT(false); // doesn't exist
674 dim = "SubpassData";
675 proj = false;
676 break;
677 }
678 if (fTextureFunctionOverride != "") {
679 this->write(fTextureFunctionOverride.c_str());
680 } else {
681 this->write("texture");
682 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
683 this->write(dim);
684 }
685 if (proj) {
686 this->write("Proj");
687 }
688 }
689 nameWritten = true;
690 break;
691 }
692 case FunctionClass::kTranspose:
693 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
694 SkASSERT(c.fArguments.size() == 1);
695 this->writeTransposeHack(*c.fArguments[0]);
696 return;
697 }
698 break;
699 }
700 }
701 if (!nameWritten) {
702 this->write(c.fFunction.fName);
703 }
704 this->write("(");
705 const char* separator = "";
706 for (const auto& arg : c.fArguments) {
707 this->write(separator);
708 separator = ", ";
709 this->writeExpression(*arg, kSequence_Precedence);
710 }
711 if (fProgram.fSettings.fSharpenTextures && isTextureFunctionWithBias) {
712 this->write(", -0.5");
713 }
714 this->write(")");
715}
716
717void GLSLCodeGenerator::writeConstructor(const Constructor& c, Precedence parentPrecedence) {
718 if (c.fArguments.size() == 1 &&
719 (this->getTypeName(c.fType) == this->getTypeName(c.fArguments[0]->fType) ||
720 (c.fType.kind() == Type::kScalar_Kind &&
721 c.fArguments[0]->fType == *fContext.fFloatLiteral_Type))) {
722 // in cases like half(float), they're different types as far as SkSL is concerned but the
723 // same type as far as GLSL is concerned. We avoid a redundant float(float) by just writing
724 // out the inner expression here.
725 this->writeExpression(*c.fArguments[0], parentPrecedence);
726 return;
727 }
728 this->writeType(c.fType);
729 this->write("(");
730 const char* separator = "";
731 for (const auto& arg : c.fArguments) {
732 this->write(separator);
733 separator = ", ";
734 this->writeExpression(*arg, kSequence_Precedence);
735 }
736 this->write(")");
737}
738
739void GLSLCodeGenerator::writeFragCoord() {
740 if (!fProgram.fSettings.fCaps->canUseFragCoord()) {
741 if (!fSetupFragCoordWorkaround) {
742 const char* precision = usesPrecisionModifiers() ? "highp " : "";
743 fFunctionHeader += precision;
744 fFunctionHeader += " float sk_FragCoord_InvW = 1. / sk_FragCoord_Workaround.w;\n";
745 fFunctionHeader += precision;
746 fFunctionHeader += " vec4 sk_FragCoord_Resolved = "
747 "vec4(sk_FragCoord_Workaround.xyz * sk_FragCoord_InvW, sk_FragCoord_InvW);\n";
748 // Ensure that we get exact .5 values for x and y.
749 fFunctionHeader += " sk_FragCoord_Resolved.xy = floor(sk_FragCoord_Resolved.xy) + "
750 "vec2(.5);\n";
751 fSetupFragCoordWorkaround = true;
752 }
753 this->write("sk_FragCoord_Resolved");
754 return;
755 }
756
757 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
758 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
759 // declaration varies in earlier GLSL specs. So it is simpler to omit it.
760 if (!fProgram.fSettings.fFlipY) {
761 this->write("gl_FragCoord");
762 } else if (const char* extension =
763 fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) {
764 if (!fSetupFragPositionGlobal) {
765 if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
766 this->writeExtension(extension);
767 }
768 fGlobals.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n");
769 fSetupFragPositionGlobal = true;
770 }
771 this->write("gl_FragCoord");
772 } else {
773 if (!fSetupFragPositionLocal) {
774 fFunctionHeader += usesPrecisionModifiers() ? "highp " : "";
775 fFunctionHeader += " vec4 sk_FragCoord = vec4(gl_FragCoord.x, " SKSL_RTHEIGHT_NAME
776 " - gl_FragCoord.y, gl_FragCoord.z, gl_FragCoord.w);\n";
777 fSetupFragPositionLocal = true;
778 }
779 this->write("sk_FragCoord");
780 }
781}
782
783void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
784 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
785 case SK_FRAGCOLOR_BUILTIN:
786 if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
787 this->write("sk_FragColor");
788 } else {
789 this->write("gl_FragColor");
790 }
791 break;
792 case SK_FRAGCOORD_BUILTIN:
793 this->writeFragCoord();
794 break;
795 case SK_WIDTH_BUILTIN:
796 this->write("u_skRTWidth");
797 break;
798 case SK_HEIGHT_BUILTIN:
799 this->write("u_skRTHeight");
800 break;
801 case SK_CLOCKWISE_BUILTIN:
802 this->write(fProgram.fSettings.fFlipY ? "(!gl_FrontFacing)" : "gl_FrontFacing");
803 break;
804 case SK_SAMPLEMASK_BUILTIN:
805 SkASSERT(fProgram.fSettings.fCaps->sampleMaskSupport());
806 this->write("gl_SampleMask");
807 break;
808 case SK_VERTEXID_BUILTIN:
809 this->write("gl_VertexID");
810 break;
811 case SK_INSTANCEID_BUILTIN:
812 this->write("gl_InstanceID");
813 break;
814 case SK_CLIPDISTANCE_BUILTIN:
815 this->write("gl_ClipDistance");
816 break;
817 case SK_IN_BUILTIN:
818 this->write("gl_in");
819 break;
820 case SK_INVOCATIONID_BUILTIN:
821 this->write("gl_InvocationID");
822 break;
823 case SK_LASTFRAGCOLOR_BUILTIN:
824 this->write(fProgram.fSettings.fCaps->fbFetchColorName());
825 break;
826 default:
827 this->write(ref.fVariable.fName);
828 }
829}
830
831void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
832 this->writeExpression(*expr.fBase, kPostfix_Precedence);
833 this->write("[");
834 this->writeExpression(*expr.fIndex, kTopLevel_Precedence);
835 this->write("]");
836}
837
838bool is_sk_position(const FieldAccess& f) {
839 return "sk_Position" == f.fBase->fType.fields()[f.fFieldIndex].fName;
840}
841
842void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
843 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) {
844 this->writeExpression(*f.fBase, kPostfix_Precedence);
845 this->write(".");
846 }
847 switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) {
848 case SK_CLIPDISTANCE_BUILTIN:
849 this->write("gl_ClipDistance");
850 break;
851 default:
852 StringFragment name = f.fBase->fType.fields()[f.fFieldIndex].fName;
853 if (name == "sk_Position") {
854 this->write("gl_Position");
855 } else if (name == "sk_PointSize") {
856 this->write("gl_PointSize");
857 } else {
858 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName);
859 }
860 }
861}
862
863void GLSLCodeGenerator::writeConstantSwizzle(const Swizzle& swizzle, const String& constants) {
864 this->writeType(swizzle.fType);
865 this->write("(");
866 this->write(constants);
867 this->write(")");
868}
869
870void GLSLCodeGenerator::writeSwizzleMask(const Swizzle& swizzle, const String& mask) {
871 this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
872 this->write(".");
873 this->write(mask);
874}
875
876void GLSLCodeGenerator::writeSwizzleConstructor(const Swizzle& swizzle, const String& constants,
877 const String& mask,
878 GLSLCodeGenerator::SwizzleOrder order) {
879 this->writeType(swizzle.fType);
880 this->write("(");
881 if (order == SwizzleOrder::CONSTANTS_FIRST) {
882 this->write(constants);
883 this->write(", ");
884 this->writeSwizzleMask(swizzle, mask);
885 } else {
886 this->writeSwizzleMask(swizzle, mask);
887 this->write(", ");
888 this->write(constants);
889 }
890 this->write(")");
891}
892
893void GLSLCodeGenerator::writeSwizzleConstructor(const Swizzle& swizzle, const String& constants,
894 const String& mask, const String& reswizzle) {
895 this->writeSwizzleConstructor(swizzle, constants, mask, SwizzleOrder::MASK_FIRST);
896 this->write(".");
897 this->write(reswizzle);
898}
899
900// Writing a swizzle is complicated due to the handling of constant swizzle components. The most
901// problematic case is a mask like '.r00a'. A naive approach might turn that into
902// 'vec4(base.r, 0, 0, base.a)', but that would cause 'base' to be evaluated twice. We instead
903// group the swizzle mask ('ra') and constants ('0, 0') together and use a secondary swizzle to put
904// them back into the right order, so in this case we end up with something like
905// 'vec4(base4.ra, 0, 0).rbag'.
906void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
907 // has a 1 bit in every position for which the swizzle mask is a constant, so 'r0b1' would
908 // yield binary 0101.
909 int constantBits = 0;
910 String mask;
911 String constants;
912 // compute mask ("ra") and constant ("0, 0") strings, and fill in constantBits
913 for (int c : swizzle.fComponents) {
914 constantBits <<= 1;
915 switch (c) {
916 case SKSL_SWIZZLE_0:
917 constantBits |= 1;
918 if (constants.length() > 0) {
919 constants += ", ";
920 }
921 constants += "0";
922 break;
923 case SKSL_SWIZZLE_1:
924 constantBits |= 1;
925 if (constants.length() > 0) {
926 constants += ", ";
927 }
928 constants += "1";
929 break;
930 case 0:
931 mask += "x";
932 break;
933 case 1:
934 mask += "y";
935 break;
936 case 2:
937 mask += "z";
938 break;
939 case 3:
940 mask += "w";
941 break;
942 default:
943 SkASSERT(false);
944 }
945 }
946 switch (swizzle.fComponents.size()) {
947 case 1:
948 if (constantBits == 1) {
949 this->write(constants);
950 }
951 else {
952 this->writeSwizzleMask(swizzle, mask);
953 }
954 break;
955 case 2:
956 switch (constantBits) {
957 case 0: // 00
958 this->writeSwizzleMask(swizzle, mask);
959 break;
960 case 1: // 01
961 this->writeSwizzleConstructor(swizzle, constants, mask,
962 SwizzleOrder::MASK_FIRST);
963 break;
964 case 2: // 10
965 this->writeSwizzleConstructor(swizzle, constants, mask,
966 SwizzleOrder::CONSTANTS_FIRST);
967 break;
968 case 3: // 11
969 this->writeConstantSwizzle(swizzle, constants);
970 break;
971 default:
972 SkASSERT(false);
973 }
974 break;
975 case 3:
976 switch (constantBits) {
977 case 0: // 000
978 this->writeSwizzleMask(swizzle, mask);
979 break;
980 case 1: // 001
981 case 3: // 011
982 this->writeSwizzleConstructor(swizzle, constants, mask,
983 SwizzleOrder::MASK_FIRST);
984 break;
985 case 4: // 100
986 case 6: // 110
987 this->writeSwizzleConstructor(swizzle, constants, mask,
988 SwizzleOrder::CONSTANTS_FIRST);
989 break;
990 case 2: // 010
991 this->writeSwizzleConstructor(swizzle, constants, mask, "xzy");
992 break;
993 case 5: // 101
994 this->writeSwizzleConstructor(swizzle, constants, mask, "yxz");
995 break;
996 case 7: // 111
997 this->writeConstantSwizzle(swizzle, constants);
998 break;
999 }
1000 break;
1001 case 4:
1002 switch (constantBits) {
1003 case 0: // 0000
1004 this->writeSwizzleMask(swizzle, mask);
1005 break;
1006 case 1: // 0001
1007 case 3: // 0011
1008 case 7: // 0111
1009 this->writeSwizzleConstructor(swizzle, constants, mask,
1010 SwizzleOrder::MASK_FIRST);
1011 break;
1012 case 8: // 1000
1013 case 12: // 1100
1014 case 14: // 1110
1015 this->writeSwizzleConstructor(swizzle, constants, mask,
1016 SwizzleOrder::CONSTANTS_FIRST);
1017 break;
1018 case 2: // 0010
1019 this->writeSwizzleConstructor(swizzle, constants, mask, "xywz");
1020 break;
1021 case 4: // 0100
1022 this->writeSwizzleConstructor(swizzle, constants, mask, "xwyz");
1023 break;
1024 case 5: // 0101
1025 this->writeSwizzleConstructor(swizzle, constants, mask, "xzyw");
1026 break;
1027 case 6: // 0110
1028 this->writeSwizzleConstructor(swizzle, constants, mask, "xzwy");
1029 break;
1030 case 9: // 1001
1031 this->writeSwizzleConstructor(swizzle, constants, mask, "zxyw");
1032 break;
1033 case 10: // 1010
1034 this->writeSwizzleConstructor(swizzle, constants, mask, "zxwy");
1035 break;
1036 case 11: // 1011
1037 this->writeSwizzleConstructor(swizzle, constants, mask, "yxzw");
1038 break;
1039 case 13: // 1101
1040 this->writeSwizzleConstructor(swizzle, constants, mask, "yzxw");
1041 break;
1042 case 15: // 1111
1043 this->writeConstantSwizzle(swizzle, constants);
1044 break;
1045 }
1046 }
1047}
1048
1049GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) {
1050 switch (op) {
1051 case Token::STAR: // fall through
1052 case Token::SLASH: // fall through
1053 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence;
1054 case Token::PLUS: // fall through
1055 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence;
1056 case Token::SHL: // fall through
1057 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence;
1058 case Token::LT: // fall through
1059 case Token::GT: // fall through
1060 case Token::LTEQ: // fall through
1061 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence;
1062 case Token::EQEQ: // fall through
1063 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence;
1064 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence;
1065 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence;
1066 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence;
1067 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence;
1068 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence;
1069 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence;
1070 case Token::EQ: // fall through
1071 case Token::PLUSEQ: // fall through
1072 case Token::MINUSEQ: // fall through
1073 case Token::STAREQ: // fall through
1074 case Token::SLASHEQ: // fall through
1075 case Token::PERCENTEQ: // fall through
1076 case Token::SHLEQ: // fall through
1077 case Token::SHREQ: // fall through
1078 case Token::LOGICALANDEQ: // fall through
1079 case Token::LOGICALXOREQ: // fall through
1080 case Token::LOGICALOREQ: // fall through
1081 case Token::BITWISEANDEQ: // fall through
1082 case Token::BITWISEXOREQ: // fall through
1083 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence;
1084 case Token::COMMA: return GLSLCodeGenerator::kSequence_Precedence;
1085 default: ABORT("unsupported binary operator");
1086 }
1087}
1088
1089void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
1090 Precedence parentPrecedence) {
1091 if (fProgram.fSettings.fCaps->unfoldShortCircuitAsTernary() &&
1092 (b.fOperator == Token::LOGICALAND || b.fOperator == Token::LOGICALOR)) {
1093 this->writeShortCircuitWorkaroundExpression(b, parentPrecedence);
1094 return;
1095 }
1096
1097 Precedence precedence = GetBinaryPrecedence(b.fOperator);
1098 if (precedence >= parentPrecedence) {
1099 this->write("(");
1100 }
1101 bool positionWorkaround = fProgramKind == Program::Kind::kVertex_Kind &&
1102 Compiler::IsAssignment(b.fOperator) &&
1103 Expression::kFieldAccess_Kind == b.fLeft->fKind &&
1104 is_sk_position((FieldAccess&) *b.fLeft) &&
1105 !b.fRight->containsRTAdjust() &&
1106 !fProgram.fSettings.fCaps->canUseFragCoord();
1107 if (positionWorkaround) {
1108 this->write("sk_FragCoord_Workaround = (");
1109 }
1110 this->writeExpression(*b.fLeft, precedence);
1111 this->write(" ");
1112 this->write(Compiler::OperatorName(b.fOperator));
1113 this->write(" ");
1114 this->writeExpression(*b.fRight, precedence);
1115 if (positionWorkaround) {
1116 this->write(")");
1117 }
1118 if (precedence >= parentPrecedence) {
1119 this->write(")");
1120 }
1121}
1122
1123void GLSLCodeGenerator::writeShortCircuitWorkaroundExpression(const BinaryExpression& b,
1124 Precedence parentPrecedence) {
1125 if (kTernary_Precedence >= parentPrecedence) {
1126 this->write("(");
1127 }
1128
1129 // Transform:
1130 // a && b => a ? b : false
1131 // a || b => a ? true : b
1132 this->writeExpression(*b.fLeft, kTernary_Precedence);
1133 this->write(" ? ");
1134 if (b.fOperator == Token::LOGICALAND) {
1135 this->writeExpression(*b.fRight, kTernary_Precedence);
1136 } else {
1137 BoolLiteral boolTrue(fContext, -1, true);
1138 this->writeBoolLiteral(boolTrue);
1139 }
1140 this->write(" : ");
1141 if (b.fOperator == Token::LOGICALAND) {
1142 BoolLiteral boolFalse(fContext, -1, false);
1143 this->writeBoolLiteral(boolFalse);
1144 } else {
1145 this->writeExpression(*b.fRight, kTernary_Precedence);
1146 }
1147 if (kTernary_Precedence >= parentPrecedence) {
1148 this->write(")");
1149 }
1150}
1151
1152void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
1153 Precedence parentPrecedence) {
1154 if (kTernary_Precedence >= parentPrecedence) {
1155 this->write("(");
1156 }
1157 this->writeExpression(*t.fTest, kTernary_Precedence);
1158 this->write(" ? ");
1159 this->writeExpression(*t.fIfTrue, kTernary_Precedence);
1160 this->write(" : ");
1161 this->writeExpression(*t.fIfFalse, kTernary_Precedence);
1162 if (kTernary_Precedence >= parentPrecedence) {
1163 this->write(")");
1164 }
1165}
1166
1167void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
1168 Precedence parentPrecedence) {
1169 if (kPrefix_Precedence >= parentPrecedence) {
1170 this->write("(");
1171 }
1172 this->write(Compiler::OperatorName(p.fOperator));
1173 this->writeExpression(*p.fOperand, kPrefix_Precedence);
1174 if (kPrefix_Precedence >= parentPrecedence) {
1175 this->write(")");
1176 }
1177}
1178
1179void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
1180 Precedence parentPrecedence) {
1181 if (kPostfix_Precedence >= parentPrecedence) {
1182 this->write("(");
1183 }
1184 this->writeExpression(*p.fOperand, kPostfix_Precedence);
1185 this->write(Compiler::OperatorName(p.fOperator));
1186 if (kPostfix_Precedence >= parentPrecedence) {
1187 this->write(")");
1188 }
1189}
1190
1191void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
1192 this->write(b.fValue ? "true" : "false");
1193}
1194
1195void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
1196 if (i.fType == *fContext.fUInt_Type) {
1197 this->write(to_string(i.fValue & 0xffffffff) + "u");
1198 } else if (i.fType == *fContext.fUShort_Type) {
1199 this->write(to_string(i.fValue & 0xffff) + "u");
1200 } else if (i.fType == *fContext.fUByte_Type) {
1201 this->write(to_string(i.fValue & 0xff) + "u");
1202 } else {
1203 this->write(to_string((int32_t) i.fValue));
1204 }
1205}
1206
1207void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
1208 this->write(to_string(f.fValue));
1209}
1210
1211void GLSLCodeGenerator::writeSetting(const Setting& s) {
1212 ABORT("internal error; setting was not folded to a constant during compilation\n");
1213}
1214
1215void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
1216 fSetupFragPositionLocal = false;
1217 fSetupFragCoordWorkaround = false;
1218 if (fProgramKind != Program::kPipelineStage_Kind) {
1219 this->writeTypePrecision(f.fDeclaration.fReturnType);
1220 this->writeType(f.fDeclaration.fReturnType);
1221 this->write(" " + f.fDeclaration.fName + "(");
1222 const char* separator = "";
1223 for (const auto& param : f.fDeclaration.fParameters) {
1224 this->write(separator);
1225 separator = ", ";
1226 this->writeModifiers(param->fModifiers, false);
1227 std::vector<int> sizes;
1228 const Type* type = &param->fType;
1229 while (type->kind() == Type::kArray_Kind) {
1230 sizes.push_back(type->columns());
1231 type = &type->componentType();
1232 }
1233 this->writeTypePrecision(*type);
1234 this->writeType(*type);
1235 this->write(" " + param->fName);
1236 for (int s : sizes) {
1237 if (s <= 0) {
1238 this->write("[]");
1239 } else {
1240 this->write("[" + to_string(s) + "]");
1241 }
1242 }
1243 }
1244 this->writeLine(") {");
1245 fIndentation++;
1246 }
1247 fFunctionHeader = "";
1248 OutputStream* oldOut = fOut;
1249 StringStream buffer;
1250 fOut = &buffer;
1251 this->writeStatements(((Block&) *f.fBody).fStatements);
1252 if (fProgramKind != Program::kPipelineStage_Kind) {
1253 fIndentation--;
1254 this->writeLine("}");
1255 }
1256
1257 fOut = oldOut;
1258 this->write(fFunctionHeader);
1259 this->write(buffer.str());
1260}
1261
1262void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
1263 bool globalContext) {
1264 if (modifiers.fFlags & Modifiers::kFlat_Flag) {
1265 this->write("flat ");
1266 }
1267 if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
1268 this->write("noperspective ");
1269 }
1270 String layout = modifiers.fLayout.description();
1271 if (layout.size()) {
1272 this->write(layout + " ");
1273 }
1274 if (modifiers.fFlags & Modifiers::kReadOnly_Flag) {
1275 this->write("readonly ");
1276 }
1277 if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) {
1278 this->write("writeonly ");
1279 }
1280 if (modifiers.fFlags & Modifiers::kCoherent_Flag) {
1281 this->write("coherent ");
1282 }
1283 if (modifiers.fFlags & Modifiers::kVolatile_Flag) {
1284 this->write("volatile ");
1285 }
1286 if (modifiers.fFlags & Modifiers::kRestrict_Flag) {
1287 this->write("restrict ");
1288 }
1289 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
1290 (modifiers.fFlags & Modifiers::kOut_Flag)) {
1291 this->write("inout ");
1292 } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
1293 if (globalContext &&
1294 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
1295 this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
1296 : "varying ");
1297 } else {
1298 this->write("in ");
1299 }
1300 } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
1301 if (globalContext &&
1302 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
1303 this->write("varying ");
1304 } else {
1305 this->write("out ");
1306 }
1307 }
1308 if (modifiers.fFlags & Modifiers::kUniform_Flag) {
1309 this->write("uniform ");
1310 }
1311 if (modifiers.fFlags & Modifiers::kConst_Flag) {
1312 this->write("const ");
1313 }
1314 if (modifiers.fFlags & Modifiers::kPLS_Flag) {
1315 this->write("__pixel_localEXT ");
1316 }
1317 if (modifiers.fFlags & Modifiers::kPLSIn_Flag) {
1318 this->write("__pixel_local_inEXT ");
1319 }
1320 if (modifiers.fFlags & Modifiers::kPLSOut_Flag) {
1321 this->write("__pixel_local_outEXT ");
1322 }
1323 switch (modifiers.fLayout.fFormat) {
1324 case Layout::Format::kUnspecified:
1325 break;
1326 case Layout::Format::kRGBA32F: // fall through
1327 case Layout::Format::kR32F:
1328 this->write("highp ");
1329 break;
1330 case Layout::Format::kRGBA16F: // fall through
1331 case Layout::Format::kR16F: // fall through
1332 case Layout::Format::kLUMINANCE16F: // fall through
1333 case Layout::Format::kRG16F:
1334 this->write("mediump ");
1335 break;
1336 case Layout::Format::kRGBA8: // fall through
1337 case Layout::Format::kR8: // fall through
1338 case Layout::Format::kRGBA8I: // fall through
1339 case Layout::Format::kR8I:
1340 this->write("lowp ");
1341 break;
1342 }
1343}
1344
1345void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
1346 if (intf.fTypeName == "sk_PerVertex") {
1347 return;
1348 }
1349 this->writeModifiers(intf.fVariable.fModifiers, true);
1350 this->writeLine(intf.fTypeName + " {");
1351 fIndentation++;
1352 const Type* structType = &intf.fVariable.fType;
1353 while (structType->kind() == Type::kArray_Kind) {
1354 structType = &structType->componentType();
1355 }
1356 for (const auto& f : structType->fields()) {
1357 this->writeModifiers(f.fModifiers, false);
1358 this->writeTypePrecision(*f.fType);
1359 this->writeType(*f.fType);
1360 this->writeLine(" " + f.fName + ";");
1361 }
1362 fIndentation--;
1363 this->write("}");
1364 if (intf.fInstanceName.size()) {
1365 this->write(" ");
1366 this->write(intf.fInstanceName);
1367 for (const auto& size : intf.fSizes) {
1368 this->write("[");
1369 if (size) {
1370 this->writeExpression(*size, kTopLevel_Precedence);
1371 }
1372 this->write("]");
1373 }
1374 }
1375 this->writeLine(";");
1376}
1377
1378void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
1379 this->writeExpression(value, kTopLevel_Precedence);
1380}
1381
1382const char* GLSLCodeGenerator::getTypePrecision(const Type& type) {
1383 if (usesPrecisionModifiers()) {
1384 switch (type.kind()) {
1385 case Type::kScalar_Kind:
1386 if (type == *fContext.fShort_Type || type == *fContext.fUShort_Type ||
1387 type == *fContext.fByte_Type || type == *fContext.fUByte_Type) {
1388 if (fProgram.fSettings.fForceHighPrecision ||
1389 fProgram.fSettings.fCaps->incompleteShortIntPrecision()) {
1390 return "highp ";
1391 }
1392 return "mediump ";
1393 }
1394 if (type == *fContext.fHalf_Type) {
1395 return fProgram.fSettings.fForceHighPrecision ? "highp " : "mediump ";
1396 }
1397 if (type == *fContext.fFloat_Type || type == *fContext.fInt_Type ||
1398 type == *fContext.fUInt_Type) {
1399 return "highp ";
1400 }
1401 return "";
1402 case Type::kVector_Kind: // fall through
1403 case Type::kMatrix_Kind:
1404 return this->getTypePrecision(type.componentType());
1405 default:
1406 break;
1407 }
1408 }
1409 return "";
1410}
1411
1412void GLSLCodeGenerator::writeTypePrecision(const Type& type) {
1413 this->write(this->getTypePrecision(type));
1414}
1415
1416void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
1417 if (!decl.fVars.size()) {
1418 return;
1419 }
1420 bool wroteType = false;
1421 for (const auto& stmt : decl.fVars) {
1422 VarDeclaration& var = (VarDeclaration&) *stmt;
1423 if (wroteType) {
1424 this->write(", ");
1425 } else {
1426 this->writeModifiers(var.fVar->fModifiers, global);
1427 this->writeTypePrecision(decl.fBaseType);
1428 this->writeType(decl.fBaseType);
1429 this->write(" ");
1430 wroteType = true;
1431 }
1432 this->write(var.fVar->fName);
1433 for (const auto& size : var.fSizes) {
1434 this->write("[");
1435 if (size) {
1436 this->writeExpression(*size, kTopLevel_Precedence);
1437 }
1438 this->write("]");
1439 }
1440 if (var.fValue) {
1441 this->write(" = ");
1442 this->writeVarInitializer(*var.fVar, *var.fValue);
1443 }
1444 if (!fFoundExternalSamplerDecl && var.fVar->fType == *fContext.fSamplerExternalOES_Type) {
1445 if (fProgram.fSettings.fCaps->externalTextureExtensionString()) {
1446 this->writeExtension(fProgram.fSettings.fCaps->externalTextureExtensionString());
1447 }
1448 if (fProgram.fSettings.fCaps->secondExternalTextureExtensionString()) {
1449 this->writeExtension(
1450 fProgram.fSettings.fCaps->secondExternalTextureExtensionString());
1451 }
1452 fFoundExternalSamplerDecl = true;
1453 }
1454 if (!fFoundRectSamplerDecl && var.fVar->fType == *fContext.fSampler2DRect_Type) {
1455 fFoundRectSamplerDecl = true;
1456 }
1457 }
1458 if (wroteType) {
1459 this->write(";");
1460 }
1461}
1462
1463void GLSLCodeGenerator::writeStatement(const Statement& s) {
1464 switch (s.fKind) {
1465 case Statement::kBlock_Kind:
1466 this->writeBlock((Block&) s);
1467 break;
1468 case Statement::kExpression_Kind:
1469 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence);
1470 this->write(";");
1471 break;
1472 case Statement::kReturn_Kind:
1473 this->writeReturnStatement((ReturnStatement&) s);
1474 break;
1475 case Statement::kVarDeclarations_Kind:
1476 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
1477 break;
1478 case Statement::kIf_Kind:
1479 this->writeIfStatement((IfStatement&) s);
1480 break;
1481 case Statement::kFor_Kind:
1482 this->writeForStatement((ForStatement&) s);
1483 break;
1484 case Statement::kWhile_Kind:
1485 this->writeWhileStatement((WhileStatement&) s);
1486 break;
1487 case Statement::kDo_Kind:
1488 this->writeDoStatement((DoStatement&) s);
1489 break;
1490 case Statement::kSwitch_Kind:
1491 this->writeSwitchStatement((SwitchStatement&) s);
1492 break;
1493 case Statement::kBreak_Kind:
1494 this->write("break;");
1495 break;
1496 case Statement::kContinue_Kind:
1497 this->write("continue;");
1498 break;
1499 case Statement::kDiscard_Kind:
1500 this->write("discard;");
1501 break;
1502 case Statement::kNop_Kind:
1503 this->write(";");
1504 break;
1505 default:
1506#ifdef SK_DEBUG
1507 ABORT("unsupported statement: %s", s.description().c_str());
1508#endif
1509 break;
1510 }
1511}
1512
1513void GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statement>>& statements) {
1514 for (const auto& s : statements) {
1515 if (!s->isEmpty()) {
1516 this->writeStatement(*s);
1517 this->writeLine();
1518 }
1519 }
1520}
1521
1522void GLSLCodeGenerator::writeBlock(const Block& b) {
1523 this->writeLine("{");
1524 fIndentation++;
1525 this->writeStatements(b.fStatements);
1526 fIndentation--;
1527 this->write("}");
1528}
1529
1530void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
1531 this->write("if (");
1532 this->writeExpression(*stmt.fTest, kTopLevel_Precedence);
1533 this->write(") ");
1534 this->writeStatement(*stmt.fIfTrue);
1535 if (stmt.fIfFalse) {
1536 this->write(" else ");
1537 this->writeStatement(*stmt.fIfFalse);
1538 }
1539}
1540
1541void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
1542 this->write("for (");
1543 if (f.fInitializer && !f.fInitializer->isEmpty()) {
1544 this->writeStatement(*f.fInitializer);
1545 } else {
1546 this->write("; ");
1547 }
1548 if (f.fTest) {
1549 if (fProgram.fSettings.fCaps->addAndTrueToLoopCondition()) {
1550 std::unique_ptr<Expression> and_true(new BinaryExpression(
1551 -1, f.fTest->clone(), Token::LOGICALAND,
1552 std::unique_ptr<BoolLiteral>(new BoolLiteral(fContext, -1,
1553 true)),
1554 *fContext.fBool_Type));
1555 this->writeExpression(*and_true, kTopLevel_Precedence);
1556 } else {
1557 this->writeExpression(*f.fTest, kTopLevel_Precedence);
1558 }
1559 }
1560 this->write("; ");
1561 if (f.fNext) {
1562 this->writeExpression(*f.fNext, kTopLevel_Precedence);
1563 }
1564 this->write(") ");
1565 this->writeStatement(*f.fStatement);
1566}
1567
1568void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) {
1569 this->write("while (");
1570 this->writeExpression(*w.fTest, kTopLevel_Precedence);
1571 this->write(") ");
1572 this->writeStatement(*w.fStatement);
1573}
1574
1575void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
1576 if (!fProgram.fSettings.fCaps->rewriteDoWhileLoops()) {
1577 this->write("do ");
1578 this->writeStatement(*d.fStatement);
1579 this->write(" while (");
1580 this->writeExpression(*d.fTest, kTopLevel_Precedence);
1581 this->write(");");
1582 return;
1583 }
1584
1585 // Otherwise, do the do while loop workaround, to rewrite loops of the form:
1586 // do {
1587 // CODE;
1588 // } while (CONDITION)
1589 //
1590 // to loops of the form
1591 // bool temp = false;
1592 // while (true) {
1593 // if (temp) {
1594 // if (!CONDITION) {
1595 // break;
1596 // }
1597 // }
1598 // temp = true;
1599 // CODE;
1600 // }
1601 String tmpVar = "_tmpLoopSeenOnce" + to_string(fVarCount++);
1602 this->write("bool ");
1603 this->write(tmpVar);
1604 this->writeLine(" = false;");
1605 this->writeLine("while (true) {");
1606 fIndentation++;
1607 this->write("if (");
1608 this->write(tmpVar);
1609 this->writeLine(") {");
1610 fIndentation++;
1611 this->write("if (!");
1612 this->writeExpression(*d.fTest, kPrefix_Precedence);
1613 this->writeLine(") {");
1614 fIndentation++;
1615 this->writeLine("break;");
1616 fIndentation--;
1617 this->writeLine("}");
1618 fIndentation--;
1619 this->writeLine("}");
1620 this->write(tmpVar);
1621 this->writeLine(" = true;");
1622 this->writeStatement(*d.fStatement);
1623 this->writeLine();
1624 fIndentation--;
1625 this->write("}");
1626}
1627
1628void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
1629 this->write("switch (");
1630 this->writeExpression(*s.fValue, kTopLevel_Precedence);
1631 this->writeLine(") {");
1632 fIndentation++;
1633 for (const auto& c : s.fCases) {
1634 if (c->fValue) {
1635 this->write("case ");
1636 this->writeExpression(*c->fValue, kTopLevel_Precedence);
1637 this->writeLine(":");
1638 } else {
1639 this->writeLine("default:");
1640 }
1641 fIndentation++;
1642 for (const auto& stmt : c->fStatements) {
1643 this->writeStatement(*stmt);
1644 this->writeLine();
1645 }
1646 fIndentation--;
1647 }
1648 fIndentation--;
1649 this->write("}");
1650}
1651
1652void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
1653 this->write("return");
1654 if (r.fExpression) {
1655 this->write(" ");
1656 this->writeExpression(*r.fExpression, kTopLevel_Precedence);
1657 }
1658 this->write(";");
1659}
1660
1661void GLSLCodeGenerator::writeHeader() {
1662 this->write(fProgram.fSettings.fCaps->versionDeclString());
1663 this->writeLine();
1664}
1665
1666void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
1667 switch (e.fKind) {
1668 case ProgramElement::kExtension_Kind:
1669 this->writeExtension(((Extension&) e).fName);
1670 break;
1671 case ProgramElement::kVar_Kind: {
1672 VarDeclarations& decl = (VarDeclarations&) e;
1673 if (decl.fVars.size() > 0) {
1674 int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin;
1675 if (builtin == -1) {
1676 // normal var
1677 this->writeVarDeclarations(decl, true);
1678 this->writeLine();
1679 } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
1680 fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput() &&
1681 ((VarDeclaration&) *decl.fVars[0]).fVar->fWriteCount) {
1682 if (fProgram.fSettings.fFragColorIsInOut) {
1683 this->write("inout ");
1684 } else {
1685 this->write("out ");
1686 }
1687 if (usesPrecisionModifiers()) {
1688 this->write("mediump ");
1689 }
1690 this->writeLine("vec4 sk_FragColor;");
1691 }
1692 }
1693 break;
1694 }
1695 case ProgramElement::kInterfaceBlock_Kind:
1696 this->writeInterfaceBlock((InterfaceBlock&) e);
1697 break;
1698 case ProgramElement::kFunction_Kind:
1699 this->writeFunction((FunctionDefinition&) e);
1700 break;
1701 case ProgramElement::kModifiers_Kind: {
1702 const Modifiers& modifiers = ((ModifiersDeclaration&) e).fModifiers;
1703 if (!fFoundGSInvocations && modifiers.fLayout.fInvocations >= 0) {
1704 if (fProgram.fSettings.fCaps->gsInvocationsExtensionString()) {
1705 this->writeExtension(fProgram.fSettings.fCaps->gsInvocationsExtensionString());
1706 }
1707 fFoundGSInvocations = true;
1708 }
1709 this->writeModifiers(modifiers, true);
1710 this->writeLine(";");
1711 break;
1712 }
1713 case ProgramElement::kEnum_Kind:
1714 break;
1715 default:
1716#ifdef SK_DEBUG
1717 printf("unsupported program element %s\n", e.description().c_str());
1718#endif
1719 SkASSERT(false);
1720 }
1721}
1722
1723void GLSLCodeGenerator::writeInputVars() {
1724 if (fProgram.fInputs.fRTWidth) {
1725 const char* precision = usesPrecisionModifiers() ? "highp " : "";
1726 fGlobals.writeText("uniform ");
1727 fGlobals.writeText(precision);
1728 fGlobals.writeText("float " SKSL_RTWIDTH_NAME ";\n");
1729 }
1730 if (fProgram.fInputs.fRTHeight) {
1731 const char* precision = usesPrecisionModifiers() ? "highp " : "";
1732 fGlobals.writeText("uniform ");
1733 fGlobals.writeText(precision);
1734 fGlobals.writeText("float " SKSL_RTHEIGHT_NAME ";\n");
1735 }
1736}
1737
1738bool GLSLCodeGenerator::generateCode() {
1739 if (fProgramKind != Program::kPipelineStage_Kind) {
1740 this->writeHeader();
1741 }
1742 if (Program::kGeometry_Kind == fProgramKind &&
1743 fProgram.fSettings.fCaps->geometryShaderExtensionString()) {
1744 this->writeExtension(fProgram.fSettings.fCaps->geometryShaderExtensionString());
1745 }
1746 OutputStream* rawOut = fOut;
1747 StringStream body;
1748 fOut = &body;
1749 for (const auto& e : fProgram) {
1750 this->writeProgramElement(e);
1751 }
1752 fOut = rawOut;
1753
1754 write_stringstream(fExtensions, *rawOut);
1755 this->writeInputVars();
1756 write_stringstream(fGlobals, *rawOut);
1757
1758 if (!fProgram.fSettings.fCaps->canUseFragCoord()) {
1759 Layout layout;
1760 switch (fProgram.fKind) {
1761 case Program::kVertex_Kind: {
1762 Modifiers modifiers(layout, Modifiers::kOut_Flag);
1763 this->writeModifiers(modifiers, true);
1764 if (this->usesPrecisionModifiers()) {
1765 this->write("highp ");
1766 }
1767 this->write("vec4 sk_FragCoord_Workaround;\n");
1768 break;
1769 }
1770 case Program::kFragment_Kind: {
1771 Modifiers modifiers(layout, Modifiers::kIn_Flag);
1772 this->writeModifiers(modifiers, true);
1773 if (this->usesPrecisionModifiers()) {
1774 this->write("highp ");
1775 }
1776 this->write("vec4 sk_FragCoord_Workaround;\n");
1777 break;
1778 }
1779 default:
1780 break;
1781 }
1782 }
1783
1784 if (this->usesPrecisionModifiers()) {
1785 this->writeLine("precision mediump float;");
1786 this->writeLine("precision mediump sampler2D;");
1787 if (fFoundExternalSamplerDecl &&
1788 !fProgram.fSettings.fCaps->noDefaultPrecisionForExternalSamplers()) {
1789 this->writeLine("precision mediump samplerExternalOES;");
1790 }
1791 if (fFoundRectSamplerDecl) {
1792 this->writeLine("precision mediump sampler2DRect;");
1793 }
1794 }
1795 write_stringstream(fExtraFunctions, *rawOut);
1796 write_stringstream(body, *rawOut);
1797 return true;
1798}
1799
1800}
1801