]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Don't copy layouts to generated out interfaces
[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(FunctionDeclaration &func)
28 {
29         vector<FunctionDeclaration *> &decls = functions[func.name];
30         if(func.definition)
31         {
32                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
33                 {
34                         (*i)->definition = func.definition;
35                         (*i)->body.body.clear();
36                 }
37         }
38         decls.push_back(&func);
39 }
40
41 void DeclarationCombiner::visit(VariableDeclaration &var)
42 {
43         VariableDeclaration *&ptr = variables[var.name];
44         if(ptr)
45         {
46                 ptr->type = var.type;
47                 if(var.init_expression)
48                         ptr->init_expression = var.init_expression;
49                 if(var.layout)
50                 {
51                         if(ptr->layout)
52                         {
53                                 for(vector<Layout::Qualifier>::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i)
54                                 {
55                                         bool found = false;
56                                         for(vector<Layout::Qualifier>::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j)
57                                                 if(j->name==i->name)
58                                                 {
59                                                         j->has_value = i->value;
60                                                         j->value = i->value;
61                                                         found = true;
62                                                 }
63
64                                         if(!found)
65                                                 ptr->layout->qualifiers.push_back(*i);
66                                 }
67                         }
68                         else
69                                 ptr->layout = var.layout;
70                 }
71                 nodes_to_remove.insert(&var);
72         }
73         else
74                 ptr = &var;
75 }
76
77
78 ConstantSpecializer::ConstantSpecializer():
79         values(0)
80 { }
81
82 void ConstantSpecializer::apply(Stage &stage, const map<string, int> *v)
83 {
84         values = v;
85         stage.content.visit(*this);
86 }
87
88 void ConstantSpecializer::visit(VariableDeclaration &var)
89 {
90         bool specializable = false;
91         if(var.layout)
92         {
93                 vector<Layout::Qualifier> &qualifiers = var.layout->qualifiers;
94                 for(vector<Layout::Qualifier>::iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i)
95                         if(i->name=="constant_id")
96                         {
97                                 specializable = true;
98                                 if(values)
99                                         qualifiers.erase(i);
100                                 else if(i->value==-1)
101                                         i->value = hash32(var.name)&0x7FFFFFFF;
102                                 break;
103                         }
104
105                 if(qualifiers.empty())
106                         var.layout = 0;
107         }
108
109         if(specializable && values)
110         {
111                 map<string, int>::const_iterator i = values->find(var.name);
112                 if(i!=values->end())
113                 {
114                         RefPtr<Literal> literal = new Literal;
115                         if(var.type=="bool")
116                         {
117                                 literal->token = (i->second ? "true" : "false");
118                                 literal->value = static_cast<bool>(i->second);
119                         }
120                         else if(var.type=="int")
121                         {
122                                 literal->token = lexical_cast<string>(i->second);
123                                 literal->value = i->second;
124                         }
125                         var.init_expression = literal;
126                 }
127         }
128 }
129
130
131 void BlockResolver::enter(Block &block)
132 {
133         block.parent = current_block;
134 }
135
136
137 VariableResolver::VariableResolver():
138         stage(0),
139         builtins(0),
140         members(0),
141         record_target(false),
142         assignment_target(0),
143         self_referencing(false)
144 { }
145
146 void VariableResolver::apply(Stage &s)
147 {
148         stage = &s;
149         Stage *builtin_stage = get_builtins(s.type);
150         builtins = (builtin_stage ? &builtin_stage->content : 0);
151         s.content.visit(*this);
152 }
153
154 Block *VariableResolver::next_block(Block &block)
155 {
156         return block.parent ? block.parent : &block!=builtins ? builtins : 0;
157 }
158
159 void VariableResolver::enter(Block &block)
160 {
161         block.variables.clear();
162 }
163
164 void VariableResolver::visit(VariableReference &var)
165 {
166         var.declaration = 0;
167         members = 0;
168         for(Block *block=current_block; (!var.declaration && block); block=next_block(*block))
169         {
170                 map<string, VariableDeclaration *>::iterator i = block->variables.find(var.name);
171                 if(i!=block->variables.end())
172                         var.declaration = i->second;
173         }
174
175         if(var.declaration)
176         {
177                 if(var.declaration->type_declaration)
178                         members = &var.declaration->type_declaration->members.variables;
179         }
180         else
181         {
182                 const map<string, InterfaceBlock *> &blocks = stage->interface_blocks;
183                 map<string, InterfaceBlock *>::const_iterator i = blocks.find(var.name);
184                 if(i!=blocks.end() && i->second->instance_name==var.name)
185                 {
186                         iface_ref = new InterfaceBlockReference;
187                         iface_ref->name = var.name;
188                         iface_ref->declaration = i->second;
189                         members = &i->second->members.variables;
190                 }
191                 else
192                 {
193                         for(i=blocks.begin(); (!var.declaration && i!=blocks.end()); ++i)
194                                 if(i->second->instance_name.empty())
195                                 {
196                                         map<string, VariableDeclaration *>::iterator j = i->second->members.variables.find(var.name);
197                                         if(j!=i->second->members.variables.end())
198                                                 var.declaration = j->second;
199                                 }
200                 }
201         }
202
203         if(record_target)
204         {
205                 if(assignment_target)
206                 {
207                         record_target = false;
208                         assignment_target = 0;
209                 }
210                 else
211                         assignment_target = var.declaration;
212         }
213         else if(var.declaration && var.declaration==assignment_target)
214                 self_referencing = true;
215 }
216
217 void VariableResolver::visit(InterfaceBlockReference &iface)
218 {
219         iface.declaration = 0;
220         for(Block *block=current_block; block; block=next_block(*block))
221         {
222                 map<string, InterfaceBlock *>::iterator i = stage->interface_blocks.find(iface.name);
223                 if(i!=stage->interface_blocks.end())
224                 {
225                         iface.declaration = i->second;
226                         members = &i->second->members.variables;
227                         break;
228                 }
229         }
230 }
231
232 void VariableResolver::visit(MemberAccess &memacc)
233 {
234         members = 0;
235         iface_ref = 0;
236         memacc.left->visit(*this);
237
238         if(iface_ref)
239                 memacc.left = iface_ref;
240         iface_ref = 0;
241
242         memacc.declaration = 0;
243         if(members)
244         {
245                 map<string, VariableDeclaration *>::iterator i = members->find(memacc.member);
246                 if(i!=members->end())
247                 {
248                         memacc.declaration = i->second;
249                         if(i->second->type_declaration)
250                                 members = &i->second->type_declaration->members.variables;
251                 }
252                 else
253                         members = 0;
254         }
255 }
256
257 void VariableResolver::visit(BinaryExpression &binary)
258 {
259         if(binary.oper=="[")
260         {
261                 {
262                         SetForScope<bool> set(record_target, false);
263                         binary.right->visit(*this);
264                 }
265                 members = 0;
266                 iface_ref = 0;
267                 binary.left->visit(*this);
268                 if(iface_ref)
269                         binary.left = iface_ref;
270                 iface_ref = 0;
271         }
272         else
273         {
274                 TraversingVisitor::visit(binary);
275                 members = 0;
276         }
277 }
278
279 void VariableResolver::visit(Assignment &assign)
280 {
281         {
282                 SetFlag set(record_target);
283                 assignment_target = 0;
284                 assign.left->visit(*this);
285         }
286
287         self_referencing = false;
288         assign.right->visit(*this);
289
290         assign.self_referencing = (self_referencing || assign.oper!="=");
291         assign.target_declaration = assignment_target;
292 }
293
294 void VariableResolver::visit(StructDeclaration &strct)
295 {
296         TraversingVisitor::visit(strct);
297         stage->types[strct.name] = &strct;
298 }
299
300 void VariableResolver::visit(VariableDeclaration &var)
301 {
302         map<string, StructDeclaration *>::iterator i = stage->types.find(var.type);
303         if(i!=stage->types.end())
304                 var.type_declaration = i->second;
305
306         if(!block_interface.empty() && var.interface.empty())
307                 var.interface = block_interface;
308
309         TraversingVisitor::visit(var);
310         current_block->variables[var.name] = &var;
311 }
312
313 void VariableResolver::visit(InterfaceBlock &iface)
314 {
315         /* Block names can't be used for any other identifiers so we can put them
316         in the same map with instance names. */
317         stage->interface_blocks[iface.name] = &iface;
318         if(!iface.instance_name.empty())
319                 stage->interface_blocks[iface.instance_name] = &iface;
320
321         SetForScope<string> set_iface(block_interface, iface.interface);
322         TraversingVisitor::visit(iface);
323 }
324
325
326 void FunctionResolver::visit(FunctionCall &call)
327 {
328         map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
329         if(i!=functions.end())
330                 call.declaration = i->second.back();
331
332         TraversingVisitor::visit(call);
333 }
334
335 void FunctionResolver::visit(FunctionDeclaration &func)
336 {
337         vector<FunctionDeclaration *> &decls = functions[func.name];
338         if(func.definition)
339         {
340                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
341                         (*i)->definition = func.definition;
342                 decls.clear();
343                 decls.push_back(&func);
344         }
345         else if(!decls.empty() && decls.back()->definition)
346                 func.definition = decls.back()->definition;
347         else
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