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