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