]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Refactor the way of applying visitors to stages
[libs/gl.git] / source / glsl / generate.cpp
1 #include <msp/core/raii.h>
2 #include "builtin.h"
3 #include "generate.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9 namespace SL {
10
11 DeclarationCombiner::DeclarationCombiner():
12         toplevel(true)
13 { }
14
15 void DeclarationCombiner::visit(Block &block)
16 {
17         if(!toplevel)
18                 return;
19
20         SetForScope<bool> set(toplevel, false);
21         BlockModifier::visit(block);
22 }
23
24 void DeclarationCombiner::visit(FunctionDeclaration &func)
25 {
26         vector<FunctionDeclaration *> &decls = functions[func.name];
27         if(func.definition)
28         {
29                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
30                 {
31                         (*i)->definition = func.definition;
32                         (*i)->body.body.clear();
33                 }
34         }
35         decls.push_back(&func);
36 }
37
38 void DeclarationCombiner::visit(VariableDeclaration &var)
39 {
40         VariableDeclaration *&ptr = variables[var.name];
41         if(ptr)
42         {
43                 ptr->type = var.type;
44                 if(var.init_expression)
45                         ptr->init_expression = var.init_expression;
46                 if(var.layout)
47                 {
48                         if(ptr->layout)
49                         {
50                                 for(vector<Layout::Qualifier>::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i)
51                                 {
52                                         bool found = false;
53                                         for(vector<Layout::Qualifier>::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j)
54                                                 if(j->identifier==i->identifier)
55                                                 {
56                                                         j->value = i->value;
57                                                         found = true;
58                                                 }
59
60                                         if(!found)
61                                                 ptr->layout->qualifiers.push_back(*i);
62                                 }
63                         }
64                         else
65                                 ptr->layout = var.layout;
66                 }
67                 remove_node = true;
68         }
69         else
70                 ptr = &var;
71 }
72
73
74 VariableResolver::VariableResolver():
75         anonymous(false),
76         record_target(false),
77         assignment_target(0),
78         self_referencing(false)
79 { }
80
81 void VariableResolver::apply(Stage &stage)
82 {
83         Stage *builtins = get_builtins(stage.type);
84         if(builtins)
85                 blocks.push_back(&builtins->content);
86         visit(stage.content);
87         if(builtins)
88                 blocks.pop_back();
89 }
90
91 void VariableResolver::visit(Block &block)
92 {
93         blocks.push_back(&block);
94         block.variables.clear();
95         TraversingVisitor::visit(block);
96         blocks.pop_back();
97 }
98
99 void VariableResolver::visit(VariableReference &var)
100 {
101         var.declaration = 0;
102         type = 0;
103         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
104         {
105                 --i;
106                 map<string, VariableDeclaration *>::iterator j = (*i)->variables.find(var.name);
107                 if(j!=(*i)->variables.end())
108                 {
109                         var.declaration = j->second;
110                         type = j->second->type_declaration;
111                         break;
112                 }
113         }
114
115         if(record_target)
116         {
117                 if(assignment_target)
118                 {
119                         record_target = false;
120                         assignment_target = 0;
121                 }
122                 else
123                         assignment_target = var.declaration;
124         }
125         else if(var.declaration && var.declaration==assignment_target)
126                 self_referencing = true;
127 }
128
129 void VariableResolver::visit(MemberAccess &memacc)
130 {
131         type = 0;
132         TraversingVisitor::visit(memacc);
133         memacc.declaration = 0;
134         if(type)
135         {
136                 map<string, VariableDeclaration *>::iterator i = type->members.variables.find(memacc.member);
137                 if(i!=type->members.variables.end())
138                 {
139                         memacc.declaration = i->second;
140                         type = i->second->type_declaration;
141                 }
142                 else
143                         type = 0;
144         }
145 }
146
147 void VariableResolver::visit(BinaryExpression &binary)
148 {
149         if(binary.oper=="[")
150         {
151                 {
152                         SetForScope<bool> set(record_target, false);
153                         binary.right->visit(*this);
154                 }
155                 type = 0;
156                 binary.left->visit(*this);
157         }
158         else
159         {
160                 TraversingVisitor::visit(binary);
161                 type = 0;
162         }
163 }
164
165 void VariableResolver::visit(Assignment &assign)
166 {
167         {
168                 SetFlag set(record_target);
169                 assignment_target = 0;
170                 assign.left->visit(*this);
171         }
172
173         self_referencing = false;
174         assign.right->visit(*this);
175
176         assign.self_referencing = (self_referencing || assign.oper!="=");
177         assign.target_declaration = assignment_target;
178 }
179
180 void VariableResolver::visit(StructDeclaration &strct)
181 {
182         TraversingVisitor::visit(strct);
183         blocks.back()->types[strct.name] = &strct;
184 }
185
186 void VariableResolver::visit(VariableDeclaration &var)
187 {
188         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
189         {
190                 --i;
191                 map<string, StructDeclaration *>::iterator j = (*i)->types.find(var.type);
192                 if(j!=(*i)->types.end())
193                         var.type_declaration = j->second;
194         }
195
196         if(!block_interface.empty() && var.interface.empty())
197                 var.interface = block_interface;
198
199         TraversingVisitor::visit(var);
200         blocks.back()->variables[var.name] = &var;
201         if(anonymous && blocks.size()>1)
202                 blocks[blocks.size()-2]->variables[var.name] = &var;
203 }
204
205 void VariableResolver::visit(InterfaceBlock &iface)
206 {
207         SetFlag set(anonymous);
208         SetForScope<string> set2(block_interface, iface.interface);
209         TraversingVisitor::visit(iface);
210 }
211
212
213 void FunctionResolver::visit(FunctionCall &call)
214 {
215         map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
216         if(i!=functions.end())
217                 call.declaration = i->second.back();
218
219         TraversingVisitor::visit(call);
220 }
221
222 void FunctionResolver::visit(FunctionDeclaration &func)
223 {
224         vector<FunctionDeclaration *> &decls = functions[func.name];
225         if(func.definition)
226         {
227                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
228                         (*i)->definition = func.definition;
229                 decls.clear();
230                 decls.push_back(&func);
231         }
232         else if(!decls.empty() && decls.back()->definition)
233                 func.definition = decls.back()->definition;
234         else
235                 decls.push_back(&func);
236
237         TraversingVisitor::visit(func);
238 }
239
240
241 InterfaceGenerator::InterfaceGenerator():
242         stage(0),
243         scope_level(0)
244 { }
245
246 string InterfaceGenerator::get_out_prefix(Stage::Type type)
247 {
248         if(type==Stage::VERTEX)
249                 return "_vs_out_";
250         else if(type==Stage::GEOMETRY)
251                 return "_gs_out_";
252         else
253                 return string();
254 }
255
256 void InterfaceGenerator::apply(Stage &s)
257 {
258         SetForScope<Stage *> set(stage, &s);
259         if(stage->previous)
260                 in_prefix = get_out_prefix(stage->previous->type);
261         out_prefix = get_out_prefix(stage->type);
262         visit(s.content);
263 }
264
265 void InterfaceGenerator::visit(Block &block)
266 {
267         SetForScope<unsigned> set(scope_level, scope_level+1);
268         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
269         {
270                 (*i)->visit(*this);
271
272                 if(scope_level==1)
273                 {
274                         for(map<string, RefPtr<VariableDeclaration> >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
275                         {
276                                 NodeList<Statement>::iterator k = block.body.insert(i, j->second);
277                                 (*k)->visit(*this);
278                         }
279                         iface_declarations.clear();
280                 }
281
282                 apply_and_increment(block, i);
283         }
284 }
285
286 string InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
287 {
288         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
289         return prefix+name.substr(offset);
290 }
291
292 bool InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
293 {
294         const map<string, VariableDeclaration *> &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables);
295         if(stage_vars.count(name) || iface_declarations.count(name))
296                 return false;
297
298         VariableDeclaration* iface_var = new VariableDeclaration;
299         iface_var->sampling = var.sampling;
300         iface_var->interface = iface;
301         iface_var->type = var.type;
302         iface_var->type_declaration = var.type_declaration;
303         iface_var->name = name;
304         if(stage->type==Stage::GEOMETRY)
305                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
306         else
307                 iface_var->array = var.array;
308         if(iface_var->array)
309                 iface_var->array_size = var.array_size;
310         if(iface=="in")
311                 iface_var->linked_declaration = &var;
312         iface_declarations[name] = iface_var;
313
314         return true;
315 }
316
317 ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
318 {
319         Assignment *assign = new Assignment;
320         VariableReference *ref = new VariableReference;
321         ref->name = left;
322         assign->left = ref;
323         assign->oper = "=";
324         assign->right = right;
325
326         ExpressionStatement *stmt = new ExpressionStatement;
327         stmt->expression = assign;
328         stmt->visit(*this);
329         insert_nodes.push_back(stmt);
330
331         return *stmt;
332 }
333
334 void InterfaceGenerator::visit(VariableReference &var)
335 {
336         if(var.declaration || !stage->previous)
337                 return;
338         if(iface_declarations.count(var.name))
339                 return;
340
341         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
342         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
343         if(i==prev_out.end())
344                 i = prev_out.find(in_prefix+var.name);
345         if(i!=prev_out.end())
346         {
347                 generate_interface(*i->second, "in", i->second->name);
348                 var.name = i->second->name;
349         }
350 }
351
352 void InterfaceGenerator::visit(VariableDeclaration &var)
353 {
354         if(var.interface=="out")
355         {
356                 if(scope_level==1)
357                         stage->out_variables[var.name] = &var;
358                 else if(generate_interface(var, "out", change_prefix(var.name, string())))
359                 {
360                         remove_node = true;
361                         if(var.init_expression)
362                         {
363                                 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
364                                 stmt.source = var.source;
365                                 stmt.line = var.line;
366                                 return;
367                         }
368                 }
369         }
370         else if(var.interface=="in")
371         {
372                 stage->in_variables[var.name] = &var;
373                 if(var.linked_declaration)
374                         var.linked_declaration->linked_declaration = &var;
375                 else if(stage->previous)
376                 {
377                         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
378                         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
379                         if(i!=prev_out.end())
380                         {
381                                 var.linked_declaration = i->second;
382                                 i->second->linked_declaration = &var;
383                         }
384                 }
385         }
386
387         TraversingVisitor::visit(var);
388 }
389
390 void InterfaceGenerator::visit(Passthrough &pass)
391 {
392         vector<VariableDeclaration *> pass_vars;
393
394         for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
395                 pass_vars.push_back(i->second);
396         for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
397                 if(i->second->interface=="in")
398                         pass_vars.push_back(i->second.get());
399
400         if(stage->previous)
401         {
402                 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
403                 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
404                 {
405                         bool linked = false;
406                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
407                                 linked = ((*j)->linked_declaration==i->second);
408
409                         if(!linked && generate_interface(*i->second, "in", i->second->name))
410                                 pass_vars.push_back(i->second);
411                 }
412         }
413
414         if(stage->type==Stage::GEOMETRY)
415         {
416                 VariableReference *ref = new VariableReference;
417                 ref->name = "gl_in";
418
419                 BinaryExpression *subscript = new BinaryExpression;
420                 subscript->left = ref;
421                 subscript->oper = "[";
422                 subscript->right = pass.subscript;
423                 subscript->after = "]";
424
425                 MemberAccess *memacc = new MemberAccess;
426                 memacc->left = subscript;
427                 memacc->member = "gl_Position";
428
429                 insert_assignment("gl_Position", memacc);
430         }
431
432         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
433         {
434                 string out_name = change_prefix((*i)->name, out_prefix);
435                 generate_interface(**i, "out", out_name);
436
437                 VariableReference *ref = new VariableReference;
438                 ref->name = (*i)->name;
439                 if(pass.subscript)
440                 {
441                         BinaryExpression *subscript = new BinaryExpression;
442                         subscript->left = ref;
443                         subscript->oper = "[";
444                         subscript->right = pass.subscript;
445                         subscript->after = "]";
446                         insert_assignment(out_name, subscript);
447                 }
448                 else
449                         insert_assignment(out_name, ref);
450         }
451
452         remove_node = true;
453 }
454
455
456 DeclarationReorderer::DeclarationReorderer():
457         scope_level(0),
458         kind(NO_DECLARATION)
459 { }
460
461 void DeclarationReorderer::visit(FunctionCall &call)
462 {
463         FunctionDeclaration *def = call.declaration;
464         if(def)
465                 def = def->definition;
466         if(def && !ordered_funcs.count(def))
467                 needed_funcs.insert(def);
468 }
469
470 void DeclarationReorderer::visit(Block &block)
471 {
472         SetForScope<unsigned> set(scope_level, scope_level+1);
473         if(scope_level>1)
474                 return TraversingVisitor::visit(block);
475
476         NodeList<Statement>::iterator struct_insert_point = block.body.end();
477         NodeList<Statement>::iterator variable_insert_point = block.body.end();
478         NodeList<Statement>::iterator function_insert_point = block.body.end();
479         unsigned unordered_func_count = 0;
480         bool ordered_any_funcs = false;
481
482         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
483         {
484                 kind = NO_DECLARATION;
485                 (*i)->visit(*this);
486
487                 bool moved = false;
488                 if(kind==STRUCT && struct_insert_point!=block.body.end())
489                 {
490                         block.body.insert(struct_insert_point, *i);
491                         moved = true;
492                 }
493                 else if(kind>STRUCT && struct_insert_point==block.body.end())
494                         struct_insert_point = i;
495
496                 if(kind==VARIABLE && variable_insert_point!=block.body.end())
497                 {
498                         block.body.insert(variable_insert_point, *i);
499                         moved = true;
500                 }
501                 else if(kind>VARIABLE && variable_insert_point==block.body.end())
502                         variable_insert_point = i;
503
504                 if(kind==FUNCTION)
505                 {
506                         if(function_insert_point==block.body.end())
507                                 function_insert_point = i;
508
509                         if(needed_funcs.empty())
510                         {
511                                 ordered_funcs.insert(i->get());
512                                 if(i!=function_insert_point)
513                                 {
514                                         block.body.insert(function_insert_point, *i);
515                                         moved = true;
516                                 }
517                                 else
518                                         ++function_insert_point;
519                                 ordered_any_funcs = true;
520                         }
521                         else
522                                 ++unordered_func_count;
523                 }
524
525                 if(moved)
526                 {
527                         if(function_insert_point==i)
528                                 ++function_insert_point;
529                         block.body.erase(i++);
530                 }
531                 else
532                         ++i;
533
534                 if(i==block.body.end() && unordered_func_count)
535                 {
536                         if(!ordered_any_funcs)
537                                 // A subset of the remaining functions forms a recursive loop
538                                 /* TODO pick a function and move it up, adding any necessary
539                                 declarations */
540                                 break;
541
542                         i = function_insert_point;
543                         unordered_func_count = 0;
544                 }
545         }
546 }
547
548 void DeclarationReorderer::visit(VariableDeclaration &var)
549 {
550         TraversingVisitor::visit(var);
551         kind = VARIABLE;
552 }
553
554 void DeclarationReorderer::visit(FunctionDeclaration &func)
555 {
556         needed_funcs.clear();
557         func.body.visit(*this);
558         needed_funcs.erase(&func);
559         kind = FUNCTION;
560 }
561
562 } // namespace SL
563 } // namespace GL
564 } // namespace Msp