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