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 "GLSL.std.450.h"
11
12 #include "SkSLCompiler.h"
13 #include "ir/SkSLExpressionStatement.h"
14 #include "ir/SkSLExtension.h"
15 #include "ir/SkSLIndexExpression.h"
16 #include "ir/SkSLModifiersDeclaration.h"
17 #include "ir/SkSLNop.h"
18 #include "ir/SkSLVariableReference.h"
19
20 namespace SkSL {
21
write(const char * s)22 void GLSLCodeGenerator::write(const char* s) {
23 if (s[0] == 0) {
24 return;
25 }
26 if (fAtLineStart) {
27 for (int i = 0; i < fIndentation; i++) {
28 fOut->writeText(" ");
29 }
30 }
31 fOut->writeText(s);
32 fAtLineStart = false;
33 }
34
writeLine(const char * s)35 void GLSLCodeGenerator::writeLine(const char* s) {
36 this->write(s);
37 fOut->writeText(fLineEnding);
38 fAtLineStart = true;
39 }
40
write(const String & s)41 void GLSLCodeGenerator::write(const String& s) {
42 this->write(s.c_str());
43 }
44
writeLine(const String & s)45 void GLSLCodeGenerator::writeLine(const String& s) {
46 this->writeLine(s.c_str());
47 }
48
writeLine()49 void GLSLCodeGenerator::writeLine() {
50 this->writeLine("");
51 }
52
writeExtension(const Extension & ext)53 void GLSLCodeGenerator::writeExtension(const Extension& ext) {
54 this->writeLine("#extension " + ext.fName + " : enable");
55 }
56
writeType(const Type & type)57 void GLSLCodeGenerator::writeType(const Type& type) {
58 if (type.kind() == Type::kStruct_Kind) {
59 for (const Type* search : fWrittenStructs) {
60 if (*search == type) {
61 // already written
62 this->write(type.name());
63 return;
64 }
65 }
66 fWrittenStructs.push_back(&type);
67 this->writeLine("struct " + type.name() + " {");
68 fIndentation++;
69 for (const auto& f : type.fields()) {
70 this->writeModifiers(f.fModifiers, false);
71 // sizes (which must be static in structs) are part of the type name here
72 this->writeType(*f.fType);
73 this->writeLine(" " + f.fName + ";");
74 }
75 fIndentation--;
76 this->write("}");
77 } else {
78 this->write(type.name());
79 }
80 }
81
writeExpression(const Expression & expr,Precedence parentPrecedence)82 void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
83 switch (expr.fKind) {
84 case Expression::kBinary_Kind:
85 this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence);
86 break;
87 case Expression::kBoolLiteral_Kind:
88 this->writeBoolLiteral((BoolLiteral&) expr);
89 break;
90 case Expression::kConstructor_Kind:
91 this->writeConstructor((Constructor&) expr);
92 break;
93 case Expression::kIntLiteral_Kind:
94 this->writeIntLiteral((IntLiteral&) expr);
95 break;
96 case Expression::kFieldAccess_Kind:
97 this->writeFieldAccess(((FieldAccess&) expr));
98 break;
99 case Expression::kFloatLiteral_Kind:
100 this->writeFloatLiteral(((FloatLiteral&) expr));
101 break;
102 case Expression::kFunctionCall_Kind:
103 this->writeFunctionCall((FunctionCall&) expr);
104 break;
105 case Expression::kPrefix_Kind:
106 this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence);
107 break;
108 case Expression::kPostfix_Kind:
109 this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence);
110 break;
111 case Expression::kSetting_Kind:
112 this->writeSetting((Setting&) expr);
113 break;
114 case Expression::kSwizzle_Kind:
115 this->writeSwizzle((Swizzle&) expr);
116 break;
117 case Expression::kVariableReference_Kind:
118 this->writeVariableReference((VariableReference&) expr);
119 break;
120 case Expression::kTernary_Kind:
121 this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence);
122 break;
123 case Expression::kIndex_Kind:
124 this->writeIndexExpression((IndexExpression&) expr);
125 break;
126 default:
127 ABORT("unsupported expression: %s", expr.description().c_str());
128 }
129 }
130
is_abs(Expression & expr)131 static bool is_abs(Expression& expr) {
132 if (expr.fKind != Expression::kFunctionCall_Kind) {
133 return false;
134 }
135 return ((FunctionCall&) expr).fFunction.fName == "abs";
136 }
137
138 // turns min(abs(x), y) into ((tmpVar1 = abs(x)) < (tmpVar2 = y) ? tmpVar1 : tmpVar2) to avoid a
139 // Tegra3 compiler bug.
writeMinAbsHack(Expression & absExpr,Expression & otherExpr)140 void GLSLCodeGenerator::writeMinAbsHack(Expression& absExpr, Expression& otherExpr) {
141 ASSERT(!fProgram.fSettings.fCaps->canUseMinAndAbsTogether());
142 String tmpVar1 = "minAbsHackVar" + to_string(fVarCount++);
143 String tmpVar2 = "minAbsHackVar" + to_string(fVarCount++);
144 this->fFunctionHeader += " " + absExpr.fType.name() + " " + tmpVar1 + ";\n";
145 this->fFunctionHeader += " " + otherExpr.fType.name() + " " + tmpVar2 + ";\n";
146 this->write("((" + tmpVar1 + " = ");
147 this->writeExpression(absExpr, kTopLevel_Precedence);
148 this->write(") < (" + tmpVar2 + " = ");
149 this->writeExpression(otherExpr, kAssignment_Precedence);
150 this->write(") ? " + tmpVar1 + " : " + tmpVar2 + ")");
151 }
152
writeFunctionCall(const FunctionCall & c)153 void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
154 if (!fProgram.fSettings.fCaps->canUseMinAndAbsTogether() && c.fFunction.fName == "min" &&
155 c.fFunction.fBuiltin) {
156 ASSERT(c.fArguments.size() == 2);
157 if (is_abs(*c.fArguments[0])) {
158 this->writeMinAbsHack(*c.fArguments[0], *c.fArguments[1]);
159 return;
160 }
161 if (is_abs(*c.fArguments[1])) {
162 // note that this violates the GLSL left-to-right evaluation semantics. I doubt it will
163 // ever end up mattering, but it's worth calling out.
164 this->writeMinAbsHack(*c.fArguments[1], *c.fArguments[0]);
165 return;
166 }
167 }
168 if (fProgram.fSettings.fCaps->mustForceNegatedAtanParamToFloat() &&
169 c.fFunction.fName == "atan" &&
170 c.fFunction.fBuiltin && c.fArguments.size() == 2 &&
171 c.fArguments[1]->fKind == Expression::kPrefix_Kind) {
172 const PrefixExpression& p = (PrefixExpression&) *c.fArguments[1];
173 if (p.fOperator == Token::MINUS) {
174 this->write("atan(");
175 this->writeExpression(*c.fArguments[0], kSequence_Precedence);
176 this->write(", -1.0 * ");
177 this->writeExpression(*p.fOperand, kMultiplicative_Precedence);
178 this->write(")");
179 return;
180 }
181 }
182 if (!fFoundDerivatives && (c.fFunction.fName == "dFdx" || c.fFunction.fName == "dFdy") &&
183 c.fFunction.fBuiltin && fProgram.fSettings.fCaps->shaderDerivativeExtensionString()) {
184 ASSERT(fProgram.fSettings.fCaps->shaderDerivativeSupport());
185 fHeader.writeText("#extension ");
186 fHeader.writeText(fProgram.fSettings.fCaps->shaderDerivativeExtensionString());
187 fHeader.writeText(" : require\n");
188 fFoundDerivatives = true;
189 }
190 if (c.fFunction.fName == "texture" && c.fFunction.fBuiltin) {
191 const char* dim = "";
192 bool proj = false;
193 switch (c.fArguments[0]->fType.dimensions()) {
194 case SpvDim1D:
195 dim = "1D";
196 if (c.fArguments[1]->fType == *fContext.fFloat_Type) {
197 proj = false;
198 } else {
199 ASSERT(c.fArguments[1]->fType == *fContext.fVec2_Type);
200 proj = true;
201 }
202 break;
203 case SpvDim2D:
204 dim = "2D";
205 if (c.fArguments[1]->fType == *fContext.fVec2_Type) {
206 proj = false;
207 } else {
208 ASSERT(c.fArguments[1]->fType == *fContext.fVec3_Type);
209 proj = true;
210 }
211 break;
212 case SpvDim3D:
213 dim = "3D";
214 if (c.fArguments[1]->fType == *fContext.fVec3_Type) {
215 proj = false;
216 } else {
217 ASSERT(c.fArguments[1]->fType == *fContext.fVec4_Type);
218 proj = true;
219 }
220 break;
221 case SpvDimCube:
222 dim = "Cube";
223 proj = false;
224 break;
225 case SpvDimRect:
226 dim = "Rect";
227 proj = false;
228 break;
229 case SpvDimBuffer:
230 ASSERT(false); // doesn't exist
231 dim = "Buffer";
232 proj = false;
233 break;
234 case SpvDimSubpassData:
235 ASSERT(false); // doesn't exist
236 dim = "SubpassData";
237 proj = false;
238 break;
239 }
240 this->write("texture");
241 if (fProgram.fSettings.fCaps->generation() < k130_GrGLSLGeneration) {
242 this->write(dim);
243 }
244 if (proj) {
245 this->write("Proj");
246 }
247
248 } else {
249 this->write(c.fFunction.fName);
250 }
251 this->write("(");
252 const char* separator = "";
253 for (const auto& arg : c.fArguments) {
254 this->write(separator);
255 separator = ", ";
256 this->writeExpression(*arg, kSequence_Precedence);
257 }
258 this->write(")");
259 }
260
writeConstructor(const Constructor & c)261 void GLSLCodeGenerator::writeConstructor(const Constructor& c) {
262 this->write(c.fType.name() + "(");
263 const char* separator = "";
264 for (const auto& arg : c.fArguments) {
265 this->write(separator);
266 separator = ", ";
267 this->writeExpression(*arg, kSequence_Precedence);
268 }
269 this->write(")");
270 }
271
writeFragCoord()272 void GLSLCodeGenerator::writeFragCoord() {
273 // We only declare "gl_FragCoord" when we're in the case where we want to use layout qualifiers
274 // to reverse y. Otherwise it isn't necessary and whether the "in" qualifier appears in the
275 // declaration varies in earlier GLSL specs. So it is simpler to omit it.
276 if (!fProgram.fSettings.fFlipY) {
277 this->write("gl_FragCoord");
278 } else if (const char* extension =
279 fProgram.fSettings.fCaps->fragCoordConventionsExtensionString()) {
280 if (!fSetupFragPositionGlobal) {
281 if (fProgram.fSettings.fCaps->generation() < k150_GrGLSLGeneration) {
282 fHeader.writeText("#extension ");
283 fHeader.writeText(extension);
284 fHeader.writeText(" : require\n");
285 }
286 fHeader.writeText("layout(origin_upper_left) in vec4 gl_FragCoord;\n");
287 fSetupFragPositionGlobal = true;
288 }
289 this->write("gl_FragCoord");
290 } else {
291 if (!fSetupFragPositionGlobal) {
292 // The Adreno compiler seems to be very touchy about access to "gl_FragCoord".
293 // Accessing glFragCoord.zw can cause a program to fail to link. Additionally,
294 // depending on the surrounding code, accessing .xy with a uniform involved can
295 // do the same thing. Copying gl_FragCoord.xy into a temp vec2 beforehand
296 // (and only accessing .xy) seems to "fix" things.
297 const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
298 : "";
299 fHeader.writeText("uniform ");
300 fHeader.writeText(precision);
301 fHeader.writeText("float " SKSL_RTHEIGHT_NAME ";\n");
302 fSetupFragPositionGlobal = true;
303 }
304 if (!fSetupFragPositionLocal) {
305 const char* precision = fProgram.fSettings.fCaps->usesPrecisionModifiers() ? "highp "
306 : "";
307 fFunctionHeader += precision;
308 fFunctionHeader += " vec2 _sktmpCoord = gl_FragCoord.xy;\n";
309 fFunctionHeader += precision;
310 fFunctionHeader += " vec4 sk_FragCoord = vec4(_sktmpCoord.x, " SKSL_RTHEIGHT_NAME
311 " - _sktmpCoord.y, 1.0, 1.0);\n";
312 fSetupFragPositionLocal = true;
313 }
314 this->write("sk_FragCoord");
315 }
316 }
317
318
writeVariableReference(const VariableReference & ref)319 void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
320 switch (ref.fVariable.fModifiers.fLayout.fBuiltin) {
321 case SK_FRAGCOLOR_BUILTIN:
322 if (fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
323 this->write("sk_FragColor");
324 } else {
325 this->write("gl_FragColor");
326 }
327 break;
328 case SK_FRAGCOORD_BUILTIN:
329 this->writeFragCoord();
330 break;
331 case SK_VERTEXID_BUILTIN:
332 this->write("gl_VertexID");
333 break;
334 case SK_CLIPDISTANCE_BUILTIN:
335 this->write("gl_ClipDistance");
336 break;
337 case SK_IN_BUILTIN:
338 this->write("gl_in");
339 break;
340 case SK_INVOCATIONID_BUILTIN:
341 this->write("gl_InvocationID");
342 break;
343 default:
344 this->write(ref.fVariable.fName);
345 }
346 }
347
writeIndexExpression(const IndexExpression & expr)348 void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
349 this->writeExpression(*expr.fBase, kPostfix_Precedence);
350 this->write("[");
351 this->writeExpression(*expr.fIndex, kTopLevel_Precedence);
352 this->write("]");
353 }
354
writeFieldAccess(const FieldAccess & f)355 void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
356 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) {
357 this->writeExpression(*f.fBase, kPostfix_Precedence);
358 this->write(".");
359 }
360 switch (f.fBase->fType.fields()[f.fFieldIndex].fModifiers.fLayout.fBuiltin) {
361 case SK_CLIPDISTANCE_BUILTIN:
362 this->write("gl_ClipDistance");
363 break;
364 default:
365 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName);
366 }
367 }
368
writeSwizzle(const Swizzle & swizzle)369 void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
370 this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
371 this->write(".");
372 for (int c : swizzle.fComponents) {
373 this->write(&("x\0y\0z\0w\0"[c * 2]));
374 }
375 }
376
GetBinaryPrecedence(Token::Kind op)377 GLSLCodeGenerator::Precedence GLSLCodeGenerator::GetBinaryPrecedence(Token::Kind op) {
378 switch (op) {
379 case Token::STAR: // fall through
380 case Token::SLASH: // fall through
381 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence;
382 case Token::PLUS: // fall through
383 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence;
384 case Token::SHL: // fall through
385 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence;
386 case Token::LT: // fall through
387 case Token::GT: // fall through
388 case Token::LTEQ: // fall through
389 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence;
390 case Token::EQEQ: // fall through
391 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence;
392 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence;
393 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence;
394 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence;
395 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence;
396 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence;
397 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence;
398 case Token::EQ: // fall through
399 case Token::PLUSEQ: // fall through
400 case Token::MINUSEQ: // fall through
401 case Token::STAREQ: // fall through
402 case Token::SLASHEQ: // fall through
403 case Token::PERCENTEQ: // fall through
404 case Token::SHLEQ: // fall through
405 case Token::SHREQ: // fall through
406 case Token::LOGICALANDEQ: // fall through
407 case Token::LOGICALXOREQ: // fall through
408 case Token::LOGICALOREQ: // fall through
409 case Token::BITWISEANDEQ: // fall through
410 case Token::BITWISEXOREQ: // fall through
411 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence;
412 case Token::COMMA: return GLSLCodeGenerator::kSequence_Precedence;
413 default: ABORT("unsupported binary operator");
414 }
415 }
416
writeBinaryExpression(const BinaryExpression & b,Precedence parentPrecedence)417 void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
418 Precedence parentPrecedence) {
419 Precedence precedence = GetBinaryPrecedence(b.fOperator);
420 if (precedence >= parentPrecedence) {
421 this->write("(");
422 }
423 this->writeExpression(*b.fLeft, precedence);
424 this->write(" " + Token::OperatorName(b.fOperator) + " ");
425 this->writeExpression(*b.fRight, precedence);
426 if (precedence >= parentPrecedence) {
427 this->write(")");
428 }
429 }
430
writeTernaryExpression(const TernaryExpression & t,Precedence parentPrecedence)431 void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
432 Precedence parentPrecedence) {
433 if (kTernary_Precedence >= parentPrecedence) {
434 this->write("(");
435 }
436 this->writeExpression(*t.fTest, kTernary_Precedence);
437 this->write(" ? ");
438 this->writeExpression(*t.fIfTrue, kTernary_Precedence);
439 this->write(" : ");
440 this->writeExpression(*t.fIfFalse, kTernary_Precedence);
441 if (kTernary_Precedence >= parentPrecedence) {
442 this->write(")");
443 }
444 }
445
writePrefixExpression(const PrefixExpression & p,Precedence parentPrecedence)446 void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
447 Precedence parentPrecedence) {
448 if (kPrefix_Precedence >= parentPrecedence) {
449 this->write("(");
450 }
451 this->write(Token::OperatorName(p.fOperator));
452 this->writeExpression(*p.fOperand, kPrefix_Precedence);
453 if (kPrefix_Precedence >= parentPrecedence) {
454 this->write(")");
455 }
456 }
457
writePostfixExpression(const PostfixExpression & p,Precedence parentPrecedence)458 void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
459 Precedence parentPrecedence) {
460 if (kPostfix_Precedence >= parentPrecedence) {
461 this->write("(");
462 }
463 this->writeExpression(*p.fOperand, kPostfix_Precedence);
464 this->write(Token::OperatorName(p.fOperator));
465 if (kPostfix_Precedence >= parentPrecedence) {
466 this->write(")");
467 }
468 }
469
writeBoolLiteral(const BoolLiteral & b)470 void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
471 this->write(b.fValue ? "true" : "false");
472 }
473
writeIntLiteral(const IntLiteral & i)474 void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
475 if (i.fType == *fContext.fUInt_Type) {
476 this->write(to_string(i.fValue & 0xffffffff) + "u");
477 } else {
478 this->write(to_string((int32_t) i.fValue));
479 }
480 }
481
writeFloatLiteral(const FloatLiteral & f)482 void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
483 this->write(to_string(f.fValue));
484 }
485
writeSetting(const Setting & s)486 void GLSLCodeGenerator::writeSetting(const Setting& s) {
487 ABORT("internal error; setting was not folded to a constant during compilation\n");
488 }
489
writeFunction(const FunctionDefinition & f)490 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
491 this->writeType(f.fDeclaration.fReturnType);
492 this->write(" " + f.fDeclaration.fName + "(");
493 const char* separator = "";
494 for (const auto& param : f.fDeclaration.fParameters) {
495 this->write(separator);
496 separator = ", ";
497 this->writeModifiers(param->fModifiers, false);
498 std::vector<int> sizes;
499 const Type* type = ¶m->fType;
500 while (type->kind() == Type::kArray_Kind) {
501 sizes.push_back(type->columns());
502 type = &type->componentType();
503 }
504 this->writeType(*type);
505 this->write(" " + param->fName);
506 for (int s : sizes) {
507 if (s <= 0) {
508 this->write("[]");
509 } else {
510 this->write("[" + to_string(s) + "]");
511 }
512 }
513 }
514 this->writeLine(") {");
515
516 fFunctionHeader = "";
517 OutputStream* oldOut = fOut;
518 StringStream buffer;
519 fOut = &buffer;
520 fIndentation++;
521 this->writeStatements(((Block&) *f.fBody).fStatements);
522 fIndentation--;
523 this->writeLine("}");
524
525 fOut = oldOut;
526 this->write(fFunctionHeader);
527 this->write(buffer.str());
528 }
529
writeModifiers(const Modifiers & modifiers,bool globalContext)530 void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers,
531 bool globalContext) {
532 if (modifiers.fFlags & Modifiers::kFlat_Flag) {
533 this->write("flat ");
534 }
535 if (modifiers.fFlags & Modifiers::kNoPerspective_Flag) {
536 this->write("noperspective ");
537 }
538 String layout = modifiers.fLayout.description();
539 if (layout.size()) {
540 this->write(layout + " ");
541 }
542 if (modifiers.fFlags & Modifiers::kReadOnly_Flag) {
543 this->write("readonly ");
544 }
545 if (modifiers.fFlags & Modifiers::kWriteOnly_Flag) {
546 this->write("writeonly ");
547 }
548 if (modifiers.fFlags & Modifiers::kCoherent_Flag) {
549 this->write("coherent ");
550 }
551 if (modifiers.fFlags & Modifiers::kVolatile_Flag) {
552 this->write("volatile ");
553 }
554 if (modifiers.fFlags & Modifiers::kRestrict_Flag) {
555 this->write("restrict ");
556 }
557 if ((modifiers.fFlags & Modifiers::kIn_Flag) &&
558 (modifiers.fFlags & Modifiers::kOut_Flag)) {
559 this->write("inout ");
560 } else if (modifiers.fFlags & Modifiers::kIn_Flag) {
561 if (globalContext &&
562 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
563 this->write(fProgramKind == Program::kVertex_Kind ? "attribute "
564 : "varying ");
565 } else {
566 this->write("in ");
567 }
568 } else if (modifiers.fFlags & Modifiers::kOut_Flag) {
569 if (globalContext &&
570 fProgram.fSettings.fCaps->generation() < GrGLSLGeneration::k130_GrGLSLGeneration) {
571 this->write("varying ");
572 } else {
573 this->write("out ");
574 }
575 }
576 if (modifiers.fFlags & Modifiers::kUniform_Flag) {
577 this->write("uniform ");
578 }
579 if (modifiers.fFlags & Modifiers::kConst_Flag) {
580 this->write("const ");
581 }
582 if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
583 if (modifiers.fFlags & Modifiers::kLowp_Flag) {
584 this->write("lowp ");
585 }
586 if (modifiers.fFlags & Modifiers::kMediump_Flag) {
587 this->write("mediump ");
588 }
589 if (modifiers.fFlags & Modifiers::kHighp_Flag) {
590 this->write("highp ");
591 }
592 }
593 }
594
writeInterfaceBlock(const InterfaceBlock & intf)595 void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
596 if (intf.fTypeName == "sk_PerVertex") {
597 return;
598 }
599 this->writeModifiers(intf.fVariable.fModifiers, true);
600 this->writeLine(intf.fTypeName + " {");
601 fIndentation++;
602 const Type* structType = &intf.fVariable.fType;
603 while (structType->kind() == Type::kArray_Kind) {
604 structType = &structType->componentType();
605 }
606 for (const auto& f : structType->fields()) {
607 this->writeModifiers(f.fModifiers, false);
608 this->writeType(*f.fType);
609 this->writeLine(" " + f.fName + ";");
610 }
611 fIndentation--;
612 this->write("}");
613 if (intf.fInstanceName.size()) {
614 this->write(" ");
615 this->write(intf.fInstanceName);
616 for (const auto& size : intf.fSizes) {
617 this->write("[");
618 if (size) {
619 this->writeExpression(*size, kTopLevel_Precedence);
620 }
621 this->write("]");
622 }
623 }
624 this->writeLine(";");
625 }
626
writeVarInitializer(const Variable & var,const Expression & value)627 void GLSLCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
628 this->writeExpression(value, kTopLevel_Precedence);
629 }
630
writeVarDeclarations(const VarDeclarations & decl,bool global)631 void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl, bool global) {
632 ASSERT(decl.fVars.size() > 0);
633 bool wroteType = false;
634 for (const auto& stmt : decl.fVars) {
635 VarDeclaration& var = (VarDeclaration&) *stmt;
636 if (wroteType) {
637 this->write(", ");
638 } else {
639 this->writeModifiers(var.fVar->fModifiers, global);
640 this->writeType(decl.fBaseType);
641 this->write(" ");
642 wroteType = true;
643 }
644 this->write(var.fVar->fName);
645 for (const auto& size : var.fSizes) {
646 this->write("[");
647 if (size) {
648 this->writeExpression(*size, kTopLevel_Precedence);
649 }
650 this->write("]");
651 }
652 if (var.fValue) {
653 this->write(" = ");
654 this->writeVarInitializer(*var.fVar, *var.fValue);
655 }
656 if (!fFoundImageDecl && var.fVar->fType == *fContext.fImage2D_Type) {
657 if (fProgram.fSettings.fCaps->imageLoadStoreExtensionString()) {
658 fHeader.writeText("#extension ");
659 fHeader.writeText(fProgram.fSettings.fCaps->imageLoadStoreExtensionString());
660 fHeader.writeText(" : require\n");
661 }
662 fFoundImageDecl = true;
663 }
664 }
665 if (wroteType) {
666 this->write(";");
667 }
668 }
669
writeStatement(const Statement & s)670 void GLSLCodeGenerator::writeStatement(const Statement& s) {
671 switch (s.fKind) {
672 case Statement::kBlock_Kind:
673 this->writeBlock((Block&) s);
674 break;
675 case Statement::kExpression_Kind:
676 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence);
677 this->write(";");
678 break;
679 case Statement::kReturn_Kind:
680 this->writeReturnStatement((ReturnStatement&) s);
681 break;
682 case Statement::kVarDeclarations_Kind:
683 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration, false);
684 break;
685 case Statement::kIf_Kind:
686 this->writeIfStatement((IfStatement&) s);
687 break;
688 case Statement::kFor_Kind:
689 this->writeForStatement((ForStatement&) s);
690 break;
691 case Statement::kWhile_Kind:
692 this->writeWhileStatement((WhileStatement&) s);
693 break;
694 case Statement::kDo_Kind:
695 this->writeDoStatement((DoStatement&) s);
696 break;
697 case Statement::kSwitch_Kind:
698 this->writeSwitchStatement((SwitchStatement&) s);
699 break;
700 case Statement::kBreak_Kind:
701 this->write("break;");
702 break;
703 case Statement::kContinue_Kind:
704 this->write("continue;");
705 break;
706 case Statement::kDiscard_Kind:
707 this->write("discard;");
708 break;
709 case Statement::kNop_Kind:
710 this->write(";");
711 break;
712 default:
713 ABORT("unsupported statement: %s", s.description().c_str());
714 }
715 }
716
writeStatements(const std::vector<std::unique_ptr<Statement>> & statements)717 void GLSLCodeGenerator::writeStatements(const std::vector<std::unique_ptr<Statement>>& statements) {
718 for (const auto& s : statements) {
719 if (!s->isEmpty()) {
720 this->writeStatement(*s);
721 this->writeLine();
722 }
723 }
724 }
725
writeBlock(const Block & b)726 void GLSLCodeGenerator::writeBlock(const Block& b) {
727 this->writeLine("{");
728 fIndentation++;
729 this->writeStatements(b.fStatements);
730 fIndentation--;
731 this->write("}");
732 }
733
writeIfStatement(const IfStatement & stmt)734 void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
735 this->write("if (");
736 this->writeExpression(*stmt.fTest, kTopLevel_Precedence);
737 this->write(") ");
738 this->writeStatement(*stmt.fIfTrue);
739 if (stmt.fIfFalse) {
740 this->write(" else ");
741 this->writeStatement(*stmt.fIfFalse);
742 }
743 }
744
writeForStatement(const ForStatement & f)745 void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
746 this->write("for (");
747 if (f.fInitializer && !f.fInitializer->isEmpty()) {
748 this->writeStatement(*f.fInitializer);
749 } else {
750 this->write("; ");
751 }
752 if (f.fTest) {
753 this->writeExpression(*f.fTest, kTopLevel_Precedence);
754 }
755 this->write("; ");
756 if (f.fNext) {
757 this->writeExpression(*f.fNext, kTopLevel_Precedence);
758 }
759 this->write(") ");
760 this->writeStatement(*f.fStatement);
761 }
762
writeWhileStatement(const WhileStatement & w)763 void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) {
764 this->write("while (");
765 this->writeExpression(*w.fTest, kTopLevel_Precedence);
766 this->write(") ");
767 this->writeStatement(*w.fStatement);
768 }
769
writeDoStatement(const DoStatement & d)770 void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
771 this->write("do ");
772 this->writeStatement(*d.fStatement);
773 this->write(" while (");
774 this->writeExpression(*d.fTest, kTopLevel_Precedence);
775 this->write(");");
776 }
777
writeSwitchStatement(const SwitchStatement & s)778 void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
779 this->write("switch (");
780 this->writeExpression(*s.fValue, kTopLevel_Precedence);
781 this->writeLine(") {");
782 fIndentation++;
783 for (const auto& c : s.fCases) {
784 if (c->fValue) {
785 this->write("case ");
786 this->writeExpression(*c->fValue, kTopLevel_Precedence);
787 this->writeLine(":");
788 } else {
789 this->writeLine("default:");
790 }
791 fIndentation++;
792 for (const auto& stmt : c->fStatements) {
793 this->writeStatement(*stmt);
794 this->writeLine();
795 }
796 fIndentation--;
797 }
798 fIndentation--;
799 this->write("}");
800 }
801
writeReturnStatement(const ReturnStatement & r)802 void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
803 this->write("return");
804 if (r.fExpression) {
805 this->write(" ");
806 this->writeExpression(*r.fExpression, kTopLevel_Precedence);
807 }
808 this->write(";");
809 }
810
writeHeader()811 void GLSLCodeGenerator::writeHeader() {
812 this->write(fProgram.fSettings.fCaps->versionDeclString());
813 this->writeLine();
814 for (const auto& e : fProgram.fElements) {
815 if (e->fKind == ProgramElement::kExtension_Kind) {
816 this->writeExtension((Extension&) *e);
817 }
818 }
819 }
820
writePrecisionModifier()821 void GLSLCodeGenerator::writePrecisionModifier() {
822 if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
823 this->write("precision ");
824 switch (fProgram.fDefaultPrecision) {
825 case Modifiers::kLowp_Flag:
826 this->write("lowp");
827 break;
828 case Modifiers::kMediump_Flag:
829 this->write("mediump");
830 break;
831 case Modifiers::kHighp_Flag:
832 this->write("highp");
833 break;
834 default:
835 ASSERT(false);
836 this->write("<error>");
837 }
838 this->writeLine(" float;");
839 }
840 }
841
writeProgramElement(const ProgramElement & e)842 void GLSLCodeGenerator::writeProgramElement(const ProgramElement& e) {
843 switch (e.fKind) {
844 case ProgramElement::kExtension_Kind:
845 break;
846 case ProgramElement::kVar_Kind: {
847 VarDeclarations& decl = (VarDeclarations&) e;
848 if (decl.fVars.size() > 0) {
849 int builtin = ((VarDeclaration&) *decl.fVars[0]).fVar->fModifiers.fLayout.fBuiltin;
850 if (builtin == -1) {
851 // normal var
852 this->writeVarDeclarations(decl, true);
853 this->writeLine();
854 } else if (builtin == SK_FRAGCOLOR_BUILTIN &&
855 fProgram.fSettings.fCaps->mustDeclareFragmentShaderOutput()) {
856 this->write("out ");
857 if (fProgram.fSettings.fCaps->usesPrecisionModifiers()) {
858 this->write("mediump ");
859 }
860 this->writeLine("vec4 sk_FragColor;");
861 }
862 }
863 break;
864 }
865 case ProgramElement::kInterfaceBlock_Kind:
866 this->writeInterfaceBlock((InterfaceBlock&) e);
867 break;
868 case ProgramElement::kFunction_Kind:
869 this->writeFunction((FunctionDefinition&) e);
870 break;
871 case ProgramElement::kModifiers_Kind:
872 this->writeModifiers(((ModifiersDeclaration&) e).fModifiers, true);
873 this->writeLine(";");
874 break;
875 default:
876 printf("%s\n", e.description().c_str());
877 ABORT("unsupported program element");
878 }
879 }
880
generateCode()881 bool GLSLCodeGenerator::generateCode() {
882 OutputStream* rawOut = fOut;
883 fOut = &fHeader;
884 fProgramKind = fProgram.fKind;
885 this->writeHeader();
886 StringStream body;
887 fOut = &body;
888 this->writePrecisionModifier();
889 for (const auto& e : fProgram.fElements) {
890 this->writeProgramElement(*e);
891 }
892 fOut = rawOut;
893
894 write_stringstream(fHeader, *rawOut);
895 write_stringstream(body, *rawOut);
896 return true;
897 }
898
899 }
900