Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Side by Side Diff: src/sksl/SkSLGLSLCodeGenerator.cpp

Issue 2185393003: added initial GLSL support to skslc (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: added initial GLSL support to skslc Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698