]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/output.cpp
1d82cae6a9ed95f20debbcf500a6a242c929c54a
[libs/gl.git] / source / glsl / output.cpp
1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
3 #include "output.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9 namespace SL {
10
11 Formatter::Formatter():
12         stage(0),
13         source_index(0),
14         source_line(1),
15         indent(0),
16         parameter_list(false),
17         omit_builtin(false)
18 { }
19
20 const string &Formatter::apply(Stage &s)
21 {
22         stage = &s;
23         omit_builtin = true;
24
25         const Version &ver = s.required_features.glsl_version;
26
27         if(ver)
28         {
29                 append(format("#version %d%02d", ver.major, ver.minor));
30                 if(s.required_features.gl_api==OPENGL_ES2 && ver>=Version(3, 0))
31                         append(" es");
32                 formatted += '\n';
33         }
34
35         if(s.required_features.arb_enhanced_layouts)
36                 append("#extension GL_ARB_enhanced_layouts: require\n");
37         if(s.required_features.arb_explicit_attrib_location)
38                 append("#extension GL_ARB_explicit_attrib_location: require\n");
39         if(s.required_features.arb_explicit_uniform_location)
40                 append("#extension GL_ARB_explicit_uniform_location: require\n");
41         if(s.required_features.arb_gpu_shader5)
42                 append("#extension GL_ARB_gpu_shader5: require\n");
43         if(s.required_features.arb_separate_shader_objects)
44                 append("#extension GL_ARB_separate_shader_objects: require\n");
45         if(s.required_features.arb_uniform_buffer_object)
46                 append("#extension GL_ARB_uniform_buffer_object: require\n");
47         if(s.required_features.ext_gpu_shader4)
48                 append("#extension GL_EXT_gpu_shader4: require\n");
49         if(s.required_features.ext_texture_array)
50                 append("#extension GL_EXT_texture_array: require\n");
51         formatted += '\n';
52
53         s.content.visit(*this);
54
55         return formatted;
56 }
57
58 void Formatter::append(const string &text)
59 {
60         formatted += text;
61         for(string::const_iterator i=text.begin(); i!=text.end(); ++i)
62                 if(*i=='\n')
63                         ++source_line;
64 }
65
66 void Formatter::append(char c)
67 {
68         formatted += c;
69         if(c=='\n')
70                 ++source_line;
71 }
72
73 void Formatter::set_source(unsigned index, unsigned line)
74 {
75         if(index!=source_index || (index && line!=source_line))
76         {
77                 if(index==source_index && line==source_line+1)
78                         formatted += '\n';
79                 else
80                 {
81                         unsigned l = line;
82                         if(stage && stage->required_features.glsl_version && stage->required_features.glsl_version<Version(3, 30))
83                                 --l;
84                         formatted += format("#line %d %d\n", l, index);
85                 }
86         }
87         source_index = index;
88         source_line = line;
89 }
90
91 void Formatter::visit(Block &block)
92 {
93         unsigned brace_indent = indent;
94         bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
95         if(use_braces)
96                 append(format("%s{\n", string(brace_indent*2, ' ')));
97
98         SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
99         string spaces(indent*2, ' ');
100         bool first = true;
101         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
102         {
103                 if(omit_builtin && (*i)->source<=BUILTIN_SOURCE)
104                         continue;
105                 if(!first)
106                         append('\n');
107                 first = false;
108                 set_source((*i)->source, (*i)->line);
109                 append(spaces);
110                 (*i)->visit(*this);
111         }
112
113         if(use_braces)
114                 append(format("\n%s}", string(brace_indent*2, ' ')));
115 }
116
117 void Formatter::visit_expression(Expression &expr, const Operator *outer_oper, bool on_rhs)
118 {
119         unsigned outer_precedence = (outer_oper ? outer_oper->precedence : 20);
120         unsigned inner_precedence = (expr.oper ? expr.oper->precedence : 0);
121
122         bool needs_parentheses = (inner_precedence>=outer_precedence);
123
124         // Omit parentheses if the outer operator encloses this operand.
125         if(outer_oper && outer_oper->type==Operator::BINARY && outer_oper->token2[0] && on_rhs)
126                 needs_parentheses = false;
127
128         if(expr.oper)
129         {
130                 /* Omit parentheses if the inner expression's operator sits between the
131                 expression and the outer operator. */
132                 bool oper_on_left = expr.oper->type==Operator::PREFIX;
133                 bool oper_on_right = expr.oper->type==Operator::POSTFIX || (expr.oper->type==Operator::BINARY && expr.oper->token2[0]);
134                 if(expr.oper && ((oper_on_left && on_rhs) || (oper_on_right && !on_rhs)))
135                         needs_parentheses = false;
136
137                 // Omit parentheses if the operator's natural grouping works out.
138                 if(expr.oper==outer_oper)
139                         needs_parentheses = (expr.oper->assoc!=Operator::ASSOCIATIVE && on_rhs!=(expr.oper->assoc==Operator::RIGHT_TO_LEFT));
140         }
141
142         if(needs_parentheses)
143                 append('(');
144         expr.visit(*this);
145         if(needs_parentheses)
146                 append(')');
147 }
148
149 void Formatter::visit(Literal &literal)
150 {
151         append(literal.token);
152 }
153
154 void Formatter::visit(VariableReference &var)
155 {
156         append(var.name);
157 }
158
159 void Formatter::visit(InterfaceBlockReference &iface)
160 {
161         append(iface.name);
162 }
163
164 void Formatter::visit(MemberAccess &memacc)
165 {
166         visit_expression(*memacc.left, memacc.oper, false);
167         append(format(".%s", memacc.member));
168 }
169
170 void Formatter::visit(Swizzle &swizzle)
171 {
172         visit_expression(*swizzle.left, swizzle.oper, false);
173         append(format(".%s", swizzle.component_group));
174 }
175
176 void Formatter::visit(UnaryExpression &unary)
177 {
178         if(unary.oper->type==Operator::PREFIX)
179                 append(unary.oper->token);
180         visit_expression(*unary.expression, unary.oper, unary.oper->type==Operator::PREFIX);
181         if(unary.oper->type==Operator::POSTFIX)
182                 append(unary.oper->token);
183 }
184
185 void Formatter::visit(BinaryExpression &binary)
186 {
187         visit_expression(*binary.left, binary.oper, false);
188         append(binary.oper->token);
189         visit_expression(*binary.right, binary.oper, true);
190         if(binary.oper->token2[0])
191                 append(binary.oper->token2);
192 }
193
194 void Formatter::visit(Assignment &assign)
195 {
196         visit_expression(*assign.left, assign.oper, false);
197         append(format(" %s ", assign.oper->token));
198         visit_expression(*assign.right, assign.oper, true);
199 }
200
201 void Formatter::visit(TernaryExpression &ternary)
202 {
203         visit_expression(*ternary.condition, ternary.oper, false);
204         append(ternary.oper->token);
205         visit_expression(*ternary.true_expr, ternary.oper, false);
206         if(ternary.oper->token2)
207                 append(ternary.oper->token2);
208         visit_expression(*ternary.false_expr, ternary.oper, true);
209 }
210
211 void Formatter::visit(FunctionCall &call)
212 {
213         append(format("%s(", call.name));
214         for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
215         {
216                 if(i!=call.arguments.begin())
217                         append(", ");
218                 (*i)->visit(*this);
219         }
220         append(')');
221 }
222
223 void Formatter::visit(ExpressionStatement &expr)
224 {
225         expr.expression->visit(*this);
226         append(';');
227 }
228
229 void Formatter::visit(Import &import)
230 {
231         append(format("import %s;", import.module));
232 }
233
234 void Formatter::visit(Precision &prec)
235 {
236         append(format("precision %s %s;", prec.precision, prec.type));
237 }
238
239 void Formatter::visit(Layout &layout)
240 {
241         append("layout(");
242         for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
243         {
244                 if(i!=layout.qualifiers.begin())
245                         append(", ");
246                 append(i->name);
247                 if(i->has_value)
248                         append(format("=%d", i->value));
249         }
250         append(')');
251 }
252
253 void Formatter::visit(InterfaceLayout &layout)
254 {
255         layout.layout.visit(*this);
256         append(format(" %s;", layout.interface));
257 }
258
259 void Formatter::visit(StructDeclaration &strct)
260 {
261         append(format("struct %s\n", strct.name));
262         strct.members.visit(*this);
263         append(';');
264 }
265
266 void Formatter::visit(VariableDeclaration &var)
267 {
268         if(var.layout)
269         {
270                 var.layout->visit(*this);
271                 append(' ');
272         }
273         if(var.constant)
274                 append("const ");
275         if(!var.interpolation.empty())
276                 append(format("%s ", var.interpolation));
277         if(!var.sampling.empty())
278                 append(format("%s ", var.sampling));
279         if(!var.interface.empty())
280         {
281                 string interface = var.interface;
282                 if(stage && stage->required_features.glsl_version && stage->required_features.glsl_version<Version(1, 30))
283                 {
284                         if(stage->type==Stage::VERTEX && var.interface=="in")
285                                 interface = "attribute";
286                         else if((stage->type==Stage::VERTEX && var.interface=="out") || (stage->type==Stage::FRAGMENT && var.interface=="in"))
287                                 interface = "varying";
288                 }
289                 append(format("%s ", interface));
290         }
291         if(!var.precision.empty())
292                 append(format("%s ", var.precision));
293         string type_name = var.type_declaration->name;
294         if(var.array)
295                 type_name = type_name.substr(0, type_name.find('['));
296         append(format("%s %s", type_name, var.name));
297         if(var.array)
298         {
299                 append('[');
300                 if(var.array_size)
301                         var.array_size->visit(*this);
302                 append(']');
303         }
304         if(var.init_expression)
305         {
306                 append(" = ");
307                 var.init_expression->visit(*this);
308         }
309         if(!parameter_list)
310                 append(';');
311 }
312
313 void Formatter::visit(InterfaceBlock &iface)
314 {
315         if(iface.layout)
316         {
317                 iface.layout->visit(*this);
318                 append(' ');
319         }
320         append(format("%s %s\n", iface.interface, iface.block_name));
321         if(iface.struct_declaration)
322                 iface.struct_declaration->members.visit(*this);
323         if(!iface.instance_name.empty())
324         {
325                 append(' ');
326                 append(iface.instance_name);
327                 if(iface.array)
328                         append("[]");
329         }
330         append(';');
331 }
332
333 void Formatter::visit(FunctionDeclaration &func)
334 {
335         append(format("%s %s(", func.return_type_declaration->name, func.name));
336         for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
337         {
338                 if(i!=func.parameters.begin())
339                         append(", ");
340                 SetFlag set(parameter_list);
341                 (*i)->visit(*this);
342         }
343         append(')');
344         if(func.definition==&func)
345         {
346                 append('\n');
347                 func.body.visit(*this);
348         }
349         else
350                 append(';');
351 }
352
353 void Formatter::visit(Conditional &cond)
354 {
355         append("if(");
356         cond.condition->visit(*this);
357         append(")\n");
358
359         cond.body.visit(*this);
360         if(!cond.else_body.body.empty())
361         {
362                 Conditional *else_cond = dynamic_cast<Conditional *>(cond.else_body.body.front().get());
363                 if(cond.else_body.body.size()==1 && else_cond)
364                 {
365                         append('\n');
366                         set_source(else_cond->source, else_cond->line);
367                         append(format("%selse ", string(indent*2, ' ')));
368                         else_cond->visit(*this);
369                 }
370                 else
371                 {
372                         append(format("\n%selse\n", string(indent*2, ' ')));
373                         cond.else_body.visit(*this);
374                 }
375         }
376 }
377
378 void Formatter::visit(Iteration &iter)
379 {
380         if(!iter.init_statement && iter.condition && !iter.loop_expression)
381         {
382                 append("while(");
383                 iter.condition->visit(*this);
384                 append(')');
385         }
386         else
387         {
388                 append("for(");
389                 if(iter.init_statement)
390                         iter.init_statement->visit(*this);
391                 else
392                         append(';');
393                 if(iter.condition)
394                 {
395                         append(' ');
396                         iter.condition->visit(*this);
397                 }
398                 append(';');
399                 if(iter.loop_expression)
400                 {
401                         append(' ');
402                         iter.loop_expression->visit(*this);
403                 }
404                 append(')');
405         }
406
407         if(iter.body.body.empty())
408                 append(" { }");
409         else
410         {
411                 append('\n');
412                 iter.body.visit(*this);
413         }
414 }
415
416 void Formatter::visit(Passthrough &pass)
417 {
418         append("passthrough");
419         if(pass.subscript)
420         {
421                 append('[');
422                 pass.subscript->visit(*this);
423                 append(']');
424         }
425         append(';');
426 }
427
428 void Formatter::visit(Return &ret)
429 {
430         append("return");
431         if(ret.expression)
432         {
433                 append(' ');
434                 ret.expression->visit(*this);
435         }
436         append(';');
437 }
438
439 void Formatter::visit(Jump &jump)
440 {
441         append(jump.keyword);
442         append(';');
443 }
444
445 } // namespace SL
446 } // namespace GL
447 } // namespace Msp