blob: da0bcb903cf3508826e8a311f6f98338ba06f0a1 [file] [log] [blame]
ethannicholasf789b382016-08-03 12:43:36 -07001/*
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 "ir/SkSLExpressionStatement.h"
15#include "ir/SkSLExtension.h"
16#include "ir/SkSLIndexExpression.h"
17#include "ir/SkSLVariableReference.h"
18
19namespace SkSL {
20
21void GLSLCodeGenerator::write(const char* s) {
22 if (s[0] == 0) {
23 return;
24 }
25 if (fAtLineStart) {
26 for (int i = 0; i < fIndentation; i++) {
27 *fOut << " ";
28 }
29 }
30 *fOut << s;
31 fAtLineStart = false;
32}
33
34void GLSLCodeGenerator::writeLine(const char* s) {
35 this->write(s);
36 *fOut << "\n";
37 fAtLineStart = true;
38}
39
40void GLSLCodeGenerator::write(const std::string& s) {
41 this->write(s.c_str());
42}
43
44void GLSLCodeGenerator::writeLine(const std::string& s) {
45 this->writeLine(s.c_str());
46}
47
48void GLSLCodeGenerator::writeLine() {
49 this->writeLine("");
50}
51
52void GLSLCodeGenerator::writeExtension(const Extension& ext) {
53 this->writeLine("#extension " + ext.fName + " : enable");
54}
55
56void GLSLCodeGenerator::writeType(const Type& type) {
57 if (type.kind() == Type::kStruct_Kind) {
58 for (const Type* search : fWrittenStructs) {
59 if (*search == type) {
60 // already written
61 this->write(type.name());
62 return;
63 }
64 }
65 fWrittenStructs.push_back(&type);
66 this->writeLine("struct " + type.name() + " {");
67 fIndentation++;
68 for (const auto& f : type.fields()) {
jvanverth9df16b52016-10-11 10:03:56 -070069 this->writeModifiers(f.fModifiers);
ethannicholasf789b382016-08-03 12:43:36 -070070 // sizes (which must be static in structs) are part of the type name here
ethannicholas0730be72016-09-01 07:59:02 -070071 this->writeType(*f.fType);
ethannicholasf789b382016-08-03 12:43:36 -070072 this->writeLine(" " + f.fName + ";");
73 }
74 fIndentation--;
75 this->writeLine("}");
76 } else {
77 this->write(type.name());
78 }
79}
80
81void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence parentPrecedence) {
82 switch (expr.fKind) {
83 case Expression::kBinary_Kind:
84 this->writeBinaryExpression((BinaryExpression&) expr, parentPrecedence);
85 break;
86 case Expression::kBoolLiteral_Kind:
87 this->writeBoolLiteral((BoolLiteral&) expr);
88 break;
89 case Expression::kConstructor_Kind:
90 this->writeConstructor((Constructor&) expr);
91 break;
92 case Expression::kIntLiteral_Kind:
93 this->writeIntLiteral((IntLiteral&) expr);
94 break;
95 case Expression::kFieldAccess_Kind:
96 this->writeFieldAccess(((FieldAccess&) expr));
97 break;
98 case Expression::kFloatLiteral_Kind:
99 this->writeFloatLiteral(((FloatLiteral&) expr));
100 break;
101 case Expression::kFunctionCall_Kind:
102 this->writeFunctionCall((FunctionCall&) expr);
103 break;
104 case Expression::kPrefix_Kind:
105 this->writePrefixExpression((PrefixExpression&) expr, parentPrecedence);
106 break;
107 case Expression::kPostfix_Kind:
108 this->writePostfixExpression((PostfixExpression&) expr, parentPrecedence);
109 break;
110 case Expression::kSwizzle_Kind:
111 this->writeSwizzle((Swizzle&) expr);
112 break;
113 case Expression::kVariableReference_Kind:
114 this->writeVariableReference((VariableReference&) expr);
115 break;
116 case Expression::kTernary_Kind:
117 this->writeTernaryExpression((TernaryExpression&) expr, parentPrecedence);
118 break;
119 case Expression::kIndex_Kind:
120 this->writeIndexExpression((IndexExpression&) expr);
121 break;
122 default:
123 ABORT("unsupported expression: %s", expr.description().c_str());
124 }
125}
126
127void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) {
128 this->write(c.fFunction.fName + "(");
129 const char* separator = "";
130 for (const auto& arg : c.fArguments) {
131 this->write(separator);
132 separator = ", ";
133 this->writeExpression(*arg, kSequence_Precedence);
134 }
135 this->write(")");
136}
137
138void GLSLCodeGenerator::writeConstructor(const Constructor& c) {
139 this->write(c.fType.name() + "(");
140 const char* separator = "";
141 for (const auto& arg : c.fArguments) {
142 this->write(separator);
143 separator = ", ";
144 this->writeExpression(*arg, kSequence_Precedence);
145 }
146 this->write(")");
147}
148
149void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) {
jvanverth9df16b52016-10-11 10:03:56 -0700150 this->write(ref.fVariable.fName);
ethannicholasf789b382016-08-03 12:43:36 -0700151}
152
153void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) {
154 this->writeExpression(*expr.fBase, kPostfix_Precedence);
155 this->write("[");
156 this->writeExpression(*expr.fIndex, kTopLevel_Precedence);
157 this->write("]");
158}
159
160void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) {
161 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) {
162 this->writeExpression(*f.fBase, kPostfix_Precedence);
163 this->write(".");
164 }
165 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName);
166}
167
168void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) {
169 this->writeExpression(*swizzle.fBase, kPostfix_Precedence);
170 this->write(".");
171 for (int c : swizzle.fComponents) {
172 this->write(&("x\0y\0z\0w\0"[c * 2]));
173 }
174}
175
176static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) {
177 switch (op) {
178 case Token::STAR: // fall through
179 case Token::SLASH: // fall through
180 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Precedence;
181 case Token::PLUS: // fall through
182 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence;
183 case Token::SHL: // fall through
184 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence;
185 case Token::LT: // fall through
186 case Token::GT: // fall through
187 case Token::LTEQ: // fall through
188 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Precedence;
189 case Token::EQEQ: // fall through
190 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence;
191 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Precedence;
192 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Precedence;
193 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedence;
194 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Precedence;
195 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Precedence;
196 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedence;
197 case Token::EQ: // fall through
198 case Token::PLUSEQ: // fall through
199 case Token::MINUSEQ: // fall through
200 case Token::STAREQ: // fall through
201 case Token::SLASHEQ: // fall through
202 case Token::PERCENTEQ: // fall through
203 case Token::SHLEQ: // fall through
204 case Token::SHREQ: // fall through
205 case Token::LOGICALANDEQ: // fall through
206 case Token::LOGICALXOREQ: // fall through
207 case Token::LOGICALOREQ: // fall through
208 case Token::BITWISEANDEQ: // fall through
209 case Token::BITWISEXOREQ: // fall through
210 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Precedence;
211 default: ABORT("unsupported binary operator");
212 }
213}
214
215void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
216 Precedence parentPrecedence) {
217 Precedence precedence = get_binary_precedence(b.fOperator);
218 if (precedence >= parentPrecedence) {
219 this->write("(");
220 }
221 this->writeExpression(*b.fLeft, precedence);
222 this->write(" " + Token::OperatorName(b.fOperator) + " ");
223 this->writeExpression(*b.fRight, precedence);
224 if (precedence >= parentPrecedence) {
225 this->write(")");
226 }
227}
228
229void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t,
230 Precedence parentPrecedence) {
231 if (kTernary_Precedence >= parentPrecedence) {
232 this->write("(");
233 }
234 this->writeExpression(*t.fTest, kTernary_Precedence);
235 this->write(" ? ");
236 this->writeExpression(*t.fIfTrue, kTernary_Precedence);
237 this->write(" : ");
238 this->writeExpression(*t.fIfFalse, kTernary_Precedence);
239 if (kTernary_Precedence >= parentPrecedence) {
240 this->write(")");
241 }
242}
243
244void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p,
245 Precedence parentPrecedence) {
246 if (kPrefix_Precedence >= parentPrecedence) {
247 this->write("(");
248 }
249 this->write(Token::OperatorName(p.fOperator));
250 this->writeExpression(*p.fOperand, kPrefix_Precedence);
251 if (kPrefix_Precedence >= parentPrecedence) {
252 this->write(")");
253 }
254}
255
256void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p,
257 Precedence parentPrecedence) {
258 if (kPostfix_Precedence >= parentPrecedence) {
259 this->write("(");
260 }
261 this->writeExpression(*p.fOperand, kPostfix_Precedence);
262 this->write(Token::OperatorName(p.fOperator));
263 if (kPostfix_Precedence >= parentPrecedence) {
264 this->write(")");
265 }
266}
267
268void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) {
269 this->write(b.fValue ? "true" : "false");
270}
271
272void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) {
jvanverth9df16b52016-10-11 10:03:56 -0700273 this->write(to_string(i.fValue));
ethannicholasf789b382016-08-03 12:43:36 -0700274}
275
276void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) {
277 this->write(to_string(f.fValue));
278}
279
280void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
281 this->writeType(f.fDeclaration.fReturnType);
282 this->write(" " + f.fDeclaration.fName + "(");
283 const char* separator = "";
284 for (const auto& param : f.fDeclaration.fParameters) {
285 this->write(separator);
286 separator = ", ";
jvanverth9df16b52016-10-11 10:03:56 -0700287 this->writeModifiers(param->fModifiers);
288 this->writeType(param->fType);
ethannicholasf789b382016-08-03 12:43:36 -0700289 this->write(" " + param->fName);
290 }
jvanverth9df16b52016-10-11 10:03:56 -0700291 this->write(") ");
292 this->writeBlock(*f.fBody);
293 this->writeLine();
ethannicholasf789b382016-08-03 12:43:36 -0700294}
295
jvanverth9df16b52016-10-11 10:03:56 -0700296void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) {
297 this->write(modifiers.description());
ethannicholasf789b382016-08-03 12:43:36 -0700298}
299
300void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) {
301 if (intf.fVariable.fName == "gl_PerVertex") {
302 return;
303 }
jvanverth9df16b52016-10-11 10:03:56 -0700304 this->writeModifiers(intf.fVariable.fModifiers);
ethannicholasf789b382016-08-03 12:43:36 -0700305 this->writeLine(intf.fVariable.fType.name() + " {");
306 fIndentation++;
307 for (const auto& f : intf.fVariable.fType.fields()) {
jvanverth9df16b52016-10-11 10:03:56 -0700308 this->writeModifiers(f.fModifiers);
ethannicholas0730be72016-09-01 07:59:02 -0700309 this->writeType(*f.fType);
ethannicholasf789b382016-08-03 12:43:36 -0700310 this->writeLine(" " + f.fName + ";");
311 }
312 fIndentation--;
313 this->writeLine("};");
314}
315
jvanverth9df16b52016-10-11 10:03:56 -0700316void GLSLCodeGenerator::writeVarDeclarations(const VarDeclarations& decl) {
ethannicholasf789b382016-08-03 12:43:36 -0700317 ASSERT(decl.fVars.size() > 0);
jvanverth9df16b52016-10-11 10:03:56 -0700318 this->writeModifiers(decl.fVars[0].fVar->fModifiers);
ethannicholasf789b382016-08-03 12:43:36 -0700319 this->writeType(decl.fBaseType);
320 std::string separator = " ";
ethannicholas14fe8cc2016-09-07 13:37:16 -0700321 for (const auto& var : decl.fVars) {
322 ASSERT(var.fVar->fModifiers == decl.fVars[0].fVar->fModifiers);
ethannicholasf789b382016-08-03 12:43:36 -0700323 this->write(separator);
324 separator = ", ";
ethannicholas14fe8cc2016-09-07 13:37:16 -0700325 this->write(var.fVar->fName);
326 for (const auto& size : var.fSizes) {
ethannicholasf789b382016-08-03 12:43:36 -0700327 this->write("[");
jvanverth9df16b52016-10-11 10:03:56 -0700328 this->writeExpression(*size, kTopLevel_Precedence);
ethannicholasf789b382016-08-03 12:43:36 -0700329 this->write("]");
330 }
ethannicholas14fe8cc2016-09-07 13:37:16 -0700331 if (var.fValue) {
ethannicholasf789b382016-08-03 12:43:36 -0700332 this->write(" = ");
ethannicholas14fe8cc2016-09-07 13:37:16 -0700333 this->writeExpression(*var.fValue, kTopLevel_Precedence);
ethannicholasf789b382016-08-03 12:43:36 -0700334 }
335 }
336 this->write(";");
337}
338
339void GLSLCodeGenerator::writeStatement(const Statement& s) {
340 switch (s.fKind) {
341 case Statement::kBlock_Kind:
342 this->writeBlock((Block&) s);
343 break;
344 case Statement::kExpression_Kind:
345 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopLevel_Precedence);
346 this->write(";");
347 break;
348 case Statement::kReturn_Kind:
349 this->writeReturnStatement((ReturnStatement&) s);
350 break;
ethannicholas14fe8cc2016-09-07 13:37:16 -0700351 case Statement::kVarDeclarations_Kind:
jvanverth9df16b52016-10-11 10:03:56 -0700352 this->writeVarDeclarations(*((VarDeclarationsStatement&) s).fDeclaration);
ethannicholasf789b382016-08-03 12:43:36 -0700353 break;
354 case Statement::kIf_Kind:
355 this->writeIfStatement((IfStatement&) s);
356 break;
357 case Statement::kFor_Kind:
358 this->writeForStatement((ForStatement&) s);
359 break;
360 case Statement::kWhile_Kind:
361 this->writeWhileStatement((WhileStatement&) s);
362 break;
363 case Statement::kDo_Kind:
364 this->writeDoStatement((DoStatement&) s);
365 break;
366 case Statement::kBreak_Kind:
367 this->write("break;");
368 break;
369 case Statement::kContinue_Kind:
370 this->write("continue;");
371 break;
372 case Statement::kDiscard_Kind:
373 this->write("discard;");
374 break;
375 default:
376 ABORT("unsupported statement: %s", s.description().c_str());
377 }
378}
379
380void GLSLCodeGenerator::writeBlock(const Block& b) {
381 this->writeLine("{");
382 fIndentation++;
383 for (const auto& s : b.fStatements) {
384 this->writeStatement(*s);
385 this->writeLine();
386 }
387 fIndentation--;
388 this->write("}");
389}
390
391void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) {
392 this->write("if (");
393 this->writeExpression(*stmt.fTest, kTopLevel_Precedence);
394 this->write(") ");
395 this->writeStatement(*stmt.fIfTrue);
396 if (stmt.fIfFalse) {
397 this->write(" else ");
398 this->writeStatement(*stmt.fIfFalse);
399 }
400}
401
402void GLSLCodeGenerator::writeForStatement(const ForStatement& f) {
403 this->write("for (");
404 if (f.fInitializer) {
405 this->writeStatement(*f.fInitializer);
406 } else {
407 this->write("; ");
408 }
409 if (f.fTest) {
410 this->writeExpression(*f.fTest, kTopLevel_Precedence);
411 }
412 this->write("; ");
413 if (f.fNext) {
414 this->writeExpression(*f.fNext, kTopLevel_Precedence);
415 }
416 this->write(") ");
417 this->writeStatement(*f.fStatement);
418}
419
420void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) {
421 this->write("while (");
422 this->writeExpression(*w.fTest, kTopLevel_Precedence);
423 this->write(") ");
424 this->writeStatement(*w.fStatement);
425}
426
427void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) {
428 this->write("do ");
429 this->writeStatement(*d.fStatement);
430 this->write(" while (");
431 this->writeExpression(*d.fTest, kTopLevel_Precedence);
432 this->write(");");
433}
434
435void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) {
436 this->write("return");
437 if (r.fExpression) {
438 this->write(" ");
439 this->writeExpression(*r.fExpression, kTopLevel_Precedence);
440 }
441 this->write(";");
442}
443
444void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) {
445 ASSERT(fOut == nullptr);
446 fOut = &out;
447 this->write("#version " + to_string(fCaps.fVersion));
jvanverth9df16b52016-10-11 10:03:56 -0700448 if (fCaps.fStandard == GLCaps::kGLES_Standard) {
ethannicholasf789b382016-08-03 12:43:36 -0700449 this->write(" es");
450 }
451 this->writeLine();
452 for (const auto& e : program.fElements) {
453 switch (e->fKind) {
454 case ProgramElement::kExtension_Kind:
jvanverth9df16b52016-10-11 10:03:56 -0700455 this->writeExtension((Extension&) *e);
ethannicholasf789b382016-08-03 12:43:36 -0700456 break;
457 case ProgramElement::kVar_Kind: {
ethannicholas14fe8cc2016-09-07 13:37:16 -0700458 VarDeclarations& decl = (VarDeclarations&) *e;
jvanverth9df16b52016-10-11 10:03:56 -0700459 if (decl.fVars.size() > 0 &&
460 decl.fVars[0].fVar->fModifiers.fLayout.fBuiltin == -1) {
461 this->writeVarDeclarations(decl);
462 this->writeLine();
ethannicholasf789b382016-08-03 12:43:36 -0700463 }
464 break;
465 }
466 case ProgramElement::kInterfaceBlock_Kind:
467 this->writeInterfaceBlock((InterfaceBlock&) *e);
468 break;
469 case ProgramElement::kFunction_Kind:
470 this->writeFunction((FunctionDefinition&) *e);
471 break;
ethannicholasf789b382016-08-03 12:43:36 -0700472 default:
473 printf("%s\n", e->description().c_str());
474 ABORT("unsupported program element");
475 }
476 }
477 fOut = nullptr;
478}
479
480}