]> git.tdb.fi Git - libs/gl.git/blob - source/glsl/generate.cpp
Some tweaks to GLSL debug output
[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->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         visit(stage.content);
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         visit(s.content);
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
362         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
363         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
364         if(i==prev_out.end())
365                 i = prev_out.find(in_prefix+var.name);
366         if(i!=prev_out.end())
367         {
368                 generate_interface(*i->second, "in", i->second->name);
369                 var.name = i->second->name;
370         }
371 }
372
373 void InterfaceGenerator::visit(VariableDeclaration &var)
374 {
375         if(var.interface=="out")
376         {
377                 if(current_block==&stage->content)
378                         stage->out_variables[var.name] = &var;
379                 else if(generate_interface(var, "out", change_prefix(var.name, string())))
380                 {
381                         nodes_to_remove.insert(&var);
382                         if(var.init_expression)
383                         {
384                                 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
385                                 stmt.source = var.source;
386                                 stmt.line = var.line;
387                                 return;
388                         }
389                 }
390         }
391         else if(var.interface=="in")
392         {
393                 stage->in_variables[var.name] = &var;
394                 if(var.linked_declaration)
395                         var.linked_declaration->linked_declaration = &var;
396                 else if(stage->previous)
397                 {
398                         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
399                         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
400                         if(i!=prev_out.end())
401                         {
402                                 var.linked_declaration = i->second;
403                                 i->second->linked_declaration = &var;
404                         }
405                 }
406         }
407
408         TraversingVisitor::visit(var);
409 }
410
411 void InterfaceGenerator::visit(Passthrough &pass)
412 {
413         vector<VariableDeclaration *> pass_vars;
414
415         for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
416                 pass_vars.push_back(i->second);
417
418         if(stage->previous)
419         {
420                 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
421                 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
422                 {
423                         bool linked = false;
424                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
425                                 linked = ((*j)->linked_declaration==i->second);
426
427                         if(!linked && generate_interface(*i->second, "in", i->second->name))
428                                 pass_vars.push_back(i->second);
429                 }
430         }
431
432         if(stage->type==Stage::GEOMETRY)
433         {
434                 VariableReference *ref = new VariableReference;
435                 ref->name = "gl_in";
436
437                 BinaryExpression *subscript = new BinaryExpression;
438                 subscript->left = ref;
439                 subscript->oper = "[";
440                 subscript->right = pass.subscript;
441                 subscript->after = "]";
442
443                 MemberAccess *memacc = new MemberAccess;
444                 memacc->left = subscript;
445                 memacc->member = "gl_Position";
446
447                 insert_assignment("gl_Position", memacc);
448         }
449
450         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
451         {
452                 string out_name = change_prefix((*i)->name, out_prefix);
453                 generate_interface(**i, "out", out_name);
454
455                 VariableReference *ref = new VariableReference;
456                 ref->name = (*i)->name;
457                 if(pass.subscript)
458                 {
459                         BinaryExpression *subscript = new BinaryExpression;
460                         subscript->left = ref;
461                         subscript->oper = "[";
462                         subscript->right = pass.subscript;
463                         subscript->after = "]";
464                         insert_assignment(out_name, subscript);
465                 }
466                 else
467                         insert_assignment(out_name, ref);
468         }
469
470         nodes_to_remove.insert(&pass);
471 }
472
473
474 DeclarationReorderer::DeclarationReorderer():
475         kind(NO_DECLARATION)
476 { }
477
478 void DeclarationReorderer::visit(FunctionCall &call)
479 {
480         FunctionDeclaration *def = call.declaration;
481         if(def)
482                 def = def->definition;
483         if(def && !ordered_funcs.count(def))
484                 needed_funcs.insert(def);
485 }
486
487 void DeclarationReorderer::visit(Block &block)
488 {
489         if(block.parent)
490                 return TraversingVisitor::visit(block);
491
492         NodeList<Statement>::iterator struct_insert_point = block.body.end();
493         NodeList<Statement>::iterator variable_insert_point = block.body.end();
494         NodeList<Statement>::iterator function_insert_point = block.body.end();
495         unsigned unordered_func_count = 0;
496         bool ordered_any_funcs = false;
497
498         for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
499         {
500                 kind = NO_DECLARATION;
501                 (*i)->visit(*this);
502
503                 bool moved = false;
504                 if(kind==STRUCT && struct_insert_point!=block.body.end())
505                 {
506                         block.body.insert(struct_insert_point, *i);
507                         moved = true;
508                 }
509                 else if(kind>STRUCT && struct_insert_point==block.body.end())
510                         struct_insert_point = i;
511
512                 if(kind==VARIABLE && variable_insert_point!=block.body.end())
513                 {
514                         block.body.insert(variable_insert_point, *i);
515                         moved = true;
516                 }
517                 else if(kind>VARIABLE && variable_insert_point==block.body.end())
518                         variable_insert_point = i;
519
520                 if(kind==FUNCTION)
521                 {
522                         if(function_insert_point==block.body.end())
523                                 function_insert_point = i;
524
525                         if(needed_funcs.empty())
526                         {
527                                 ordered_funcs.insert(i->get());
528                                 if(i!=function_insert_point)
529                                 {
530                                         block.body.insert(function_insert_point, *i);
531                                         moved = true;
532                                 }
533                                 else
534                                         ++function_insert_point;
535                                 ordered_any_funcs = true;
536                         }
537                         else
538                                 ++unordered_func_count;
539                 }
540
541                 if(moved)
542                 {
543                         if(function_insert_point==i)
544                                 ++function_insert_point;
545                         block.body.erase(i++);
546                 }
547                 else
548                         ++i;
549
550                 if(i==block.body.end() && unordered_func_count)
551                 {
552                         if(!ordered_any_funcs)
553                                 // A subset of the remaining functions forms a recursive loop
554                                 /* TODO pick a function and move it up, adding any necessary
555                                 declarations */
556                                 break;
557
558                         i = function_insert_point;
559                         unordered_func_count = 0;
560                 }
561         }
562 }
563
564 void DeclarationReorderer::visit(VariableDeclaration &var)
565 {
566         TraversingVisitor::visit(var);
567         kind = VARIABLE;
568 }
569
570 void DeclarationReorderer::visit(FunctionDeclaration &func)
571 {
572         needed_funcs.clear();
573         func.body.visit(*this);
574         needed_funcs.erase(&func);
575         kind = FUNCTION;
576 }
577
578 } // namespace SL
579 } // namespace GL
580 } // namespace Msp