]> git.tdb.fi Git - libs/gl.git/blob - source/programcompiler.cpp
Support precision qualifiers in shaders
[libs/gl.git] / source / programcompiler.cpp
1 #include <msp/core/raii.h>
2 #include <msp/strings/format.h>
3 #include <msp/strings/utils.h>
4 #include "error.h"
5 #include "program.h"
6 #include "programcompiler.h"
7 #include "resources.h"
8 #include "shader.h"
9
10 using namespace std;
11
12 namespace {
13
14 const char builtins_src[] =
15         "////// vertex\n"
16         "out gl_PerVertex {\n"
17         "  vec4 gl_Position;\n"
18         "  float gl_ClipDistance[];\n"
19         "};"
20         "////// geometry\n"
21         "in gl_PerVertex {\n"
22         "  vec4 gl_Position;\n"
23         "  float gl_ClipDistance[];\n"
24         "} gl_in[];\n"
25         "out gl_PerVertex {\n"
26         "  vec4 gl_Position;\n"
27         "  float gl_ClipDistance[];\n"
28         "};\n";
29
30 }
31
32 namespace Msp {
33 namespace GL {
34
35 using namespace ProgramSyntax;
36
37 ProgramCompiler::ProgramCompiler():
38         resources(0),
39         module(0)
40 { }
41
42 void ProgramCompiler::compile(const string &source)
43 {
44         resources = 0;
45         module = &parser.parse(source);
46         process();
47 }
48
49 void ProgramCompiler::compile(IO::Base &io, Resources *res)
50 {
51         resources = res;
52         module = &parser.parse(io);
53         process();
54 }
55
56 void ProgramCompiler::add_shaders(Program &program)
57 {
58         if(!module)
59                 throw invalid_operation("ProgramCompiler::add_shaders");
60
61         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
62         {
63                 if(i->type==VERTEX)
64                 {
65                         program.attach_shader_owned(new VertexShader(apply<Formatter>(*i)));
66                         for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
67                                 program.bind_attribute(j->second, j->first);
68                 }
69                 else if(i->type==GEOMETRY)
70                         program.attach_shader_owned(new GeometryShader(apply<Formatter>(*i)));
71                 else if(i->type==FRAGMENT)
72                 {
73                         program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
74                         for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
75                                 program.bind_fragment_data(j->second, j->first);
76                 }
77         }
78 }
79
80 Module *ProgramCompiler::create_builtins_module()
81 {
82         ProgramParser parser;
83         Module *module = new Module(parser.parse(builtins_src));
84         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
85         {
86                 VariableResolver resolver;
87                 i->content.visit(resolver);
88                 for(map<string, VariableDeclaration *>::iterator j=i->content.variables.begin(); j!=i->content.variables.end(); ++j)
89                         j->second->linked_declaration = j->second;
90         }
91         return module;
92 }
93
94 Module &ProgramCompiler::get_builtins_module()
95 {
96         static RefPtr<Module> builtins_module = create_builtins_module();
97         return *builtins_module;
98 }
99
100 Stage *ProgramCompiler::get_builtins(StageType type)
101 {
102         Module &module = get_builtins_module();
103         for(list<Stage>::iterator i=module.stages.begin(); i!=module.stages.end(); ++i)
104                 if(i->type==type)
105                         return &*i;
106         return 0;
107 }
108
109 void ProgramCompiler::process()
110 {
111         list<Import *> imports = apply<NodeGatherer<Import> >(module->shared);
112         for(list<Import *>::iterator i=imports.end(); i!=imports.begin(); )
113                 import((*--i)->module);
114         apply<NodeRemover>(module->shared, set<Node *>(imports.begin(), imports.end()));
115
116         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
117                 generate(*i);
118         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); )
119         {
120                 if(optimize(*i))
121                         i = module->stages.begin();
122                 else
123                         ++i;
124         }
125         for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
126                 finalize(*i);
127 }
128
129 void ProgramCompiler::import(const string &name)
130 {
131         string fn = name+".glsl";
132         RefPtr<IO::Seekable> io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn));
133         if(!io)
134                 throw runtime_error(format("module %s not found", name));
135         ProgramParser import_parser;
136         Module &imported_module = import_parser.parse(*io);
137
138         inject_block(module->shared.content, imported_module.shared.content);
139         apply<DeclarationCombiner>(module->shared);
140         for(list<Stage>::iterator i=imported_module.stages.begin(); i!=imported_module.stages.end(); ++i)
141         {
142                 list<Stage>::iterator j;
143                 for(j=module->stages.begin(); (j!=module->stages.end() && j->type<i->type); ++j) ;
144                 if(j==module->stages.end() || j->type>i->type)
145                 {
146                         j = module->stages.insert(j, *i);
147                         list<Stage>::iterator k = j;
148                         if(++k!=module->stages.end())
149                                 k->previous = &*j;
150                         if(j!=module->stages.begin())
151                                 j->previous = &*--(k=j);
152                 }
153                 else
154                 {
155                         inject_block(j->content, i->content);
156                         apply<DeclarationCombiner>(*j);
157                 }
158         }
159 }
160
161 void ProgramCompiler::generate(Stage &stage)
162 {
163         inject_block(stage.content, module->shared.content);
164
165         apply<DeclarationReorderer>(stage);
166         apply<FunctionResolver>(stage);
167         apply<VariableResolver>(stage);
168         apply<InterfaceGenerator>(stage);
169         apply<VariableResolver>(stage);
170         apply<VariableRenamer>(stage);
171         apply<DeclarationReorderer>(stage);
172         apply<LegacyConverter>(stage);
173 }
174
175 bool ProgramCompiler::optimize(Stage &stage)
176 {
177         apply<ConstantConditionEliminator>(stage);
178
179         set<FunctionDeclaration *> inlineable = apply<InlineableFunctionLocator>(stage);
180         apply<FunctionInliner>(stage, inlineable);
181
182         set<Node *> unused = apply<UnusedVariableLocator>(stage);
183         set<Node *> unused2 = apply<UnusedFunctionLocator>(stage);
184         unused.insert(unused2.begin(), unused2.end());
185         apply<NodeRemover>(stage, unused);
186
187         return !unused.empty();
188 }
189
190 void ProgramCompiler::finalize(Stage &stage)
191 {
192         if(get_gl_api()==OPENGL_ES2)
193                 apply<DefaultPrecisionGenerator>(stage);
194         else
195                 apply<PrecisionRemover>(stage);
196 }
197
198 void ProgramCompiler::inject_block(Block &target, const Block &source)
199 {
200         list<RefPtr<Node> >::iterator insert_point = target.body.begin();
201         for(list<RefPtr<Node> >::const_iterator i=source.body.begin(); i!=source.body.end(); ++i)
202                 target.body.insert(insert_point, (*i)->clone());
203 }
204
205 template<typename T>
206 typename T::ResultType ProgramCompiler::apply(Stage &stage)
207 {
208         T visitor;
209         visitor.apply(stage);
210         return visitor.get_result();
211 }
212
213 template<typename T, typename A>
214 typename T::ResultType ProgramCompiler::apply(Stage &stage, const A &arg)
215 {
216         T visitor(arg);
217         visitor.apply(stage);
218         return visitor.get_result();
219 }
220
221
222 ProgramCompiler::Visitor::Visitor():
223         stage(0)
224 { }
225
226 void ProgramCompiler::Visitor::apply(Stage &s)
227 {
228         SetForScope<Stage *> set(stage, &s);
229         stage->content.visit(*this);
230 }
231
232
233 ProgramCompiler::Formatter::Formatter():
234         indent(0),
235         parameter_list(false),
236         else_if(0)
237 { }
238
239 void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
240 {
241         GLApi api = get_gl_api();
242         const Version &ver = s.required_version;
243
244         if(ver)
245         {
246                 formatted += format("#version %d%02d", ver.major, ver.minor);
247                 if(api==OPENGL_ES2 && ver>=Version(3, 0))
248                         formatted += " es";
249                 formatted += '\n';
250         }
251
252         Visitor::apply(s);
253 }
254
255 void ProgramCompiler::Formatter::visit(Literal &literal)
256 {
257         formatted += literal.token;
258 }
259
260 void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr)
261 {
262         formatted += '(';
263         parexpr.expression->visit(*this);
264         formatted += ')';
265 }
266
267 void ProgramCompiler::Formatter::visit(VariableReference &var)
268 {
269         formatted += var.name;
270 }
271
272 void ProgramCompiler::Formatter::visit(MemberAccess &memacc)
273 {
274         memacc.left->visit(*this);
275         formatted += format(".%s", memacc.member);
276 }
277
278 void ProgramCompiler::Formatter::visit(UnaryExpression &unary)
279 {
280         if(unary.prefix)
281                 formatted += unary.oper;
282         unary.expression->visit(*this);
283         if(!unary.prefix)
284                 formatted += unary.oper;
285 }
286
287 void ProgramCompiler::Formatter::visit(BinaryExpression &binary)
288 {
289         binary.left->visit(*this);
290         formatted += binary.oper;
291         binary.right->visit(*this);
292         formatted += binary.after;
293 }
294
295 void ProgramCompiler::Formatter::visit(Assignment &assign)
296 {
297         assign.left->visit(*this);
298         formatted += format(" %s ", assign.oper);
299         assign.right->visit(*this);
300 }
301
302 void ProgramCompiler::Formatter::visit(FunctionCall &call)
303 {
304         formatted += format("%s(", call.name);
305         for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
306         {
307                 if(i!=call.arguments.begin())
308                         formatted += ", ";
309                 (*i)->visit(*this);
310         }
311         formatted += ')';
312 }
313
314 void ProgramCompiler::Formatter::visit(ExpressionStatement &expr)
315 {
316         expr.expression->visit(*this);
317         formatted += ';';
318 }
319
320 void ProgramCompiler::Formatter::visit(Block &block)
321 {
322         if(else_if)
323                 --else_if;
324
325         unsigned brace_indent = indent;
326         bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
327         if(use_braces)
328                 formatted += format("%s{\n", string(brace_indent*2, ' '));
329
330         SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
331         string spaces(indent*2, ' ');
332         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
333         {
334                 if(i!=block.body.begin())
335                         formatted += '\n';
336                 formatted += spaces;
337                 (*i)->visit(*this);
338                 else_if = 0;
339         }
340
341         if(use_braces)
342                 formatted += format("\n%s}", string(brace_indent*2, ' '));
343 }
344
345 void ProgramCompiler::Formatter::visit(Import &import)
346 {
347         formatted += format("import %s;", import.module);
348 }
349
350 void ProgramCompiler::Formatter::visit(Precision &prec)
351 {
352         formatted += format("precision %s %s;", prec.precision, prec.type);
353 }
354
355 void ProgramCompiler::Formatter::visit(Layout &layout)
356 {
357         formatted += "layout(";
358         for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
359         {
360                 if(i!=layout.qualifiers.begin())
361                         formatted += ", ";
362                 formatted += i->identifier;
363                 if(!i->value.empty())
364                         formatted += format("=%s", i->value);
365         }
366         formatted += ')';
367 }
368
369 void ProgramCompiler::Formatter::visit(InterfaceLayout &layout)
370 {
371         layout.layout.visit(*this);
372         formatted += format(" %s;", layout.interface);
373 }
374
375 void ProgramCompiler::Formatter::visit(StructDeclaration &strct)
376 {
377         formatted += format("struct %s\n", strct.name);
378         strct.members.visit(*this);
379         formatted += ';';
380 }
381
382 void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
383 {
384         if(var.layout)
385         {
386                 var.layout->visit(*this);
387                 formatted += ' ';
388         }
389         if(var.constant)
390                 formatted += "const ";
391         if(!var.sampling.empty())
392                 formatted += format("%s ", var.sampling);
393         if(!var.interface.empty() && var.interface!=block_interface)
394         {
395                 string interface = var.interface;
396                 if(stage->required_version<Version(1, 30))
397                 {
398                         if(stage->type==VERTEX && var.interface=="in")
399                                 interface = "attribute";
400                         else if((stage->type==VERTEX && var.interface=="out") || (stage->type==FRAGMENT && var.interface=="in"))
401                                 interface = "varying";
402                 }
403                 formatted += format("%s ", interface);
404         }
405         if(!var.precision.empty())
406                 formatted += format("%s ", var.precision);
407         formatted += format("%s %s", var.type, var.name);
408         if(var.array)
409         {
410                 formatted += '[';
411                 if(var.array_size)
412                         var.array_size->visit(*this);
413                 formatted += ']';
414         }
415         if(var.init_expression)
416         {
417                 formatted += " = ";
418                 var.init_expression->visit(*this);
419         }
420         if(!parameter_list)
421                 formatted += ';';
422 }
423
424 void ProgramCompiler::Formatter::visit(InterfaceBlock &iface)
425 {
426         SetForScope<string> set(block_interface, iface.interface);
427         formatted += format("%s %s\n", iface.interface, iface.name);
428         iface.members.visit(*this);
429         formatted += ';';
430 }
431
432 void ProgramCompiler::Formatter::visit(FunctionDeclaration &func)
433 {
434         formatted += format("%s %s(", func.return_type, func.name);
435         for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
436         {
437                 if(i!=func.parameters.begin())
438                         formatted += ", ";
439                 SetFlag set(parameter_list);
440                 (*i)->visit(*this);
441         }
442         formatted += ')';
443         if(func.definition==&func)
444         {
445                 formatted += '\n';
446                 func.body.visit(*this);
447         }
448         else
449                 formatted += ';';
450 }
451
452 void ProgramCompiler::Formatter::visit(Conditional &cond)
453 {
454         if(else_if)
455                 formatted.replace(formatted.rfind('\n'), string::npos, 1, ' ');
456
457         indent -= else_if;
458
459         formatted += "if(";
460         cond.condition->visit(*this);
461         formatted += ")\n";
462
463         cond.body.visit(*this);
464         if(!cond.else_body.body.empty())
465         {
466                 formatted += format("\n%selse\n", string(indent*2, ' '));
467                 SetForScope<unsigned> set(else_if, 2);
468                 cond.else_body.visit(*this);
469         }
470 }
471
472 void ProgramCompiler::Formatter::visit(Iteration &iter)
473 {
474         formatted += "for(";
475         iter.init_statement->visit(*this);
476         formatted += ' ';
477         iter.condition->visit(*this);
478         formatted += "; ";
479         iter.loop_expression->visit(*this);
480         formatted += ")\n";
481         iter.body.visit(*this);
482 }
483
484 void ProgramCompiler::Formatter::visit(Return &ret)
485 {
486         formatted += "return ";
487         ret.expression->visit(*this);
488         formatted += ';';
489 }
490
491 void ProgramCompiler::Formatter::visit(Jump &jump)
492 {
493         formatted += jump.keyword;
494         formatted += ';';
495 }
496
497
498 ProgramCompiler::DeclarationCombiner::DeclarationCombiner():
499         toplevel(true),
500         remove_node(false)
501 { }
502
503 void ProgramCompiler::DeclarationCombiner::visit(Block &block)
504 {
505         if(!toplevel)
506                 return;
507
508         SetForScope<bool> set(toplevel, false);
509         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
510         {
511                 remove_node = false;
512                 (*i)->visit(*this);
513                 if(remove_node)
514                         block.body.erase(i++);
515                 else
516                         ++i;
517         }
518 }
519
520 void ProgramCompiler::DeclarationCombiner::visit(FunctionDeclaration &func)
521 {
522         vector<FunctionDeclaration *> &decls = functions[func.name];
523         if(func.definition)
524         {
525                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
526                 {
527                         (*i)->definition = func.definition;
528                         (*i)->body.body.clear();
529                 }
530         }
531         decls.push_back(&func);
532 }
533
534 void ProgramCompiler::DeclarationCombiner::visit(VariableDeclaration &var)
535 {
536         VariableDeclaration *&ptr = variables[var.name];
537         if(ptr)
538         {
539                 ptr->type = var.type;
540                 if(var.init_expression)
541                         ptr->init_expression = var.init_expression;
542                 remove_node = true;
543         }
544         else
545                 ptr = &var;
546 }
547
548
549 ProgramCompiler::VariableResolver::VariableResolver():
550         anonymous(false),
551         record_target(false),
552         assignment_target(0),
553         self_referencing(false)
554 { }
555
556 void ProgramCompiler::VariableResolver::apply(Stage &s)
557 {
558         SetForScope<Stage *> set(stage, &s);
559         Stage *builtins = get_builtins(stage->type);
560         if(builtins)
561                 blocks.push_back(&builtins->content);
562         stage->content.visit(*this);
563         if(builtins)
564                 blocks.pop_back();
565 }
566
567 void ProgramCompiler::VariableResolver::visit(Block &block)
568 {
569         blocks.push_back(&block);
570         block.variables.clear();
571         TraversingVisitor::visit(block);
572         blocks.pop_back();
573 }
574
575 void ProgramCompiler::VariableResolver::visit(VariableReference &var)
576 {
577         var.declaration = 0;
578         type = 0;
579         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
580         {
581                 --i;
582                 map<string, VariableDeclaration *>::iterator j = (*i)->variables.find(var.name);
583                 if(j!=(*i)->variables.end())
584                 {
585                         var.declaration = j->second;
586                         type = j->second->type_declaration;
587                         break;
588                 }
589         }
590
591         if(record_target)
592         {
593                 if(assignment_target)
594                 {
595                         record_target = false;
596                         assignment_target = 0;
597                 }
598                 else
599                         assignment_target = var.declaration;
600         }
601         else if(var.declaration && var.declaration==assignment_target)
602                 self_referencing = true;
603 }
604
605 void ProgramCompiler::VariableResolver::visit(MemberAccess &memacc)
606 {
607         type = 0;
608         TraversingVisitor::visit(memacc);
609         memacc.declaration = 0;
610         if(type)
611         {
612                 map<string, VariableDeclaration *>::iterator i = type->members.variables.find(memacc.member);
613                 if(i!=type->members.variables.end())
614                 {
615                         memacc.declaration = i->second;
616                         type = i->second->type_declaration;
617                 }
618                 else
619                         type = 0;
620         }
621 }
622
623 void ProgramCompiler::VariableResolver::visit(BinaryExpression &binary)
624 {
625         if(binary.oper=="[")
626         {
627                 {
628                         SetForScope<bool> set(record_target, false);
629                         binary.right->visit(*this);
630                 }
631                 type = 0;
632                 binary.left->visit(*this);
633         }
634         else
635         {
636                 TraversingVisitor::visit(binary);
637                 type = 0;
638         }
639 }
640
641 void ProgramCompiler::VariableResolver::visit(Assignment &assign)
642 {
643         {
644                 SetFlag set(record_target);
645                 assignment_target = 0;
646                 assign.left->visit(*this);
647         }
648
649         self_referencing = false;
650         assign.right->visit(*this);
651
652         assign.self_referencing = (self_referencing || assign.oper!="=");
653         assign.target_declaration = assignment_target;
654 }
655
656 void ProgramCompiler::VariableResolver::visit(StructDeclaration &strct)
657 {
658         TraversingVisitor::visit(strct);
659         blocks.back()->types[strct.name] = &strct;
660 }
661
662 void ProgramCompiler::VariableResolver::visit(VariableDeclaration &var)
663 {
664         for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
665         {
666                 --i;
667                 map<string, StructDeclaration *>::iterator j = (*i)->types.find(var.type);
668                 if(j!=(*i)->types.end())
669                         var.type_declaration = j->second;
670         }
671
672         if(!block_interface.empty() && var.interface.empty())
673                 var.interface = block_interface;
674
675         TraversingVisitor::visit(var);
676         blocks.back()->variables[var.name] = &var;
677         if(anonymous && blocks.size()>1)
678                 blocks[blocks.size()-2]->variables[var.name] = &var;
679 }
680
681 void ProgramCompiler::VariableResolver::visit(InterfaceBlock &iface)
682 {
683         SetFlag set(anonymous);
684         SetForScope<string> set2(block_interface, iface.interface);
685         TraversingVisitor::visit(iface);
686 }
687
688
689 void ProgramCompiler::FunctionResolver::visit(FunctionCall &call)
690 {
691         map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
692         if(i!=functions.end())
693                 call.declaration = i->second.back();
694
695         TraversingVisitor::visit(call);
696 }
697
698 void ProgramCompiler::FunctionResolver::visit(FunctionDeclaration &func)
699 {
700         vector<FunctionDeclaration *> &decls = functions[func.name];
701         if(func.definition)
702         {
703                 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
704                         (*i)->definition = func.definition;
705                 decls.clear();
706                 decls.push_back(&func);
707         }
708         else if(!decls.empty() && decls.back()->definition)
709                 func.definition = decls.back()->definition;
710         else
711                 decls.push_back(&func);
712
713         TraversingVisitor::visit(func);
714 }
715
716
717 ProgramCompiler::BlockModifier::BlockModifier():
718         remove_node(false)
719 { }
720
721 void ProgramCompiler::BlockModifier::flatten_block(Block &block)
722 {
723         insert_nodes.insert(insert_nodes.end(), block.body.begin(), block.body.end());
724         remove_node = true;
725 }
726
727 void ProgramCompiler::BlockModifier::apply_and_increment(Block &block, list<RefPtr<Node> >::iterator &i)
728 {
729         block.body.insert(i, insert_nodes.begin(), insert_nodes.end());
730         insert_nodes.clear();
731
732         if(remove_node)
733                 block.body.erase(i++);
734         else
735                 ++i;
736         remove_node = false;
737 }
738
739 void ProgramCompiler::BlockModifier::visit(Block &block)
740 {
741         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
742         {
743                 (*i)->visit(*this);
744                 apply_and_increment(block, i);
745         }
746 }
747
748
749 ProgramCompiler::InterfaceGenerator::InterfaceGenerator():
750         scope_level(0)
751 { }
752
753 string ProgramCompiler::InterfaceGenerator::get_out_prefix(StageType type)
754 {
755         if(type==VERTEX)
756                 return "_vs_out_";
757         else if(type==GEOMETRY)
758                 return "_gs_out_";
759         else
760                 return string();
761 }
762
763 void ProgramCompiler::InterfaceGenerator::apply(Stage &s)
764 {
765         SetForScope<Stage *> set(stage, &s);
766         if(stage->previous)
767                 in_prefix = get_out_prefix(stage->previous->type);
768         out_prefix = get_out_prefix(stage->type);
769         stage->content.visit(*this);
770 }
771
772 void ProgramCompiler::InterfaceGenerator::visit(Block &block)
773 {
774         SetForScope<unsigned> set(scope_level, scope_level+1);
775         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
776         {
777                 (*i)->visit(*this);
778
779                 if(scope_level==1)
780                 {
781                         for(map<string, RefPtr<VariableDeclaration> >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
782                         {
783                                 list<RefPtr<Node> >::iterator k = block.body.insert(i, j->second);
784                                 (*k)->visit(*this);
785                         }
786                         iface_declarations.clear();
787                 }
788
789                 apply_and_increment(block, i);
790         }
791 }
792
793 string ProgramCompiler::InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
794 {
795         unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
796         return prefix+name.substr(offset);
797 }
798
799 bool ProgramCompiler::InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
800 {
801         const map<string, VariableDeclaration *> &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables);
802         if(stage_vars.count(name) || iface_declarations.count(name))
803                 return false;
804
805         VariableDeclaration* iface_var = new VariableDeclaration;
806         iface_var->sampling = var.sampling;
807         iface_var->interface = iface;
808         iface_var->type = var.type;
809         iface_var->type_declaration = var.type_declaration;
810         iface_var->name = name;
811         if(stage->type==GEOMETRY)
812                 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
813         else
814                 iface_var->array = var.array;
815         if(iface_var->array)
816                 iface_var->array_size = var.array_size;
817         if(iface=="in")
818                 iface_var->linked_declaration = &var;
819         iface_declarations[name] = iface_var;
820
821         return true;
822 }
823
824 void ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right)
825 {
826         Assignment *assign = new Assignment;
827         VariableReference *ref = new VariableReference;
828         ref->name = left;
829         assign->left = ref;
830         assign->oper = "=";
831         assign->right = right;
832
833         ExpressionStatement *stmt = new ExpressionStatement;
834         stmt->expression = assign;
835         insert_nodes.push_back(stmt);
836 }
837
838 void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var)
839 {
840         if(var.declaration || !stage->previous)
841                 return;
842         if(iface_declarations.count(var.name))
843                 return;
844
845         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
846         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
847         if(i==prev_out.end())
848                 i = prev_out.find(in_prefix+var.name);
849         if(i!=prev_out.end())
850                 generate_interface(*i->second, "in", var.name);
851 }
852
853 void ProgramCompiler::InterfaceGenerator::visit(VariableDeclaration &var)
854 {
855         if(var.interface=="out")
856         {
857                 if(scope_level==1)
858                         stage->out_variables[var.name] = &var;
859                 else if(generate_interface(var, "out", change_prefix(var.name, string())))
860                 {
861                         remove_node = true;
862                         if(var.init_expression)
863                                 insert_assignment(var.name, var.init_expression->clone());
864                 }
865         }
866         else if(var.interface=="in")
867         {
868                 stage->in_variables[var.name] = &var;
869                 if(var.linked_declaration)
870                         var.linked_declaration->linked_declaration = &var;
871                 else if(stage->previous)
872                 {
873                         const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
874                         map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
875                         if(i!=prev_out.end())
876                         {
877                                 var.linked_declaration = i->second;
878                                 i->second->linked_declaration = &var;
879                         }
880                 }
881         }
882
883         TraversingVisitor::visit(var);
884 }
885
886 void ProgramCompiler::InterfaceGenerator::visit(Passthrough &pass)
887 {
888         vector<VariableDeclaration *> pass_vars;
889
890         for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
891                 pass_vars.push_back(i->second);
892         for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
893                 if(i->second->interface=="in")
894                         pass_vars.push_back(i->second.get());
895
896         if(stage->previous)
897         {
898                 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
899                 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
900                 {
901                         bool linked = false;
902                         for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
903                                 linked = ((*j)->linked_declaration==i->second);
904
905                         if(!linked && generate_interface(*i->second, "in", i->second->name))
906                                 pass_vars.push_back(i->second);
907                 }
908         }
909
910         if(stage->type==GEOMETRY)
911         {
912                 VariableReference *ref = new VariableReference;
913                 ref->name = "gl_in";
914
915                 BinaryExpression *subscript = new BinaryExpression;
916                 subscript->left = ref;
917                 subscript->oper = "[";
918                 subscript->right = pass.subscript;
919                 subscript->after = "]";
920
921                 MemberAccess *memacc = new MemberAccess;
922                 memacc->left = subscript;
923                 memacc->member = "gl_Position";
924
925                 insert_assignment("gl_Position", memacc);
926         }
927
928         for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
929         {
930                 string out_name = change_prefix((*i)->name, out_prefix);
931                 generate_interface(**i, "out", out_name);
932
933                 VariableReference *ref = new VariableReference;
934                 ref->name = (*i)->name;
935                 if(pass.subscript)
936                 {
937                         BinaryExpression *subscript = new BinaryExpression;
938                         subscript->left = ref;
939                         subscript->oper = "[";
940                         subscript->right = pass.subscript;
941                         subscript->after = "]";
942                         insert_assignment(out_name, subscript);
943                 }
944                 else
945                         insert_assignment(out_name, ref);
946         }
947
948         remove_node = true;
949 }
950
951
952 void ProgramCompiler::VariableRenamer::visit(VariableReference &var)
953 {
954         if(var.declaration)
955                 var.name = var.declaration->name;
956 }
957
958 void ProgramCompiler::VariableRenamer::visit(VariableDeclaration &var)
959 {
960         if(var.linked_declaration)
961                 var.name = var.linked_declaration->name;
962         TraversingVisitor::visit(var);
963 }
964
965
966 ProgramCompiler::DeclarationReorderer::DeclarationReorderer():
967         kind(NO_DECLARATION)
968 { }
969
970 void ProgramCompiler::DeclarationReorderer::visit(Block &block)
971 {
972         list<RefPtr<Node> >::iterator struct_insert_point = block.body.end();
973         list<RefPtr<Node> >::iterator variable_insert_point = block.body.end();
974
975         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
976         {
977                 kind = NO_DECLARATION;
978                 (*i)->visit(*this);
979
980                 bool moved = false;
981                 if(kind==STRUCT && struct_insert_point!=block.body.end())
982                 {
983                         block.body.insert(struct_insert_point, *i);
984                         moved = true;
985                 }
986                 else if(kind>STRUCT && struct_insert_point==block.body.end())
987                         struct_insert_point = i;
988
989                 if(kind==VARIABLE && variable_insert_point!=block.body.end())
990                 {
991                         block.body.insert(variable_insert_point, *i);
992                         moved = true;
993                 }
994                 else if(kind>VARIABLE && variable_insert_point==block.body.end())
995                         variable_insert_point = i;
996
997                 if(moved)
998                         block.body.erase(i++);
999                 else
1000                         ++i;
1001         }
1002 }
1003
1004
1005 ProgramCompiler::InlineableFunctionLocator::InlineableFunctionLocator():
1006         in_function(0)
1007 { }
1008
1009 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionCall &call)
1010 {
1011         FunctionDeclaration *def = call.declaration;
1012         if(def && def->definition!=def)
1013                 def = def->definition;
1014
1015         if(def)
1016         {
1017                 unsigned &count = refcounts[def];
1018                 ++count;
1019                 if(count>1 || def==in_function)
1020                         inlineable.erase(def);
1021         }
1022
1023         TraversingVisitor::visit(call);
1024 }
1025
1026 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionDeclaration &func)
1027 {
1028         unsigned &count = refcounts[func.definition];
1029         if(!count && func.parameters.empty())
1030                 inlineable.insert(func.definition);
1031
1032         SetForScope<FunctionDeclaration *> set(in_function, &func);
1033         TraversingVisitor::visit(func);
1034 }
1035
1036
1037 ProgramCompiler::FunctionInliner::FunctionInliner():
1038         extract_result(0)
1039 { }
1040
1041 ProgramCompiler::FunctionInliner::FunctionInliner(const set<FunctionDeclaration *> &in):
1042         inlineable(in),
1043         extract_result(0)
1044 { }
1045
1046 void ProgramCompiler::FunctionInliner::visit_and_inline(RefPtr<Expression> &ptr)
1047 {
1048         inline_result = 0;
1049         ptr->visit(*this);
1050         if(inline_result)
1051                 ptr = inline_result;
1052 }
1053
1054 void ProgramCompiler::FunctionInliner::visit(Block &block)
1055 {
1056         if(extract_result)
1057                 --extract_result;
1058
1059         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); ++i)
1060         {
1061                 (*i)->visit(*this);
1062                 if(extract_result)
1063                         --extract_result;
1064         }
1065 }
1066
1067 void ProgramCompiler::FunctionInliner::visit(UnaryExpression &unary)
1068 {
1069         visit_and_inline(unary.expression);
1070         inline_result = 0;
1071 }
1072
1073 void ProgramCompiler::FunctionInliner::visit(BinaryExpression &binary)
1074 {
1075         visit_and_inline(binary.left);
1076         visit_and_inline(binary.right);
1077         inline_result = 0;
1078 }
1079
1080 void ProgramCompiler::FunctionInliner::visit(FunctionCall &call)
1081 {
1082         for(vector<RefPtr<Expression> >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
1083                 visit_and_inline(*i);
1084
1085         FunctionDeclaration *def = call.declaration;
1086         if(def && def->definition!=def)
1087                 def = def->definition;
1088
1089         if(def && inlineable.count(def))
1090         {
1091                 extract_result = 2;
1092                 def->visit(*this);
1093         }
1094         else
1095                 inline_result = 0;
1096 }
1097
1098 void ProgramCompiler::FunctionInliner::visit(Return &ret)
1099 {
1100         TraversingVisitor::visit(ret);
1101
1102         if(extract_result)
1103                 inline_result = ret.expression->clone();
1104 }
1105
1106
1107 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
1108         variable_values(0),
1109         result(0.0f),
1110         result_valid(false)
1111 { }
1112
1113 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v):
1114         variable_values(&v),
1115         result(0.0f),
1116         result_valid(false)
1117 { }
1118
1119 void ProgramCompiler::ExpressionEvaluator::visit(Literal &literal)
1120 {
1121         if(literal.token=="true")
1122                 result = 1.0f;
1123         else if(literal.token=="false")
1124                 result = 0.0f;
1125         else
1126                 result = lexical_cast<float>(literal.token);
1127         result_valid = true;
1128 }
1129
1130 void ProgramCompiler::ExpressionEvaluator::visit(ParenthesizedExpression &parexp)
1131 {
1132         parexp.expression->visit(*this);
1133 }
1134
1135 void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var)
1136 {
1137         if(!var.declaration)
1138                 return;
1139
1140         if(variable_values)
1141         {
1142                 ValueMap::const_iterator i = variable_values->find(var.declaration);
1143                 if(i!=variable_values->end())
1144                         i->second->visit(*this);
1145         }
1146         else if(var.declaration->init_expression)
1147                 var.declaration->init_expression->visit(*this);
1148 }
1149
1150 void ProgramCompiler::ExpressionEvaluator::visit(UnaryExpression &unary)
1151 {
1152         result_valid = false;
1153         unary.expression->visit(*this);
1154         if(!result_valid)
1155                 return;
1156
1157         if(unary.oper=="!")
1158                 result = !result;
1159         else
1160                 result_valid = false;
1161 }
1162
1163 void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary)
1164 {
1165         result_valid = false;
1166         binary.left->visit(*this);
1167         if(!result_valid)
1168                 return;
1169
1170         float left_result = result;
1171         result_valid = false;
1172         binary.right->visit(*this);
1173         if(!result_valid)
1174                 return;
1175
1176         if(binary.oper=="<")
1177                 result = (left_result<result);
1178         else if(binary.oper=="<=")
1179                 result = (left_result<=result);
1180         else if(binary.oper==">")
1181                 result = (left_result>result);
1182         else if(binary.oper==">=")
1183                 result = (left_result>=result);
1184         else if(binary.oper=="==")
1185                 result = (left_result==result);
1186         else if(binary.oper=="!=")
1187                 result = (left_result!=result);
1188         else if(binary.oper=="&&")
1189                 result = (left_result && result);
1190         else if(binary.oper=="||")
1191                 result = (left_result || result);
1192         else
1193                 result_valid = false;
1194 }
1195
1196
1197 ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
1198         scope_level(0)
1199 { }
1200
1201 void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
1202 {
1203         SetForScope<unsigned> set(scope_level, scope_level+1);
1204         BlockModifier::visit(block);
1205
1206         for(map<string, VariableDeclaration *>::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i)
1207                 variable_values.erase(i->second);
1208 }
1209
1210 void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign)
1211 {
1212         variable_values.erase(assign.target_declaration);
1213 }
1214
1215 void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var)
1216 {
1217         if(var.constant || scope_level>1)
1218                 variable_values[&var] = var.init_expression.get();
1219 }
1220
1221 void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
1222 {
1223         ExpressionEvaluator eval(variable_values);
1224         cond.condition->visit(eval);
1225         if(eval.result_valid)
1226                 flatten_block(eval.result ? cond.body : cond.else_body);
1227         else
1228                 TraversingVisitor::visit(cond);
1229 }
1230
1231 void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
1232 {
1233         if(iter.condition)
1234         {
1235                 ExpressionEvaluator eval;
1236                 iter.condition->visit(eval);
1237                 if(eval.result_valid && !eval.result)
1238                 {
1239                         remove_node = true;
1240                         return;
1241                 }
1242         }
1243
1244         TraversingVisitor::visit(iter);
1245 }
1246
1247
1248 ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
1249         aggregate(0),
1250         assignment(0),
1251         assignment_target(false),
1252         global_scope(true)
1253 { }
1254
1255 void ProgramCompiler::UnusedVariableLocator::apply(Stage &s)
1256 {
1257         variables.push_back(BlockVariableMap());
1258         Visitor::apply(s);
1259         BlockVariableMap &global_variables = variables.back();
1260         for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i)
1261         {
1262                 if(i->first->interface=="out" && (s.type==FRAGMENT || i->first->linked_declaration || !i->first->name.compare(0, 3, "gl_")))
1263                         continue;
1264                 if(!i->second.referenced)
1265                 {
1266                         unused_nodes.insert(i->first);
1267                         clear_assignments(i->second, true);
1268                 }
1269         }
1270         variables.pop_back();
1271 }
1272
1273 void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var)
1274 {
1275         map<VariableDeclaration *, Node *>::iterator i = aggregates.find(var.declaration);
1276         if(i!=aggregates.end())
1277                 unused_nodes.erase(i->second);
1278
1279         if(var.declaration && !assignment_target)
1280         {
1281                 VariableInfo &var_info = variables.back()[var.declaration];
1282                 var_info.assignments.clear();
1283                 var_info.referenced = true;
1284         }
1285 }
1286
1287 void ProgramCompiler::UnusedVariableLocator::visit(MemberAccess &memacc)
1288 {
1289         TraversingVisitor::visit(memacc);
1290         unused_nodes.erase(memacc.declaration);
1291 }
1292
1293 void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary)
1294 {
1295         if(binary.oper=="[")
1296         {
1297                 binary.left->visit(*this);
1298                 SetForScope<bool> set(assignment_target, false);
1299                 binary.right->visit(*this);
1300         }
1301         else
1302                 TraversingVisitor::visit(binary);
1303 }
1304
1305 void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign)
1306 {
1307         {
1308                 SetForScope<bool> set(assignment_target, !assign.self_referencing);
1309                 assign.left->visit(*this);
1310         }
1311         assign.right->visit(*this);
1312         assignment = &assign;
1313 }
1314
1315 void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref)
1316 {
1317         VariableInfo &var_info = variables.back()[&var];
1318         if(!self_ref)
1319                 clear_assignments(var_info, true);
1320         var_info.assignments.push_back(&node);
1321         var_info.conditionally_assigned = false;
1322 }
1323
1324 void ProgramCompiler::UnusedVariableLocator::clear_assignments(VariableInfo &var_info, bool mark_unused)
1325 {
1326         if(mark_unused)
1327         {
1328                 for(vector<Node *>::iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i)
1329                         unused_nodes.insert(*i);
1330         }
1331         var_info.assignments.clear();
1332 }
1333
1334 void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr)
1335 {
1336         assignment = 0;
1337         TraversingVisitor::visit(expr);
1338         if(assignment && assignment->target_declaration)
1339                 record_assignment(*assignment->target_declaration, expr, assignment->self_referencing);
1340 }
1341
1342 void ProgramCompiler::UnusedVariableLocator::visit(StructDeclaration &strct)
1343 {
1344         SetForScope<Node *> set(aggregate, &strct);
1345         unused_nodes.insert(&strct);
1346         TraversingVisitor::visit(strct);
1347 }
1348
1349 void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var)
1350 {
1351         if(aggregate)
1352                 aggregates[&var] = aggregate;
1353         else
1354         {
1355                 variables.back()[&var].local = true;
1356                 if(var.init_expression)
1357                         record_assignment(var, *var.init_expression, false);
1358         }
1359         unused_nodes.erase(var.type_declaration);
1360         TraversingVisitor::visit(var);
1361 }
1362
1363 void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface)
1364 {
1365         SetForScope<Node *> set(aggregate, &iface);
1366         unused_nodes.insert(&iface);
1367         TraversingVisitor::visit(iface);
1368 }
1369
1370 void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
1371 {
1372         variables.push_back(BlockVariableMap());
1373
1374         {
1375                 SetForScope<bool> set(global_scope, false);
1376                 for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1377                         (*i)->visit(*this);
1378                 func.body.visit(*this);
1379         }
1380
1381         BlockVariableMap &block_variables = variables.back();
1382         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1383                 i->second.conditionally_assigned = true;
1384         for(vector<RefPtr<VariableDeclaration> >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1385                 block_variables[i->get()].referenced = true;
1386         merge_down_variables();
1387 }
1388
1389 void ProgramCompiler::UnusedVariableLocator::merge_down_variables()
1390 {
1391         BlockVariableMap &parent_variables = variables[variables.size()-2];
1392         BlockVariableMap &block_variables = variables.back();
1393         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1394         {
1395                 if(i->second.local)
1396                 {
1397                         if(!i->second.referenced)
1398                                 unused_nodes.insert(i->first);
1399                         clear_assignments(i->second, true);
1400                         continue;
1401                 }
1402
1403                 BlockVariableMap::iterator j = parent_variables.find(i->first);
1404                 if(j==parent_variables.end())
1405                         parent_variables.insert(*i);
1406                 else
1407                 {
1408                         if(i->second.referenced || !i->second.conditionally_assigned)
1409                                 clear_assignments(j->second, !i->second.referenced);
1410                         j->second.conditionally_assigned = i->second.conditionally_assigned;
1411                         j->second.referenced |= i->second.referenced;
1412                         j->second.assignments.insert(j->second.assignments.end(), i->second.assignments.begin(), i->second.assignments.end());
1413                 }
1414         }
1415         variables.pop_back();
1416 }
1417
1418 void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond)
1419 {
1420         cond.condition->visit(*this);
1421         variables.push_back(BlockVariableMap());
1422         cond.body.visit(*this);
1423
1424         BlockVariableMap if_variables;
1425         swap(variables.back(), if_variables);
1426         cond.else_body.visit(*this);
1427
1428         BlockVariableMap &else_variables = variables.back();
1429         for(BlockVariableMap::iterator i=else_variables.begin(); i!=else_variables.end(); ++i)
1430         {
1431                 BlockVariableMap::iterator j = if_variables.find(i->first);
1432                 if(j!=if_variables.end())
1433                 {
1434                         i->second.assignments.insert(i->second.assignments.end(), j->second.assignments.begin(), j->second.assignments.end());
1435                         i->second.conditionally_assigned |= j->second.conditionally_assigned;
1436                         if_variables.erase(j);
1437                 }
1438                 else
1439                         i->second.conditionally_assigned = true;
1440         }
1441
1442         for(BlockVariableMap::iterator i=if_variables.begin(); i!=if_variables.end(); ++i)
1443         {
1444                 i->second.conditionally_assigned = true;
1445                 else_variables.insert(*i);
1446         }
1447
1448         merge_down_variables();
1449 }
1450
1451 void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
1452 {
1453         variables.push_back(BlockVariableMap());
1454         TraversingVisitor::visit(iter);
1455
1456         BlockVariableMap &block_variables = variables.back();
1457         for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1458                 if(!i->second.local && i->second.referenced)
1459                         i->second.assignments.clear();
1460
1461         merge_down_variables();
1462 }
1463
1464
1465 ProgramCompiler::UnusedVariableLocator::VariableInfo::VariableInfo():
1466         local(false),
1467         conditionally_assigned(false),
1468         referenced(false)
1469 { }
1470
1471
1472 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
1473 {
1474         TraversingVisitor::visit(call);
1475
1476         unused_nodes.erase(call.declaration);
1477         if(call.declaration && call.declaration->definition!=call.declaration)
1478                 used_definitions.insert(call.declaration->definition);
1479 }
1480
1481 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
1482 {
1483         TraversingVisitor::visit(func);
1484
1485         if((func.name!="main" || func.body.body.empty()) && !used_definitions.count(&func))
1486                 unused_nodes.insert(&func);
1487 }
1488
1489
1490 ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
1491         to_remove(r)
1492 { }
1493
1494 void ProgramCompiler::NodeRemover::visit(Block &block)
1495 {
1496         for(list<RefPtr<Node> >::iterator i=block.body.begin(); i!=block.body.end(); )
1497         {
1498                 (*i)->visit(*this);
1499                 if(to_remove.count(i->get()))
1500                         block.body.erase(i++);
1501                 else
1502                         ++i;
1503         }
1504 }
1505
1506 void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var)
1507 {
1508         if(to_remove.count(&var))
1509         {
1510                 stage->in_variables.erase(var.name);
1511                 stage->out_variables.erase(var.name);
1512                 stage->locations.erase(var.name);
1513                 if(var.linked_declaration)
1514                         var.linked_declaration->linked_declaration = 0;
1515         }
1516         else if(var.init_expression && to_remove.count(var.init_expression.get()))
1517                 var.init_expression = 0;
1518 }
1519
1520
1521 void ProgramCompiler::PrecisionRemover::visit(Precision &)
1522 {
1523         remove_node = true;
1524 }
1525
1526 void ProgramCompiler::PrecisionRemover::visit(VariableDeclaration &var)
1527 {
1528         var.precision.clear();
1529 }
1530
1531
1532 ProgramCompiler::DefaultPrecisionGenerator::DefaultPrecisionGenerator():
1533         toplevel(true)
1534 { }
1535
1536 void ProgramCompiler::DefaultPrecisionGenerator::visit(Block &block)
1537 {
1538         if(toplevel)
1539         {
1540                 SetForScope<bool> set(toplevel, false);
1541                 BlockModifier::visit(block);
1542         }
1543         else
1544                 Visitor::visit(block);
1545 }
1546
1547 void ProgramCompiler::DefaultPrecisionGenerator::visit(Precision &prec)
1548 {
1549         have_default.insert(prec.type);
1550 }
1551
1552 void ProgramCompiler::DefaultPrecisionGenerator::visit(VariableDeclaration &var)
1553 {
1554         if(var.type_declaration)
1555                 return;
1556
1557         string type = var.type;
1558         if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
1559                 type = "float";
1560         else if(!type.compare(0, 3, "ivec") || type=="uint")
1561                 type = "int";
1562
1563         if(!have_default.count(type))
1564         {
1565                 Precision *prec = new Precision;
1566                 if(!type.compare(0, 7, "sampler"))
1567                         prec->precision = "lowp";
1568                 else if(stage->type==FRAGMENT)
1569                         prec->precision = "mediump";
1570                 else
1571                         prec->precision = "highp";
1572                 prec->type = type;
1573                 insert_nodes.push_back(prec);
1574
1575                 have_default.insert(type);
1576         }
1577 }
1578
1579
1580 ProgramCompiler::LegacyConverter::LegacyConverter():
1581         target_api(get_gl_api()),
1582         target_version(get_glsl_version()),
1583         frag_out(0)
1584 { }
1585
1586 ProgramCompiler::LegacyConverter::LegacyConverter(const Version &v):
1587         target_api(get_gl_api()),
1588         target_version(v),
1589         frag_out(0)
1590 { }
1591
1592 bool ProgramCompiler::LegacyConverter::check_version(const Version &feature_version) const
1593 {
1594         if(target_version<feature_version)
1595                 return false;
1596         else if(stage->required_version<feature_version)
1597                 stage->required_version = feature_version;
1598
1599         return true;
1600 }
1601
1602 bool ProgramCompiler::LegacyConverter::supports_unified_interface_syntax() const
1603 {
1604         if(target_api==OPENGL_ES2)
1605                 return check_version(Version(3, 0));
1606         else
1607                 return check_version(Version(1, 30));
1608 }
1609
1610 void ProgramCompiler::LegacyConverter::visit(VariableReference &var)
1611 {
1612         if(var.declaration==frag_out && !supports_unified_interface_syntax())
1613         {
1614                 var.name = "gl_FragColor";
1615                 var.declaration = 0;
1616                 type = "vec4";
1617         }
1618         else if(var.declaration)
1619                 type = var.declaration->type;
1620         else
1621                 type = string();
1622 }
1623
1624 void ProgramCompiler::LegacyConverter::visit(Assignment &assign)
1625 {
1626         TraversingVisitor::visit(assign);
1627         if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
1628                 assign.target_declaration = 0;
1629 }
1630
1631 bool ProgramCompiler::LegacyConverter::supports_unified_sampling_functions() const
1632 {
1633         if(target_api==OPENGL_ES2)
1634                 return check_version(Version(3, 0));
1635         else
1636                 return check_version(Version(1, 30));
1637 }
1638
1639 void ProgramCompiler::LegacyConverter::visit(FunctionCall &call)
1640 {
1641         if(call.name=="texture" && !call.declaration && !supports_unified_sampling_functions())
1642         {
1643                 vector<RefPtr<Expression> >::iterator i = call.arguments.begin();
1644                 if(i!=call.arguments.end())
1645                 {
1646                         (*i)->visit(*this);
1647                         if(type=="sampler1D")
1648                                 call.name = "texture1D";
1649                         else if(type=="sampler2D")
1650                                 call.name = "texture2D";
1651                         else if(type=="sampler3D")
1652                                 call.name = "texture3D";
1653                         else if(type=="sampler1DShadow")
1654                                 call.name = "shadow1D";
1655                         else if(type=="sampler2DShadow")
1656                                 call.name = "shadow2D";
1657
1658                         for(; i!=call.arguments.end(); ++i)
1659                                 (*i)->visit(*this);
1660                 }
1661         }
1662         else
1663                 TraversingVisitor::visit(call);
1664 }
1665
1666 bool ProgramCompiler::LegacyConverter::supports_interface_layouts() const
1667 {
1668         if(target_api==OPENGL_ES2)
1669                 return check_version(Version(3, 0));
1670         else
1671                 return check_version(Version(3, 30));
1672 }
1673
1674 void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var)
1675 {
1676         if(var.layout && !supports_interface_layouts())
1677         {
1678                 vector<Layout::Qualifier>::iterator i;
1679                 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
1680                 if(i!=var.layout->qualifiers.end())
1681                 {
1682                         unsigned location = lexical_cast<unsigned>(i->value);
1683                         if(stage->type==VERTEX && var.interface=="in")
1684                         {
1685                                 stage->locations[var.name] = location;
1686                                 var.layout->qualifiers.erase(i);
1687                         }
1688                         else if(stage->type==FRAGMENT && var.interface=="out")
1689                         {
1690                                 stage->locations[var.name] = location;
1691                                 var.layout->qualifiers.erase(i);
1692                         }
1693
1694                         if(var.layout->qualifiers.empty())
1695                                 var.layout = 0;
1696                 }
1697         }
1698
1699         if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
1700         {
1701                 if(stage->type==FRAGMENT && var.interface=="out")
1702                 {
1703                         frag_out = &var;
1704                         remove_node = true;
1705                 }
1706         }
1707
1708         TraversingVisitor::visit(var);
1709 }
1710
1711 bool ProgramCompiler::LegacyConverter::supports_interface_blocks(const string &iface) const
1712 {
1713         if(target_api==OPENGL_ES2)
1714         {
1715                 if(iface=="uniform")
1716                         return check_version(Version(3, 0));
1717                 else
1718                         return check_version(Version(3, 20));
1719         }
1720         else
1721                 return check_version(Version(1, 50));
1722 }
1723
1724 void ProgramCompiler::LegacyConverter::visit(InterfaceBlock &iface)
1725 {
1726         if(!supports_interface_blocks(iface.interface))
1727                 flatten_block(iface.members);
1728 }
1729
1730 } // namespace GL
1731 } // namespace Msp