]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Store functions definitions in Stage
[libs/gl.git] / source / glsl / generate.cpp
1 #include <msp/core/hash.h>
2 #include <msp/core/raii.h>
3 #include <msp/strings/lexicalcast.h>
4 #include "builtin.h"
5 #include "generate.h"
6
7 using namespace std;
8
9 namespace Msp {
10 namespace GL {
11 namespace SL {
12
13 void DeclarationCombiner::apply(Stage &stage)
14 {
15         stage.content.visit(*this);
16         NodeRemover().apply(stage, nodes_to_remove);
17 }
18
19 void DeclarationCombiner::visit(Block &block)
20 {
21         if(current_block)
22                 return;
23
24         TraversingVisitor::visit(block);
25 }
26
27 void DeclarationCombiner::visit(VariableDeclaration &var)
28 {
29         VariableDeclaration *&ptr = variables[var.name];
30         if(ptr)
31         {
32                 ptr->type = var.type;
33                 if(var.init_expression)
34                         ptr->init_expression = var.init_expression;
35                 if(var.layout)
36                 {
37                         if(ptr->layout)
38                         {
39                                 for(vector<Layout::Qualifier>::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i)
40                                 {
41                                         bool found = false;
42                                         for(vector<Layout::Qualifier>::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j)
43                                                 if(j->name==i->name)
44                                                 {
45                                                         j->has_value = i->value;
46                                                         j->value = i->value;
47                                                         found = true;
48                                                 }
49
50                                         if(!found)
51                                                 ptr->layout->qualifiers.push_back(*i);
52                                 }
53                         }
54                         else
55                                 ptr->layout = var.layout;
56                 }
57                 nodes_to_remove.insert(&var);
58         }
59         else
60                 ptr = &var;
61 }
62
63
64 ConstantSpecializer::ConstantSpecializer():
65         values(0)
66 { }
67
68 void ConstantSpecializer::apply(Stage &stage, const map<string, int> *v)
69 {
70         values = v;
71         stage.content.visit(*this);
72 }
73
74 void ConstantSpecializer::visit(VariableDeclaration &var)
75 {
76         bool specializable = false;
77         if(var.layout)
78         {
79                 vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
80                 for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i)
81                         if(i->name=="constant_id")
82                         {
83                                 specializable = true;
84                                 if(values)
85                                         qualifiers.erase(i);
86                                 else if(i->value==-1)
87                                         i->value = hash32(var.name)&0x7FFFFFFF;
88                                 break;
89                         }
90
91                 if(qualifiers.empty())
92                         var.layout = 0;
93         }
94
95         if(specializable && values)
96         {
97                 map<string, int>::const_iterator i = values->find(var.name);
98                 if(i!=values->end())
99                 {
100                         RefPtr<Literal> literal = new Literal;
101                         if(var.type=="bool")
102                         {
103                                 literal->token = (i->second ? "true" : "false");
104                                 literal->value = static_cast<bool>(i->second);
105                         }
106                         else if(var.type=="int")
107                         {
108                                 literal->token = lexical_cast<string>(i->second);
109                                 literal->value = i->second;
110                         }
111                         var.init_expression = literal;
112                 }
113         }
114 }
115
116
117 void BlockHierarchyResolver::enter(Block &block)
118 {
119         block.parent = current_block;
120 }
121
122
123 VariableResolver::VariableResolver():
124         stage(0),
125         builtins(0),
126         members(0),
127         record_target(false),
128         assignment_target(0),
129         self_referencing(false)
130 { }
131
132 void VariableResolver::apply(Stage &s)
133 {
134         stage = &s;
135         Stage *builtin_stage = get_builtins(s.type);
136         builtins = (builtin_stage ? &builtin_stage->content : 0);
137         s.content.visit(*this);
138 }
139
140 Block *VariableResolver::next_block(Block &block)
141 {
142         return block.parent ? block.parent : &block!=builtins ? builtins : 0;
143 }
144
145 void VariableResolver::enter(Block &block)
146 {
147         block.variables.clear();
148 }
149
150 void VariableResolver::visit(VariableReference &var)
151 {
152         var.declaration = 0;
153         members = 0;
154         for(Block *block=current_block; (!var.declaration && block); block=next_block(*block))
155         {
156                 map<string, VariableDeclaration *>::iterator i = block->variables.find(var.name);
157                 if(i!=block->variables.end())
158                         var.declaration = i->second;
159         }
160
161         if(var.declaration)
162         {
163                 if(var.declaration->type_declaration)
164                         members = &var.declaration->type_declaration->members.variables;
165         }
166         else
167         {
168                 const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
169                 map<string, InterfaceBlock *>::const_iterator i = blocks.find(var.name);
170                 if(i!=blocks.end() && i->second->instance_name==var.name)
171                 {
172                         iface_ref = new InterfaceBlockReference;
173                         iface_ref->name = var.name;
174                         iface_ref->declaration = i->second;
175                         members = &i->second->members.variables;
176                 }
177                 else
178                 {
179                         for(i=blocks.begin(); (!var.declaration && i!=blocks.end()); ++i)
180                                 if(i->second->instance_name.empty())
181                                 {
182                                         map<string, VariableDeclaration *>::iterator j = i->second->members.variables.find(var.name);
183                                         if(j!=i->second->members.variables.end())
184                                                 var.declaration = j->second;
185                                 }
186                 }
187         }
188
189         if(record_target)
190         {
191                 if(assignment_target)
192                 {
193                         record_target = false;
194                         assignment_target = 0;
195                 }
196                 else
197                         assignment_target = var.declaration;
198         }
199         else if(var.declaration && var.declaration==assignment_target)
200                 self_referencing = true;
201 }
202
203 void VariableResolver::visit(InterfaceBlockReference &iface)
204 {
205         iface.declaration = 0;
206         for(Block *block=current_block; block; block=next_block(*block))
207         {
208                 map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find(iface.name);
209                 if(i!=stage->interface_blocks.end())
210                 {
211                         iface.declaration = i->second;
212                         members = &i->second->members.variables;
213                         break;
214                 }
215         }
216 }
217
218 void VariableResolver::visit(MemberAccess &memacc)
219 {
220         members = 0;
221         iface_ref = 0;
222         memacc.left->visit(*this);
223
224         if(iface_ref)
225                 memacc.left = iface_ref;
226         iface_ref = 0;
227
228         memacc.declaration = 0;
229         if(members)
230         {
231                 map<string, VariableDeclaration *>::iterator i = members->find(memacc.member);
232                 if(i!=members->end())
233                 {
234                         memacc.declaration = i->second;
235                         if(i->second->type_declaration)
236                                 members = &i->second->type_declaration->members.variables;
237                 }
238                 else
239                         members = 0;
240         }
241 }
242
243 void VariableResolver::visit(BinaryExpression &binary)
244 {
245         if(binary.oper=="[")
246         {
247                 {
248                         SetForScope<bool> set(record_target, false);
249                         binary.right->visit(*this);
250                 }
251                 members = 0;
252                 iface_ref = 0;
253                 binary.left->visit(*this);
254                 if(iface_ref)
255                         binary.left = iface_ref;
256                 iface_ref = 0;
257         }
258         else
259         {
260                 TraversingVisitor::visit(binary);
261                 members = 0;
262         }
263 }
264
265 void VariableResolver::visit(Assignment &assign)
266 {
267         {
268                 SetFlag set(record_target);
269                 assignment_target = 0;
270                 assign.left->visit(*this);
271         }
272
273         self_referencing = false;
274         assign.right->visit(*this);
275
276         assign.self_referencing = (self_referencing || assign.oper!="=");
277         assign.target_declaration = assignment_target;
278 }
279
280 void VariableResolver::visit(StructDeclaration &strct)
281 {
282         TraversingVisitor::visit(strct);
283         stage->types[strct.name] = &strct;
284 }
285
286 void VariableResolver::visit(VariableDeclaration &var)
287 {
288         map<string, StructDeclaration *>::iterator i = stage->types.find(var.type);
289         if(i!=stage->types.end())
290                 var.type_declaration = i->second;
291
292         if(!block_interface.empty() && var.interface.empty())
293                 var.interface = block_interface;
294
295         TraversingVisitor::visit(var);
296         current_block->variables[var.name] = &var;
297 }
298
299 void VariableResolver::visit(InterfaceBlock &iface)
300 {
301         /* Block names can't be used for any other identifiers so we can put them
302         in the same map with instance names. */
303         stage->interface_blocks[iface.name] = &iface;
304         if(!iface.instance_name.empty())
305                 stage->interface_blocks[iface.instance_name] = &iface;
306
307         SetForScope<string> set_iface(block_interface, iface.interface);
308         TraversingVisitor::visit(iface);
309 }
310
311
312 void FunctionResolver::apply(Stage &s)
313 {
314         stage = &s;
315         s.content.visit(*this);
316 }
317
318 void FunctionResolver::visit(FunctionCall &call)
319 {
320         map<string, FunctionDeclaration *>::iterator i = stage->functions.find(call.name);
321         if(i!=stage->functions.end())
322                 call.declaration = i->second;
323
324         TraversingVisitor::visit(call);
325 }
326
327 void FunctionResolver::visit(FunctionDeclaration &func)
328 {
329         FunctionDeclaration *&stage_decl = stage->functions[func.name];
330         vector<FunctionDeclaration *> &decls = declarations[func.name];
331         if(func.definition==&func)
332         {
333                 stage_decl = &func;
334
335                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
336                 {
337                         (*i)->definition = func.definition;
338                         (*i)->body.body.clear();
339                 }
340         }
341         else
342         {
343                 if(!stage_decl)
344                         stage_decl = &func;
345
346                 func.definition = stage_decl->definition;
347         }
348         decls.push_back(&func);
349
350         TraversingVisitor::visit(func);
351 }
352
353
354 InterfaceGenerator::InterfaceGenerator():
355         stage(0),
356         function_scope(false),
357         iface_block(0),
358         copy_block(false),
359         iface_target_block(0)
360 { }
361
362 string InterfaceGenerator::get_out_prefix(Stage::Type type)
363 {
364         if(type==Stage::VERTEX)
365                 return "_vs_out_";
366         else if(type==Stage::GEOMETRY)
367                 return "_gs_out_";
368         else
369                 return string();
370 }
371
372 void InterfaceGenerator::apply(Stage &s)
373 {
374         stage = &s;
375         iface_target_block = &stage->content;
376         if(stage->previous)
377                 in_prefix = get_out_prefix(stage->previous->type);
378         out_prefix = get_out_prefix(stage->type);
379         s.content.visit(*this);
380         NodeRemover().apply(s, nodes_to_remove);
381 }
382
383 void InterfaceGenerator::visit(Block &block)
384 {
385         SetForScope<Block *> set_block(current_block, &block);
386         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
387         {
388                 assignment_insert_point = i;
389                 if(&block==&stage->content)
390                         iface_insert_point = i;
391
392                 (*i)->visit(*this);
393         }
394 }
395
396 string InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
397 {
398         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
399         return prefix+name.substr(offset);
400 }
401
402 bool InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
403 {
404         if(stage->content.variables.count(name))
405                 return false;
406
407         VariableDeclaration* iface_var = new VariableDeclaration;
408         iface_var->sampling = var.sampling;
409         iface_var->interface = iface;
410         iface_var->type = var.type;
411         iface_var->type_declaration = var.type_declaration;
412         iface_var->name = name;
413         if(stage->type==Stage::GEOMETRY && !copy_block)
414                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
415         else
416                 iface_var->array = var.array;
417         if(iface_var->array)
418                 iface_var->array_size = var.array_size;
419         if(iface=="in")
420         {
421                 iface_var->layout = var.layout;
422                 iface_var->linked_declaration = &var;
423                 var.linked_declaration = iface_var;
424         }
425
426         iface_target_block->body.insert(iface_insert_point, iface_var);
427         iface_target_block->variables[name] = iface_var;
428
429         return true;
430 }
431
432 bool InterfaceGenerator::generate_interface(InterfaceBlock &out_block)
433 {
434         if(stage->interface_blocks.count(out_block.name))
435                 return false;
436
437         InterfaceBlock *in_block = new InterfaceBlock;
438         in_block->interface = "in";
439         in_block->name = out_block.name;
440         in_block->instance_name = out_block.instance_name;
441         if(stage->type==Stage::GEOMETRY)
442                 in_block->array = true;
443         else
444                 in_block->array = out_block.array;
445         in_block->linked_block = &out_block;
446         out_block.linked_block = in_block;
447
448         {
449                 SetFlag set_copy(copy_block, true);
450                 SetForScope<Block *> set_target(iface_target_block, &in_block->members);
451                 SetForScope<NodeList<Statement>::iterator> set_ins_pt(iface_insert_point, in_block->members.body.end());
452                 out_block.members.visit(*this);
453         }
454
455         iface_target_block->body.insert(iface_insert_point, in_block);
456         stage->interface_blocks[in_block->name] = in_block;
457         if(!in_block->instance_name.empty())
458                 stage->interface_blocks[in_block->instance_name] = in_block;
459
460         SetFlag set_scope(function_scope, false);
461         SetForScope<Block *> set_block(current_block, &stage->content);
462         in_block->visit(*this);
463
464         return true;
465 }
466
467 ExpressionStatement &InterfaceGenerator::insert_assignment(const string &left, Expression *right)
468 {
469         Assignment *assign = new Assignment;
470         VariableReference *ref = new VariableReference;
471         ref->name = left;
472         assign->left = ref;
473         assign->oper = "=";
474         assign->right = right;
475
476         ExpressionStatement *stmt = new ExpressionStatement;
477         stmt->expression = assign;
478         current_block->body.insert(assignment_insert_point, stmt);
479         stmt->visit(*this);
480
481         return *stmt;
482 }
483
484 void InterfaceGenerator::visit(VariableReference &var)
485 {
486         if(var.declaration || !stage->previous)
487                 return;
488         /* Don't pull a variable from previous stage if we just generated an out
489         interface in this stage */
490         if(stage->content.variables.count(var.name))
491                 return;
492
493         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
494         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
495         if(i==prev_vars.end() || i->second->interface!="out")
496                 i = prev_vars.find(in_prefix+var.name);
497         if(i!=prev_vars.end() && i->second->interface=="out")
498         {
499                 generate_interface(*i->second, "in", i->second->name);
500                 var.name = i->second->name;
501                 return;
502         }
503
504         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
505         map<string, InterfaceBlock *>::const_iterator j = prev_blocks.find(var.name);
506         if(j!=prev_blocks.end() && j->second->interface=="out" && j->second->instance_name==var.name)
507         {
508                 generate_interface(*j->second);
509                 return;
510         }
511
512         for(j=prev_blocks.begin(); j!=prev_blocks.end(); ++j)
513                 if(j->second->instance_name.empty())
514                 {
515                         i = j->second->members.variables.find(var.name);
516                         if(i!=j->second->members.variables.end())
517                         {
518                                 generate_interface(*j->second);
519                                 return;
520                         }
521                 }
522 }
523
524 void InterfaceGenerator::visit(VariableDeclaration &var)
525 {
526         if(copy_block)
527         {
528                 generate_interface(var, "in", var.name);
529                 return;
530         }
531
532         if(iface_block)
533         {
534                 if(iface_block->linked_block)
535                 {
536                         const map<string, VariableDeclaration *> &linked_vars = iface_block->linked_block->members.variables;
537                         map<string, VariableDeclaration *>::const_iterator i = linked_vars.find(var.name);
538                         if(i!=linked_vars.end())
539                                 var.linked_declaration = i->second;
540                 }
541                 return;
542         }
543
544         if(var.interface=="out")
545         {
546                 /* For out variables in function scope, generate a global interface and
547                 replace the local declaration with an assignment. */
548                 if(function_scope && generate_interface(var, "out", var.name))
549                 {
550                         nodes_to_remove.insert(&var);
551                         if(var.init_expression)
552                         {
553                                 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
554                                 stmt.source = var.source;
555                                 stmt.line = var.line;
556                                 return;
557                         }
558                 }
559         }
560         else if(var.interface=="in")
561         {
562                 /* Try to link in variables in global scope with out variables from
563                 previous stage */
564                 if(current_block==&stage->content && !var.linked_declaration && stage->previous)
565                 {
566                         const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
567                         map<string, VariableDeclaration *>::const_iterator i = prev_vars.find(var.name);
568                         if(i!=prev_vars.end() && i->second->interface=="out")
569                         {
570                                 var.linked_declaration = i->second;
571                                 i->second->linked_declaration = &var;
572                         }
573                 }
574         }
575
576         TraversingVisitor::visit(var);
577 }
578
579 void InterfaceGenerator::visit(InterfaceBlock &iface)
580 {
581         if(iface.interface=="in")
582         {
583                 if(!iface.linked_block && stage->previous)
584                 {
585                         const map<string, InterfaceBlock *> &prev_blocks = stage->previous->interface_blocks;
586                         map<string, InterfaceBlock *>::const_iterator i = prev_blocks.find(iface.name);
587                         if(i!=prev_blocks.end() && i->second->interface=="out" && i->second->name==iface.name)
588                         {
589                                 iface.linked_block = i->second;
590                                 i->second->linked_block = &iface;
591                         }
592                 }
593         }
594
595         SetForScope<InterfaceBlock *> set_iface(iface_block, &iface);
596         TraversingVisitor::visit(iface);
597 }
598
599 void InterfaceGenerator::visit(FunctionDeclaration &func)
600 {
601         SetFlag set_scope(function_scope, true);
602         // Skip parameters because they're not useful here
603         func.body.visit(*this);
604 }
605
606 void InterfaceGenerator::visit(Passthrough &pass)
607 {
608         vector<VariableDeclaration *> pass_vars;
609
610         for(map<string, VariableDeclaration *>::const_iterator i=stage->content.variables.begin(); i!=stage->content.variables.end(); ++i)
611                 if(i->second->interface=="in")
612                         pass_vars.push_back(i->second);
613
614         if(stage->previous)
615         {
616                 const map<string, VariableDeclaration *> &prev_vars = stage->previous->content.variables;
617                 for(map<string, VariableDeclaration *>::const_iterator i=prev_vars.begin(); i!=prev_vars.end(); ++i)
618                 {
619                         bool linked = false;
620                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
621                                 linked = ((*j)->linked_declaration==i->second);
622
623                         if(!linked && generate_interface(*i->second, "in", i->second->name))
624                                 pass_vars.push_back(i->second);
625                 }
626         }
627
628         if(stage->type==Stage::GEOMETRY)
629         {
630                 InterfaceBlockReference *ref = new InterfaceBlockReference;
631                 ref->name = "gl_in";
632
633                 BinaryExpression *subscript = new BinaryExpression;
634                 subscript->left = ref;
635                 subscript->oper = "[";
636                 subscript->right = pass.subscript;
637                 subscript->after = "]";
638
639                 MemberAccess *memacc = new MemberAccess;
640                 memacc->left = subscript;
641                 memacc->member = "gl_Position";
642
643                 insert_assignment("gl_Position", memacc);
644         }
645
646         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
647         {
648                 string out_name = change_prefix((*i)->name, out_prefix);
649                 generate_interface(**i, "out", out_name);
650
651                 VariableReference *ref = new VariableReference;
652                 ref->name = (*i)->name;
653                 if(pass.subscript)
654                 {
655                         BinaryExpression *subscript = new BinaryExpression;
656                         subscript->left = ref;
657                         subscript->oper = "[";
658                         subscript->right = pass.subscript;
659                         subscript->after = "]";
660                         insert_assignment(out_name, subscript);
661                 }
662                 else
663                         insert_assignment(out_name, ref);
664         }
665
666         nodes_to_remove.insert(&pass);
667 }
668
669
670 DeclarationReorderer::DeclarationReorderer():
671         kind(NO_DECLARATION)
672 { }
673
674 void DeclarationReorderer::visit(FunctionCall &call)
675 {
676         FunctionDeclaration *def = call.declaration;
677         if(def)
678                 def = def->definition;
679         if(def && !ordered_funcs.count(def))
680                 needed_funcs.insert(def);
681 }
682
683 void DeclarationReorderer::visit(Block &block)
684 {
685         if(block.parent)
686                 return TraversingVisitor::visit(block);
687
688         NodeList<Statement>::iterator struct_insert_point = block.body.end();
689         NodeList<Statement>::iterator variable_insert_point = block.body.end();
690         NodeList<Statement>::iterator function_insert_point = block.body.end();
691         unsigned unordered_func_count = 0;
692         bool ordered_any_funcs = false;
693
694         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
695         {
696                 kind = NO_DECLARATION;
697                 (*i)->visit(*this);
698
699                 bool moved = false;
700                 if(kind==STRUCT && struct_insert_point!=block.body.end())
701                 {
702                         block.body.insert(struct_insert_point, *i);
703                         moved = true;
704                 }
705                 else if(kind>STRUCT && struct_insert_point==block.body.end())
706                         struct_insert_point = i;
707
708                 if(kind==VARIABLE && variable_insert_point!=block.body.end())
709                 {
710                         block.body.insert(variable_insert_point, *i);
711                         moved = true;
712                 }
713                 else if(kind>VARIABLE && variable_insert_point==block.body.end())
714                         variable_insert_point = i;
715
716                 if(kind==FUNCTION)
717                 {
718                         if(function_insert_point==block.body.end())
719                                 function_insert_point = i;
720
721                         if(needed_funcs.empty())
722                         {
723                                 ordered_funcs.insert(i->get());
724                                 if(i!=function_insert_point)
725                                 {
726                                         block.body.insert(function_insert_point, *i);
727                                         moved = true;
728                                 }
729                                 else
730                                         ++function_insert_point;
731                                 ordered_any_funcs = true;
732                         }
733                         else
734                                 ++unordered_func_count;
735                 }
736
737                 if(moved)
738                 {
739                         if(function_insert_point==i)
740                                 ++function_insert_point;
741                         block.body.erase(i++);
742                 }
743                 else
744                         ++i;
745
746                 if(i==block.body.end() && unordered_func_count)
747                 {
748                         if(!ordered_any_funcs)
749                                 // A subset of the remaining functions forms a recursive loop
750                                 /* TODO pick a function and move it up, adding any necessary
751                                 declarations */
752                                 break;
753
754                         i = function_insert_point;
755                         unordered_func_count = 0;
756                 }
757         }
758 }
759
760 void DeclarationReorderer::visit(VariableDeclaration &var)
761 {
762         TraversingVisitor::visit(var);
763         kind = VARIABLE;
764 }
765
766 void DeclarationReorderer::visit(FunctionDeclaration &func)
767 {
768         needed_funcs.clear();
769         func.body.visit(*this);
770         needed_funcs.erase(&func);
771         kind = FUNCTION;
772 }
773
774 } // namespace SL
775 } // namespace GL
776 } // namespace Msp