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 (fAtLineStart) { | |
dogben
2016/07/31 23:20:20
nit: maybe "if (s[0] == '\0') return;"? Maybe I'm
ethannicholas
2016/08/02 16:13:17
Done.
| |
23 for (int i = 0; i < fIndentation; i++) { | |
24 *fOut << " "; | |
25 } | |
26 } | |
27 *fOut << s; | |
28 fAtLineStart = false; | |
29 } | |
30 | |
31 void GLSLCodeGenerator::writeLine(const char* s) { | |
32 this->write(s); | |
33 *fOut << "\n"; | |
34 fAtLineStart = true; | |
35 } | |
36 | |
37 void GLSLCodeGenerator::write(std::string s) { | |
38 this->write(s.c_str()); | |
39 } | |
40 | |
41 void GLSLCodeGenerator::writeLine(std::string s) { | |
42 this->writeLine(s.c_str()); | |
43 } | |
44 | |
45 void GLSLCodeGenerator::write(std::string& s) { | |
46 this->write(s.c_str()); | |
47 } | |
48 | |
49 void GLSLCodeGenerator::writeLine(std::string& s) { | |
50 this->writeLine(s.c_str()); | |
51 } | |
52 | |
53 void GLSLCodeGenerator::writeLine() { | |
54 this->writeLine(""); | |
55 } | |
56 | |
57 void GLSLCodeGenerator::writeExtension(Extension& ext) { | |
58 this->writeLine("#extension " + ext.fName + " : enable"); | |
59 } | |
60 | |
61 void GLSLCodeGenerator::writeStruct(const Type& type) { | |
62 this->writeLine("struct " + type.name() + " {"); | |
63 fIndentation++; | |
64 for (const auto& f : type.fields()) { | |
65 this->writeLine(f.fType.name() + " " + f.fName + ";"); | |
dogben
2016/07/31 23:20:20
Missing modifiers?
ethannicholas
2016/08/02 16:13:17
Fixed.
| |
66 } | |
67 fIndentation--; | |
68 this->writeLine("};"); | |
69 } | |
70 | |
71 void GLSLCodeGenerator::writeExpression(Expression& expr, Precedence parentPrece dence) { | |
72 switch (expr.fKind) { | |
73 case Expression::kBinary_Kind: | |
dogben
2016/07/31 23:20:20
nit: Indentation is inconsistent.
ethannicholas
2016/08/02 16:13:17
Damn you, tabs!
| |
74 this->writeBinaryExpression((BinaryExpression&) expr, parentPreceden ce); | |
75 break; | |
76 case Expression::kBoolLiteral_Kind: | |
77 this->writeBoolLiteral((BoolLiteral&) expr); | |
78 break; | |
79 case Expression::kConstructor_Kind: | |
80 this->writeConstructor((Constructor&) expr); | |
81 break; | |
82 case Expression::kIntLiteral_Kind: | |
83 this->writeIntLiteral((IntLiteral&) expr); | |
84 break; | |
85 case Expression::kFieldAccess_Kind: | |
86 this->writeFieldAccess(((FieldAccess&) expr)); | |
87 break; | |
88 case Expression::kFloatLiteral_Kind: | |
89 this->writeFloatLiteral(((FloatLiteral&) expr)); | |
90 break; | |
91 case Expression::kFunctionCall_Kind: | |
92 this->writeFunctionCall((FunctionCall&) expr); | |
93 break; | |
94 case Expression::kPrefix_Kind: | |
95 this->writePrefixExpression((PrefixExpression&) expr); | |
dogben
2016/07/31 23:20:20
Don't we need to pass in parentPrecedence? Maybe i
ethannicholas
2016/08/02 16:13:17
We sure do!
| |
96 break; | |
97 case Expression::kPostfix_Kind: | |
98 this->writePostfixExpression((PostfixExpression&) expr); | |
99 break; | |
100 case Expression::kSwizzle_Kind: | |
101 this->writeSwizzle((Swizzle&) expr); | |
102 break; | |
103 case Expression::kVariableReference_Kind: | |
104 this->writeVariableReference((VariableReference&) expr); | |
105 break; | |
106 case Expression::kTernary_Kind: | |
107 this->writeTernaryExpression((TernaryExpression&) expr, parentPreced ence); | |
108 break; | |
109 case Expression::kIndex_Kind: | |
110 this->writeIndexExpression((IndexExpression&) expr); | |
111 break; | |
112 default: | |
113 ABORT("unsupported expression: %s", expr.description().c_str()); | |
114 } | |
115 } | |
116 | |
117 void GLSLCodeGenerator::writeFunctionCall(FunctionCall& c) { | |
118 this->write(c.fFunction.fName + "("); | |
119 const char* separator = ""; | |
120 for (const auto& arg : c.fArguments) { | |
121 this->write(separator); | |
122 separator = ", "; | |
123 this->writeExpression(*arg, kTopLevel_Precedence); | |
dogben
2016/07/31 23:20:20
nit: kSequence_Precedence, although it shouldn't m
| |
124 } | |
125 this->write(")"); | |
126 } | |
127 | |
128 void GLSLCodeGenerator::writeConstructor(Constructor& c) { | |
129 this->write(c.fType.name() + "("); | |
130 const char* separator = ""; | |
131 for (const auto& arg : c.fArguments) { | |
132 this->write(separator); | |
133 separator = ", "; | |
134 this->writeExpression(*arg, kTopLevel_Precedence); | |
135 } | |
136 this->write(")"); | |
137 } | |
138 | |
139 void GLSLCodeGenerator::writeVariableReference(VariableReference& ref) { | |
140 this->write(ref.fVariable.fName); | |
141 } | |
142 | |
143 void GLSLCodeGenerator::writeIndexExpression(IndexExpression& expr) { | |
144 this->writeExpression(*expr.fBase, kPostfix_Precedence); | |
145 this->write("["); | |
146 this->writeExpression(*expr.fIndex, kTopLevel_Precedence); | |
147 this->write("]"); | |
148 } | |
149 | |
150 void GLSLCodeGenerator::writeFieldAccess(FieldAccess& f) { | |
151 if (!f.fInAnonymousInterfaceBlock) { | |
152 this->writeExpression(*f.fBase, kPostfix_Precedence); | |
153 this->write("."); | |
154 } | |
155 this->write(f.fBase->fType.fields()[f.fFieldIndex].fName); | |
156 } | |
157 | |
158 void GLSLCodeGenerator::writeSwizzle(Swizzle& swizzle) { | |
159 this->writeExpression(*swizzle.fBase, kPostfix_Precedence); | |
160 this->write("."); | |
161 for (int c : swizzle.fComponents) { | |
162 this->write(&("x\0y\0z\0w\0"[c * 2])); | |
egdaniel
2016/08/01 13:18:27
not that functionally it really matters, but is th
ethannicholas
2016/08/02 16:13:17
Correct. Since it doesn't matter whether you use r
| |
163 } | |
164 } | |
165 | |
166 static GLSLCodeGenerator::Precedence get_binary_precedence(Token::Kind op) { | |
167 switch (op) { | |
168 case Token::STAR: // fall through | |
169 case Token::SLASH: // fall through | |
170 case Token::PERCENT: return GLSLCodeGenerator::kMultiplicative_Prec edence; | |
171 case Token::PLUS: // fall through | |
172 case Token::MINUS: return GLSLCodeGenerator::kAdditive_Precedence ; | |
173 case Token::SHL: // fall through | |
174 case Token::SHR: return GLSLCodeGenerator::kShift_Precedence; | |
175 case Token::LT: // fall through | |
176 case Token::GT: // fall through | |
177 case Token::LTEQ: // fall through | |
178 case Token::GTEQ: return GLSLCodeGenerator::kRelational_Preceden ce; | |
179 case Token::EQEQ: // fall through | |
180 case Token::NEQ: return GLSLCodeGenerator::kEquality_Precedence ; | |
181 case Token::BITWISEAND: return GLSLCodeGenerator::kBitwiseAnd_Preceden ce; | |
182 case Token::BITWISEXOR: return GLSLCodeGenerator::kBitwiseXor_Preceden ce; | |
183 case Token::BITWISEOR: return GLSLCodeGenerator::kBitwiseOr_Precedenc e; | |
184 case Token::LOGICALAND: return GLSLCodeGenerator::kLogicalAnd_Preceden ce; | |
185 case Token::LOGICALXOR: return GLSLCodeGenerator::kLogicalXor_Preceden ce; | |
186 case Token::LOGICALOR: return GLSLCodeGenerator::kLogicalOr_Precedenc e; | |
187 case Token::EQ: // fall through | |
188 case Token::PLUSEQ: // fall through | |
189 case Token::MINUSEQ: // fall through | |
190 case Token::STAREQ: // fall through | |
191 case Token::SLASHEQ: // fall through | |
192 case Token::PERCENTEQ: // fall through | |
193 case Token::SHLEQ: // fall through | |
194 case Token::SHREQ: // fall through | |
195 case Token::LOGICALANDEQ: // fall through | |
196 case Token::LOGICALXOREQ: // fall through | |
197 case Token::LOGICALOREQ: return GLSLCodeGenerator::kAssignment_Preceden ce; | |
198 default: ABORT("unsupported binary operator"); | |
199 } | |
200 } | |
201 | |
202 void GLSLCodeGenerator::writeBinaryExpression(BinaryExpression& b, Precedence pa rentPrecedence) { | |
203 Precedence precedence = get_binary_precedence(b.fOperator); | |
204 if (precedence >= parentPrecedence) { | |
205 this->write("("); | |
206 } | |
207 this->writeExpression(*b.fLeft, precedence); | |
208 this->write(" " + Token::OperatorName(b.fOperator) + " "); | |
209 this->writeExpression(*b.fRight, precedence); | |
210 if (precedence >= parentPrecedence) { | |
211 this->write(")"); | |
212 } | |
213 } | |
214 | |
215 void GLSLCodeGenerator::writeTernaryExpression(TernaryExpression& t, Precedence parentPrecedence) { | |
216 if (kTernary_Precedence >= parentPrecedence) { | |
217 this->write("("); | |
218 } | |
219 this->writeExpression(*t.fTest, kTernary_Precedence); | |
220 this->write(" ? "); | |
221 this->writeExpression(*t.fIfTrue, kTernary_Precedence); | |
222 this->write(" : "); | |
223 this->writeExpression(*t.fIfFalse, kTernary_Precedence); | |
224 if (kTernary_Precedence >= parentPrecedence) { | |
225 this->write(")"); | |
226 } | |
227 } | |
228 | |
229 void GLSLCodeGenerator::writePrefixExpression(PrefixExpression& p) { | |
230 this->write(Token::OperatorName(p.fOperator)); | |
231 this->writeExpression(*p.fOperand, kPrefix_Precedence); | |
232 } | |
233 | |
234 void GLSLCodeGenerator::writePostfixExpression(PostfixExpression& p) { | |
235 this->writeExpression(*p.fOperand, kPostfix_Precedence); | |
236 this->write(Token::OperatorName(p.fOperator)); | |
237 } | |
238 | |
239 void GLSLCodeGenerator::writeBoolLiteral(BoolLiteral& b) { | |
240 this->write(b.fValue ? "true" : "false"); | |
241 } | |
242 | |
243 void GLSLCodeGenerator::writeIntLiteral(IntLiteral& i) { | |
244 this->write(to_string(i.fValue)); | |
245 } | |
246 | |
247 void GLSLCodeGenerator::writeFloatLiteral(FloatLiteral& f) { | |
248 this->write(to_string(f.fValue)); | |
dogben
2016/07/31 23:20:19
Docs for std::to_string say std::to_string(1e-9) =
ethannicholas
2016/08/02 16:13:17
My implementation of to_string (note that this is
| |
249 } | |
250 | |
251 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) { | |
252 this->write(f.fDeclaration.fReturnType.name() + " " + f.fDeclaration.fName + "("); | |
253 const char* separator = ""; | |
254 for (const auto& param : f.fDeclaration.fParameters) { | |
255 this->write(separator); | |
256 separator = ", "; | |
257 this->write(param->fType.name() + " " + param->fName); | |
dogben
2016/07/31 23:20:19
Missing modifiers and sizes.
ethannicholas
2016/08/02 16:13:17
Fixed.
| |
258 } | |
259 this->write(") "); | |
260 this->writeBlock(*f.fBody); | |
261 } | |
262 | |
263 void GLSLCodeGenerator::writeModifiers(const Modifiers& modifiers) { | |
264 this->write(modifiers.description()); | |
265 } | |
266 | |
267 void GLSLCodeGenerator::writeInterfaceBlock(InterfaceBlock& intf) { | |
268 if (intf.fVariable.fName == "gl_PerVertex") { | |
269 return; | |
270 } | |
271 this->writeModifiers(intf.fVariable.fModifiers); | |
272 this->writeStruct(intf.fVariable.fType); | |
dogben
2016/07/31 23:20:20
We're generating a struct for an interface? I don'
ethannicholas
2016/08/02 16:13:17
Stupid extra "struct" keyword. Fixed.
| |
273 } | |
274 | |
275 void GLSLCodeGenerator::writeVarDeclaration(VarDeclaration& decl) { | |
276 for (size_t i = 0; i < decl.fVars.size(); i++) { | |
277 if (decl.fVars[i]->fModifiers.fLayout.fBuiltin >= 0) { | |
dogben
2016/07/31 23:20:20
I don't know what this is about. builtin isn't doc
ethannicholas
2016/08/02 16:13:17
It's from the SPIR-V spec. I've added a comment to
| |
278 continue; | |
279 } | |
280 this->writeModifiers(decl.fVars[i]->fModifiers); | |
281 this->write(decl.fVars[i]->fType.name() + " " + decl.fVars[i]->fName); | |
dogben
2016/07/31 23:20:20
If this is a top-level var declaration, fType migh
ethannicholas
2016/08/02 16:13:17
Done.
| |
282 if (decl.fValues[i]) { | |
283 this->write(" = "); | |
284 this->writeExpression(*decl.fValues[i], kTopLevel_Precedence); | |
dogben
2016/07/31 23:20:20
nit: kSequence_Precedence, with same caveat as abo
ethannicholas
2016/08/02 16:13:17
Done.
| |
285 } | |
286 this->writeLine(";"); | |
287 } | |
288 } | |
289 | |
290 void GLSLCodeGenerator::writeStatement(Statement& s) { | |
291 switch (s.fKind) { | |
292 case Statement::kBlock_Kind: | |
293 this->writeBlock((Block&) s); | |
294 break; | |
295 case Statement::kExpression_Kind: | |
296 this->writeExpression(*((ExpressionStatement&) s).fExpression, kTopL evel_Precedence); | |
297 this->writeLine(";"); | |
298 break; | |
299 case Statement::kReturn_Kind: | |
300 this->writeReturnStatement((ReturnStatement&) s); | |
301 break; | |
302 case Statement::kVarDeclaration_Kind: | |
303 this->writeVarDeclaration(*((VarDeclarationStatement&) s).fDeclarati on); | |
304 break; | |
305 case Statement::kIf_Kind: | |
306 this->writeIfStatement((IfStatement&) s); | |
307 break; | |
308 case Statement::kFor_Kind: | |
309 this->writeForStatement((ForStatement&) s); | |
310 break; | |
311 case Statement::kWhile_Kind: | |
312 this->writeWhileStatement((WhileStatement&) s); | |
313 break; | |
314 case Statement::kDo_Kind: | |
315 this->writeDoStatement((DoStatement&) s); | |
316 break; | |
317 case Statement::kBreak_Kind: | |
318 this->writeLine("break;"); | |
319 break; | |
320 case Statement::kContinue_Kind: | |
321 this->writeLine("continue;"); | |
322 break; | |
323 case Statement::kDiscard_Kind: | |
324 this->writeLine("discard;"); | |
325 break; | |
326 default: | |
327 ABORT("unsupported statement: %s", s.description().c_str()); | |
328 } | |
329 } | |
330 | |
331 void GLSLCodeGenerator::writeBlock(Block& b) { | |
332 this->writeLine("{"); | |
333 fIndentation++; | |
334 for (const auto& s : b.fStatements) { | |
335 this->writeStatement(*s); | |
336 } | |
337 fIndentation--; | |
338 this->writeLine("}"); | |
339 } | |
340 | |
341 void GLSLCodeGenerator::writeIfStatement(IfStatement& stmt) { | |
342 this->write("if ("); | |
343 this->writeExpression(*stmt.fTest, kTopLevel_Precedence); | |
344 this->write(") "); | |
345 this->writeStatement(*stmt.fIfTrue); | |
346 if (stmt.fIfFalse) { | |
347 this->write("else "); | |
348 this->writeStatement(*stmt.fIfFalse); | |
349 } | |
350 } | |
351 | |
352 void GLSLCodeGenerator::writeForStatement(ForStatement& f) { | |
353 this->write("for ("); | |
354 if (f.fInitializer) { | |
355 this->writeStatement(*f.fInitializer); | |
356 } | |
dogben
2016/07/31 23:20:20
else write semicolon
ethannicholas
2016/08/02 16:13:17
Done.
| |
357 if (f.fTest) { | |
358 this->writeExpression(*f.fTest, kTopLevel_Precedence); | |
359 } | |
360 this->write("; "); | |
361 if (f.fNext) { | |
362 this->writeExpression(*f.fNext, kTopLevel_Precedence); | |
363 } | |
364 this->write(") "); | |
365 this->writeStatement(*f.fStatement); | |
366 } | |
367 | |
368 void GLSLCodeGenerator::writeWhileStatement(WhileStatement& w) { | |
369 this->write("while ("); | |
370 this->writeExpression(*w.fTest, kTopLevel_Precedence); | |
371 this->write(") "); | |
372 this->writeStatement(*w.fStatement); | |
373 } | |
374 | |
375 void GLSLCodeGenerator::writeDoStatement(DoStatement& d) { | |
376 this->write("do "); | |
377 this->writeStatement(*d.fStatement); | |
378 this->write("while ("); | |
379 this->writeExpression(*d.fTest, kTopLevel_Precedence); | |
380 this->writeLine(");"); | |
381 } | |
382 | |
383 void GLSLCodeGenerator::writeReturnStatement(ReturnStatement& r) { | |
384 this->write("return"); | |
385 if (r.fExpression) { | |
386 this->write(" "); | |
387 this->writeExpression(*r.fExpression, kTopLevel_Precedence); | |
388 } | |
389 this->writeLine(";"); | |
390 } | |
391 | |
392 void GLSLCodeGenerator::generateCode(Program& program, std::ostream& out) { | |
393 ASSERT(fOut == nullptr); | |
394 fOut = &out; | |
395 this->write("#version " + to_string(fCaps.fVersion)); | |
396 if (fCaps.fStandard == GLCaps::kGLES_Standard) { | |
egdaniel
2016/08/01 13:18:27
I don't see fCaps used anywhere else so why split
ethannicholas
2016/08/02 16:13:17
Going to start paying a lot more attention to it i
| |
397 this->write(" es"); | |
398 } | |
399 this->writeLine(); | |
400 for (const auto& e : program.fElements) { | |
401 switch (e->fKind) { | |
402 case ProgramElement::kExtension_Kind: | |
403 this->writeExtension((Extension&) *e); | |
404 break; | |
405 case ProgramElement::kVar_Kind: | |
406 this->writeVarDeclaration((VarDeclaration&) *e); | |
407 break; | |
408 case ProgramElement::kInterfaceBlock_Kind: | |
409 this->writeInterfaceBlock((InterfaceBlock&) *e); | |
410 break; | |
411 case ProgramElement::kFunction_Kind: | |
412 this->writeFunction((FunctionDefinition&) *e); | |
413 break; | |
414 default: | |
415 printf("%s\n", e->description().c_str()); | |
416 ABORT("unsupported program element"); | |
417 } | |
418 } | |
419 fOut = nullptr; | |
420 } | |
421 | |
422 } | |
OLD | NEW |