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