OLD | NEW |
---|---|
(Empty) | |
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 "ir/SkSLExpressionStatement.h" | |
15 #include "ir/SkSLExtension.h" | |
16 #include "ir/SkSLIndexExpression.h" | |
17 #include "ir/SkSLVariableReference.h" | |
18 | |
19 namespace SkSL { | |
20 | |
21 void 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 | |
34 void GLSLCodeGenerator::writeLine(const char* s) { | |
35 this->write(s); | |
36 *fOut << "\n"; | |
37 fAtLineStart = true; | |
38 } | |
39 | |
40 void GLSLCodeGenerator::write(const std::string& s) { | |
41 this->write(s.c_str()); | |
42 } | |
43 | |
44 void GLSLCodeGenerator::writeLine(const std::string& s) { | |
45 this->writeLine(s.c_str()); | |
46 } | |
47 | |
48 void GLSLCodeGenerator::writeLine() { | |
49 this->writeLine(""); | |
50 } | |
51 | |
52 void GLSLCodeGenerator::writeExtension(const Extension& ext) { | |
53 this->writeLine("#extension " + ext.fName + " : enable"); | |
54 } | |
55 | |
56 void GLSLCodeGenerator::writeType(const Type& type) { | |
57 if (type.kind() == Type::kStruct_Kind) { | |
58 this->writeLine("struct " + type.name() + " {"); | |
59 fIndentation++; | |
60 for (const auto& f : type.fields()) { | |
61 this->writeModifiers(f.fModifiers); | |
62 this->writeType(f.fType); | |
dogben
2016/08/02 18:08:15
Example from the GLSL spec:
struct S { float f; };
ethannicholas
2016/08/02 20:43:06
Good catch, fixed.
| |
63 this->writeLine(" " + f.fName + ";"); | |
64 } | |
65 fIndentation--; | |
66 this->writeLine("}"); | |
67 } else { | |
68 this->write(type.name()); | |
dogben
2016/08/02 18:08:15
Maybe add a comment that array sizes are part of t
ethannicholas
2016/08/02 20:43:06
Done.
| |
69 } | |
70 } | |
71 | |
72 void GLSLCodeGenerator::writeExpression(const Expression& expr, Precedence paren tPrecedence) { | |
73 switch (expr.fKind) { | |
74 case Expression::kBinary_Kind: | |
75 this->writeBinaryExpression((BinaryExpression&) expr, parentPreceden ce); | |
76 break; | |
77 case Expression::kBoolLiteral_Kind: | |
78 this->writeBoolLiteral((BoolLiteral&) expr); | |
79 break; | |
80 case Expression::kConstructor_Kind: | |
81 this->writeConstructor((Constructor&) expr); | |
82 break; | |
83 case Expression::kIntLiteral_Kind: | |
84 this->writeIntLiteral((IntLiteral&) expr); | |
85 break; | |
86 case Expression::kFieldAccess_Kind: | |
87 this->writeFieldAccess(((FieldAccess&) expr)); | |
88 break; | |
89 case Expression::kFloatLiteral_Kind: | |
90 this->writeFloatLiteral(((FloatLiteral&) expr)); | |
91 break; | |
92 case Expression::kFunctionCall_Kind: | |
93 this->writeFunctionCall((FunctionCall&) expr); | |
94 break; | |
95 case Expression::kPrefix_Kind: | |
96 this->writePrefixExpression((PrefixExpression&) expr, parentPreceden ce); | |
97 break; | |
98 case Expression::kPostfix_Kind: | |
99 this->writePostfixExpression((PostfixExpression&) expr, parentPreced ence); | |
100 break; | |
101 case Expression::kSwizzle_Kind: | |
102 this->writeSwizzle((Swizzle&) expr); | |
103 break; | |
104 case Expression::kVariableReference_Kind: | |
105 this->writeVariableReference((VariableReference&) expr); | |
106 break; | |
107 case Expression::kTernary_Kind: | |
108 this->writeTernaryExpression((TernaryExpression&) expr, parentPreced ence); | |
109 break; | |
110 case Expression::kIndex_Kind: | |
111 this->writeIndexExpression((IndexExpression&) expr); | |
112 break; | |
113 default: | |
114 ABORT("unsupported expression: %s", expr.description().c_str()); | |
115 } | |
116 } | |
117 | |
118 void GLSLCodeGenerator::writeFunctionCall(const FunctionCall& c) { | |
119 this->write(c.fFunction.fName + "("); | |
120 const char* separator = ""; | |
121 for (const auto& arg : c.fArguments) { | |
122 this->write(separator); | |
123 separator = ", "; | |
124 this->writeExpression(*arg, kSequence_Precedence); | |
125 } | |
126 this->write(")"); | |
127 } | |
128 | |
129 void GLSLCodeGenerator::writeConstructor(const Constructor& c) { | |
130 this->write(c.fType.name() + "("); | |
131 const char* separator = ""; | |
132 for (const auto& arg : c.fArguments) { | |
133 this->write(separator); | |
134 separator = ", "; | |
135 this->writeExpression(*arg, kSequence_Precedence); | |
136 } | |
137 this->write(")"); | |
138 } | |
139 | |
140 void GLSLCodeGenerator::writeVariableReference(const VariableReference& ref) { | |
141 this->write(ref.fVariable.fName); | |
142 } | |
143 | |
144 void GLSLCodeGenerator::writeIndexExpression(const IndexExpression& expr) { | |
145 this->writeExpression(*expr.fBase, kPostfix_Precedence); | |
146 this->write("["); | |
147 this->writeExpression(*expr.fIndex, kTopLevel_Precedence); | |
148 this->write("]"); | |
149 } | |
150 | |
151 void GLSLCodeGenerator::writeFieldAccess(const FieldAccess& f) { | |
152 if (f.fOwnerKind == FieldAccess::kDefault_OwnerKind) { | |
153 this->writeExpression(*f.fBase, kPostfix_Precedence); | |
154 this->write("."); | |
155 } | |
156 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); | |
157 } | |
158 | |
159 void GLSLCodeGenerator::writeSwizzle(const Swizzle& swizzle) { | |
160 this->writeExpression(*swizzle.fBase, kPostfix_Precedence); | |
161 this->write("."); | |
162 for (int c : swizzle.fComponents) { | |
163 this->write(&("x\0y\0z\0w\0"[c * 2])); | |
164 } | |
165 } | |
166 | |
167 static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) { | |
168 switch (op) { | |
169 case Token::STAR: // fall through | |
170 case Token::SLASH: // fall through | |
171 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Prec edence; | |
172 case Token::PLUS: // fall through | |
173 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence ; | |
174 case Token::SHL: // fall through | |
175 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; | |
176 case Token::LT: // fall through | |
177 case Token::GT: // fall through | |
178 case Token::LTEQ: // fall through | |
179 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Preceden ce; | |
180 case Token::EQEQ: // fall through | |
181 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence ; | |
182 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Preceden ce; | |
183 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Preceden ce; | |
184 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedenc e; | |
185 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Preceden ce; | |
186 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Preceden ce; | |
187 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedenc e; | |
188 case Token::EQ: // fall through | |
189 case Token::PLUSEQ: // fall through | |
190 case Token::MINUSEQ: // fall through | |
191 case Token::STAREQ: // fall through | |
192 case Token::SLASHEQ: // fall through | |
193 case Token::PERCENTEQ: // fall through | |
194 case Token::SHLEQ: // fall through | |
195 case Token::SHREQ: // fall through | |
196 case Token::LOGICALANDEQ: // fall through | |
197 case Token::LOGICALXOREQ: // fall through | |
198 case Token::LOGICALOREQ: // fall through | |
199 case Token::BITWISEANDEQ: // fall through | |
200 case Token::BITWISEXOREQ: // fall through | |
201 case Token::BITWISEOREQ: return GLSLCodeGenerator::kAssignment_Preceden ce; | |
202 default: ABORT("unsupported binary operator"); | |
203 } | |
204 } | |
205 | |
206 void GLSLCodeGenerator::writeBinaryExpression(const BinaryExpression& b, | |
207 Precedence parentPrecedence) { | |
208 Precedence precedence = get_binary_precedence(b.fOperator); | |
209 if (precedence >= parentPrecedence) { | |
210 this->write("("); | |
211 } | |
212 this->writeExpression(*b.fLeft, precedence); | |
213 this->write(" " + Token::OperatorName(b.fOperator) + " "); | |
214 this->writeExpression(*b.fRight, precedence); | |
215 if (precedence >= parentPrecedence) { | |
216 this->write(")"); | |
217 } | |
218 } | |
219 | |
220 void GLSLCodeGenerator::writeTernaryExpression(const TernaryExpression& t, | |
221 Precedence parentPrecedence) { | |
222 if (kTernary_Precedence >= parentPrecedence) { | |
223 this->write("("); | |
224 } | |
225 this->writeExpression(*t.fTest, kTernary_Precedence); | |
226 this->write(" ? "); | |
227 this->writeExpression(*t.fIfTrue, kTernary_Precedence); | |
228 this->write(" : "); | |
229 this->writeExpression(*t.fIfFalse, kTernary_Precedence); | |
230 if (kTernary_Precedence >= parentPrecedence) { | |
231 this->write(")"); | |
232 } | |
233 } | |
234 | |
235 void GLSLCodeGenerator::writePrefixExpression(const PrefixExpression& p, | |
236 Precedence parentPrecedence) { | |
237 if (kPrefix_Precedence >= parentPrecedence) { | |
238 this->write("("); | |
239 } | |
240 this->write(Token::OperatorName(p.fOperator)); | |
241 this->writeExpression(*p.fOperand, kPrefix_Precedence); | |
242 if (kPrefix_Precedence >= parentPrecedence) { | |
243 this->write(")"); | |
244 } | |
245 } | |
246 | |
247 void GLSLCodeGenerator::writePostfixExpression(const PostfixExpression& p, | |
248 Precedence parentPrecedence) { | |
249 if (kPostfix_Precedence >= parentPrecedence) { | |
250 this->write("("); | |
251 } | |
252 this->writeExpression(*p.fOperand, kPostfix_Precedence); | |
253 this->write(Token::OperatorName(p.fOperator)); | |
254 if (kPostfix_Precedence >= parentPrecedence) { | |
255 this->write(")"); | |
256 } | |
257 } | |
258 | |
259 void GLSLCodeGenerator::writeBoolLiteral(const BoolLiteral& b) { | |
260 this->write(b.fValue ? "true" : "false"); | |
261 } | |
262 | |
263 void GLSLCodeGenerator::writeIntLiteral(const IntLiteral& i) { | |
264 this->write(to_string(i.fValue)); | |
265 } | |
266 | |
267 void GLSLCodeGenerator::writeFloatLiteral(const FloatLiteral& f) { | |
268 this->write(to_string(f.fValue)); | |
269 } | |
270 | |
271 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { | |
272 this->writeType(f.fDeclaration.fReturnType); | |
273 this->write(" " + f.fDeclaration.fName + "("); | |
274 const char* separator = ""; | |
275 for (const auto& param : f.fDeclaration.fParameters) { | |
276 this->write(separator); | |
277 separator = ", "; | |
278 this->writeModifiers(param->fModifiers); | |
279 this->writeType(param->fType); | |
280 this->write(" " + param->fName); | |
281 } | |
282 this->write(") "); | |
283 this->writeBlock(*f.fBody); | |
284 this->writeLine(); | |
285 } | |
286 | |
287 void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) { | |
288 this->write(modifiers.description()); | |
289 } | |
290 | |
291 void GLSLCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf) { | |
292 if (intf.fVariable.fName == "gl_PerVertex") { | |
293 return; | |
294 } | |
295 this->writeModifiers(intf.fVariable.fModifiers); | |
296 this->writeLine(intf.fVariable.fType.name() + " {"); | |
297 fIndentation++; | |
298 for (const auto& f : intf.fVariable.fType.fields()) { | |
299 this->writeModifiers(f.fModifiers); | |
300 this->writeType(f.fType); | |
301 this->writeLine(" " + f.fName + ";"); | |
302 } | |
303 fIndentation--; | |
304 this->writeLine("};"); | |
305 } | |
306 | |
307 void GLSLCodeGenerator::writeVarDeclaration(const VarDeclaration& decl) { | |
308 ASSERT(decl.fVars.size() > 0); | |
309 this->writeModifiers(decl.fVars[0]->fModifiers); | |
310 this->writeType(decl.fBaseType); | |
311 std::string separator = " "; | |
312 for (size_t i = 0; i < decl.fVars.size(); i++) { | |
313 ASSERT(decl.fVars[i]->fModifiers == decl.fVars[0]->fModifiers); | |
314 this->write(separator); | |
315 separator = ", "; | |
316 this->write(decl.fVars[i]->fName); | |
317 for (const auto& size : decl.fSizes[i]) { | |
318 this->write("["); | |
319 this->writeExpression(*size, kTopLevel_Precedence); | |
320 this->write("]"); | |
321 } | |
322 if (decl.fValues[i]) { | |
323 this->write(" = "); | |
324 this->writeExpression(*decl.fValues[i], kTopLevel_Precedence); | |
325 } | |
326 } | |
327 this->write(";"); | |
328 } | |
329 | |
330 void GLSLCodeGenerator::writeStatement(const Statement& s) { | |
331 switch (s.fKind) { | |
332 case Statement::kBlock_Kind: | |
333 this->writeBlock((Block&) s); | |
334 break; | |
335 case Statement::kExpression_Kind: | |
336 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopL evel_Precedence); | |
337 this->write(";"); | |
338 break; | |
339 case Statement::kReturn_Kind: | |
340 this->writeReturnStatement((ReturnStatement&) s); | |
341 break; | |
342 case Statement::kVarDeclaration_Kind: | |
343 this->writeVarDeclaration(*((VarDeclarationStatement&) s).fDeclarati on); | |
344 break; | |
345 case Statement::kIf_Kind: | |
346 this->writeIfStatement((IfStatement&) s); | |
347 break; | |
348 case Statement::kFor_Kind: | |
349 this->writeForStatement((ForStatement&) s); | |
350 break; | |
351 case Statement::kWhile_Kind: | |
352 this->writeWhileStatement((WhileStatement&) s); | |
353 break; | |
354 case Statement::kDo_Kind: | |
355 this->writeDoStatement((DoStatement&) s); | |
356 break; | |
357 case Statement::kBreak_Kind: | |
358 this->write("break;"); | |
359 break; | |
360 case Statement::kContinue_Kind: | |
361 this->write("continue;"); | |
362 break; | |
363 case Statement::kDiscard_Kind: | |
364 this->write("discard;"); | |
365 break; | |
366 default: | |
367 ABORT("unsupported statement: %s", s.description().c_str()); | |
368 } | |
369 } | |
370 | |
371 void GLSLCodeGenerator::writeBlock(const Block& b) { | |
372 this->writeLine("{"); | |
373 fIndentation++; | |
374 for (const auto& s : b.fStatements) { | |
375 this->writeStatement(*s); | |
376 this->writeLine(); | |
377 } | |
378 fIndentation--; | |
379 this->write("}"); | |
380 } | |
381 | |
382 void GLSLCodeGenerator::writeIfStatement(const IfStatement& stmt) { | |
383 this->write("if ("); | |
384 this->writeExpression(*stmt.fTest, kTopLevel_Precedence); | |
385 this->write(") "); | |
386 this->writeStatement(*stmt.fIfTrue); | |
387 if (stmt.fIfFalse) { | |
388 this->write(" else "); | |
389 this->writeStatement(*stmt.fIfFalse); | |
390 } | |
391 } | |
392 | |
393 void GLSLCodeGenerator::writeForStatement(const ForStatement& f) { | |
394 this->write("for ("); | |
395 if (f.fInitializer) { | |
396 this->writeStatement(*f.fInitializer); | |
397 } else { | |
398 this->write("; "); | |
399 } | |
400 if (f.fTest) { | |
401 this->writeExpression(*f.fTest, kTopLevel_Precedence); | |
402 } | |
403 this->write("; "); | |
404 if (f.fNext) { | |
405 this->writeExpression(*f.fNext, kTopLevel_Precedence); | |
406 } | |
407 this->write(") "); | |
408 this->writeStatement(*f.fStatement); | |
409 } | |
410 | |
411 void GLSLCodeGenerator::writeWhileStatement(const WhileStatement& w) { | |
412 this->write("while ("); | |
413 this->writeExpression(*w.fTest, kTopLevel_Precedence); | |
414 this->write(") "); | |
415 this->writeStatement(*w.fStatement); | |
416 } | |
417 | |
418 void GLSLCodeGenerator::writeDoStatement(const DoStatement& d) { | |
419 this->write("do "); | |
420 this->writeStatement(*d.fStatement); | |
421 this->write(" while ("); | |
422 this->writeExpression(*d.fTest, kTopLevel_Precedence); | |
423 this->write(");"); | |
424 } | |
425 | |
426 void GLSLCodeGenerator::writeReturnStatement(const ReturnStatement& r) { | |
427 this->write("return"); | |
428 if (r.fExpression) { | |
429 this->write(" "); | |
430 this->writeExpression(*r.fExpression, kTopLevel_Precedence); | |
431 } | |
432 this->write(";"); | |
433 } | |
434 | |
435 void GLSLCodeGenerator::generateCode(const Program& program, std::ostream& out) { | |
436 ASSERT(fOut == nullptr); | |
437 fOut = &out; | |
438 this->write("#version " + to_string(fCaps.fVersion)); | |
439 if (fCaps.fStandard == GLCaps::kGLES_Standard) { | |
440 this->write(" es"); | |
441 } | |
442 this->writeLine(); | |
443 for (const auto& e : program.fElements) { | |
444 switch (e->fKind) { | |
445 case ProgramElement::kExtension_Kind: | |
446 this->writeExtension((Extension&) *e); | |
447 break; | |
448 case ProgramElement::kVar_Kind: { | |
449 VarDeclaration& decl = (VarDeclaration&) *e; | |
450 if (decl.fVars.size() > 0 && decl.fVars[0]->fModifiers.fLayout.f Builtin == -1) { | |
451 this->writeVarDeclaration(decl); | |
452 this->writeLine(); | |
453 } | |
454 break; | |
455 } | |
456 case ProgramElement::kInterfaceBlock_Kind: | |
457 this->writeInterfaceBlock((InterfaceBlock&) *e); | |
458 break; | |
459 case ProgramElement::kFunction_Kind: | |
460 this->writeFunction((FunctionDefinition&) *e); | |
461 break; | |
462 default: | |
463 printf("%s\n", e->description().c_str()); | |
464 ABORT("unsupported program element"); | |
465 } | |
466 } | |
467 fOut = nullptr; | |
468 } | |
469 | |
470 } | |
OLD | NEW |