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