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