1 #include <msp/core/algorithm.h>
2 #include <msp/core/raii.h>
3 #include <msp/gl/extensions/arb_explicit_attrib_location.h>
4 #include <msp/gl/extensions/arb_gpu_shader5.h>
5 #include <msp/gl/extensions/arb_uniform_buffer_object.h>
6 #include <msp/gl/extensions/ext_gpu_shader4.h>
7 #include <msp/gl/extensions/ext_texture_array.h>
8 #include <msp/strings/format.h>
9 #include <msp/strings/regex.h>
10 #include <msp/strings/utils.h>
13 #include "programcompiler.h"
14 #include "resources.h"
23 const char builtins_src[] =
24 "#pragma MSP stage(vertex)\n"
25 "out gl_PerVertex {\n"
26 " vec4 gl_Position;\n"
27 " float gl_ClipDistance[];\n"
29 "#pragma MSP stage(geometry)\n"
31 " vec4 gl_Position;\n"
32 " float gl_ClipDistance[];\n"
34 "out gl_PerVertex {\n"
35 " vec4 gl_Position;\n"
36 " float gl_ClipDistance[];\n"
44 using namespace ProgramSyntax;
46 ProgramCompiler::ProgramCompiler():
51 ProgramCompiler::~ProgramCompiler()
56 void ProgramCompiler::compile(const string &source, const string &src_name)
60 module = new Module();
62 imported_names.push_back(src_name);
63 append_module(parser.parse(source, src_name, 1));
67 void ProgramCompiler::compile(IO::Base &io, Resources *res, const string &src_name)
71 module = new Module();
73 imported_names.push_back(src_name);
74 append_module(parser.parse(io, src_name, 1));
78 void ProgramCompiler::compile(IO::Base &io, const string &src_name)
80 compile(io, 0, src_name);
83 void ProgramCompiler::add_shaders(Program &program)
86 throw invalid_operation("ProgramCompiler::add_shaders");
90 for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
94 program.attach_shader_owned(new VertexShader(apply<Formatter>(*i)));
95 for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
96 program.bind_attribute(j->second, j->first);
98 else if(i->type==GEOMETRY)
99 program.attach_shader_owned(new GeometryShader(apply<Formatter>(*i)));
100 else if(i->type==FRAGMENT)
102 program.attach_shader_owned(new FragmentShader(apply<Formatter>(*i)));
105 for(map<string, unsigned>::iterator j=i->locations.begin(); j!=i->locations.end(); ++j)
106 program.bind_fragment_data(j->second, j->first);
111 catch(const compile_error &e)
113 static const Regex r_message("^(([0-9]+)\\(([0-9]+)\\) :|ERROR: ([0-9]+):([0-9]+):) (.*)$");
114 vector<string> lines = split(e.what(), '\n');
116 for(vector<string>::const_iterator i=lines.begin(); i!=lines.end(); ++i)
118 RegMatch m = r_message.match(*i);
125 index = lexical_cast<unsigned>(m[2].str);
126 line = lexical_cast<unsigned>(m[3].str);
130 index = lexical_cast<unsigned>(m[4].str);
131 line = lexical_cast<unsigned>(m[5].str);
133 const char *src = "<unknown>";
136 else if(index-1<imported_names.size())
137 src = imported_names[index-1].c_str();
138 translated += format("%s:%d: %s", src, line, m[6].str);
145 throw compile_error(translated);
149 Module *ProgramCompiler::create_builtins_module()
151 ProgramParser parser;
152 Module *module = new Module(parser.parse(builtins_src, "<builtin>"));
153 for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
155 VariableResolver resolver;
156 i->content.visit(resolver);
157 for(map<string, VariableDeclaration *>::iterator j=i->content.variables.begin(); j!=i->content.variables.end(); ++j)
158 j->second->linked_declaration = j->second;
163 Module &ProgramCompiler::get_builtins_module()
165 static RefPtr<Module> builtins_module = create_builtins_module();
166 return *builtins_module;
169 Stage *ProgramCompiler::get_builtins(StageType type)
171 Module &module = get_builtins_module();
172 for(list<Stage>::iterator i=module.stages.begin(); i!=module.stages.end(); ++i)
178 void ProgramCompiler::append_module(ProgramSyntax::Module &mod)
180 vector<Import *> imports = apply<NodeGatherer<Import> >(mod.shared);
181 for(vector<Import *>::iterator i=imports.begin(); i!=imports.end(); ++i)
182 import((*i)->module);
183 apply<NodeRemover>(mod.shared, set<Node *>(imports.begin(), imports.end()));
185 append_stage(mod.shared);
186 for(list<Stage>::iterator i=mod.stages.begin(); i!=mod.stages.end(); ++i)
190 void ProgramCompiler::append_stage(Stage &stage)
193 if(stage.type==SHARED)
194 target = &module->shared;
197 list<Stage>::iterator i;
198 for(i=module->stages.begin(); (i!=module->stages.end() && i->type<stage.type); ++i) ;
199 if(i==module->stages.end() || i->type>stage.type)
201 list<Stage>::iterator j = module->stages.insert(i, stage.type);
202 if(i!=module->stages.end())
205 if(i!=module->stages.begin())
212 for(NodeList<Statement>::iterator i=stage.content.body.begin(); i!=stage.content.body.end(); ++i)
213 target->content.body.push_back(*i);
214 apply<DeclarationCombiner>(*target);
217 void ProgramCompiler::process()
219 for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
221 for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); )
224 i = module->stages.begin();
228 for(list<Stage>::iterator i=module->stages.begin(); i!=module->stages.end(); ++i)
232 void ProgramCompiler::import(const string &name)
234 string fn = name+".glsl";
235 if(find(imported_names, fn)!=imported_names.end())
237 imported_names.push_back(fn);
239 RefPtr<IO::Seekable> io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn));
241 throw runtime_error(format("module %s not found", name));
242 ProgramParser import_parser;
243 append_module(import_parser.parse(*io, fn, imported_names.size()));
246 void ProgramCompiler::generate(Stage &stage)
248 inject_block(stage.content, module->shared.content);
250 apply<DeclarationReorderer>(stage);
251 apply<FunctionResolver>(stage);
252 apply<VariableResolver>(stage);
253 apply<InterfaceGenerator>(stage);
254 apply<VariableResolver>(stage);
255 apply<DeclarationReorderer>(stage);
256 apply<FunctionResolver>(stage);
257 apply<LegacyConverter>(stage);
260 bool ProgramCompiler::optimize(Stage &stage)
262 apply<ConstantConditionEliminator>(stage);
264 set<FunctionDeclaration *> inlineable = apply<InlineableFunctionLocator>(stage);
265 apply<FunctionInliner>(stage, inlineable);
267 set<Node *> unused = apply<UnusedVariableLocator>(stage);
268 set<Node *> unused2 = apply<UnusedFunctionLocator>(stage);
269 unused.insert(unused2.begin(), unused2.end());
270 apply<NodeRemover>(stage, unused);
272 return !unused.empty();
275 void ProgramCompiler::finalize(Stage &stage)
277 if(get_gl_api()==OPENGL_ES2)
278 apply<DefaultPrecisionGenerator>(stage);
280 apply<PrecisionRemover>(stage);
283 void ProgramCompiler::inject_block(Block &target, const Block &source)
285 NodeList<Statement>::iterator insert_point = target.body.begin();
286 for(NodeList<Statement>::const_iterator i=source.body.begin(); i!=source.body.end(); ++i)
287 target.body.insert(insert_point, (*i)->clone());
291 typename T::ResultType ProgramCompiler::apply(Stage &stage)
294 visitor.apply(stage);
295 return visitor.get_result();
298 template<typename T, typename A>
299 typename T::ResultType ProgramCompiler::apply(Stage &stage, const A &arg)
302 visitor.apply(stage);
303 return visitor.get_result();
307 ProgramCompiler::Visitor::Visitor():
311 void ProgramCompiler::Visitor::apply(Stage &s)
313 SetForScope<Stage *> set(stage, &s);
314 stage->content.visit(*this);
318 ProgramCompiler::BlockModifier::BlockModifier():
322 void ProgramCompiler::BlockModifier::flatten_block(Block &block)
324 insert_nodes.insert(insert_nodes.end(), block.body.begin(), block.body.end());
328 void ProgramCompiler::BlockModifier::apply_and_increment(Block &block, NodeList<Statement>::iterator &i)
330 block.body.insert(i, insert_nodes.begin(), insert_nodes.end());
331 insert_nodes.clear();
334 block.body.erase(i++);
340 void ProgramCompiler::BlockModifier::visit(Block &block)
342 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
345 apply_and_increment(block, i);
350 ProgramCompiler::Formatter::Formatter():
353 parameter_list(false)
356 void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s)
358 GLApi api = get_gl_api();
359 const Version &ver = s.required_version;
363 append(format("#version %d%02d", ver.major, ver.minor));
364 if(api==OPENGL_ES2 && ver>=Version(3, 0))
369 for(vector<const Extension *>::const_iterator i=s.required_extensions.begin(); i!=s.required_extensions.end(); ++i)
370 append(format("#extension %s: require\n", (*i)->get_name()));
371 if(!s.required_extensions.empty())
377 void ProgramCompiler::Formatter::append(const string &text)
380 for(string::const_iterator i=text.begin(); i!=text.end(); ++i)
385 void ProgramCompiler::Formatter::append(char c)
392 void ProgramCompiler::Formatter::set_source(unsigned index, unsigned line)
394 if(index!=source_index || (index && line!=source_line))
396 if(index==source_index && line==source_line+1)
401 if(stage->required_version<Version(3, 30))
403 formatted += format("#line %d %d\n", l, index);
406 source_index = index;
410 void ProgramCompiler::Formatter::visit(Literal &literal)
412 append(literal.token);
415 void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr)
418 parexpr.expression->visit(*this);
422 void ProgramCompiler::Formatter::visit(VariableReference &var)
427 void ProgramCompiler::Formatter::visit(MemberAccess &memacc)
429 memacc.left->visit(*this);
430 append(format(".%s", memacc.member));
433 void ProgramCompiler::Formatter::visit(UnaryExpression &unary)
437 unary.expression->visit(*this);
442 void ProgramCompiler::Formatter::visit(BinaryExpression &binary)
444 binary.left->visit(*this);
446 binary.right->visit(*this);
447 append(binary.after);
450 void ProgramCompiler::Formatter::visit(Assignment &assign)
452 assign.left->visit(*this);
453 append(format(" %s ", assign.oper));
454 assign.right->visit(*this);
457 void ProgramCompiler::Formatter::visit(FunctionCall &call)
459 append(format("%s(", call.name));
460 for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
462 if(i!=call.arguments.begin())
469 void ProgramCompiler::Formatter::visit(ExpressionStatement &expr)
471 expr.expression->visit(*this);
475 void ProgramCompiler::Formatter::visit(Block &block)
477 unsigned brace_indent = indent;
478 bool use_braces = (block.use_braces || (indent && block.body.size()!=1));
480 append(format("%s{\n", string(brace_indent*2, ' ')));
482 SetForScope<unsigned> set(indent, indent+(indent>0 || use_braces));
483 string spaces(indent*2, ' ');
484 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
486 if(i!=block.body.begin())
488 set_source((*i)->source, (*i)->line);
494 append(format("\n%s}", string(brace_indent*2, ' ')));
497 void ProgramCompiler::Formatter::visit(Import &import)
499 append(format("import %s;", import.module));
502 void ProgramCompiler::Formatter::visit(Precision &prec)
504 append(format("precision %s %s;", prec.precision, prec.type));
507 void ProgramCompiler::Formatter::visit(Layout &layout)
510 for(vector<Layout::Qualifier>::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i)
512 if(i!=layout.qualifiers.begin())
514 append(i->identifier);
515 if(!i->value.empty())
516 append(format("=%s", i->value));
521 void ProgramCompiler::Formatter::visit(InterfaceLayout &layout)
523 layout.layout.visit(*this);
524 append(format(" %s;", layout.interface));
527 void ProgramCompiler::Formatter::visit(StructDeclaration &strct)
529 append(format("struct %s\n", strct.name));
530 strct.members.visit(*this);
534 void ProgramCompiler::Formatter::visit(VariableDeclaration &var)
538 var.layout->visit(*this);
543 if(!var.interpolation.empty())
544 append(format("%s ", var.interpolation));
545 if(!var.sampling.empty())
546 append(format("%s ", var.sampling));
547 if(!var.interface.empty() && var.interface!=block_interface)
549 string interface = var.interface;
550 if(stage->required_version<Version(1, 30))
552 if(stage->type==VERTEX && var.interface=="in")
553 interface = "attribute";
554 else if((stage->type==VERTEX && var.interface=="out") || (stage->type==FRAGMENT && var.interface=="in"))
555 interface = "varying";
557 append(format("%s ", interface));
559 if(!var.precision.empty())
560 append(format("%s ", var.precision));
561 append(format("%s %s", var.type, var.name));
566 var.array_size->visit(*this);
569 if(var.init_expression)
572 var.init_expression->visit(*this);
578 void ProgramCompiler::Formatter::visit(InterfaceBlock &iface)
580 SetForScope<string> set(block_interface, iface.interface);
581 append(format("%s %s\n", iface.interface, iface.name));
582 iface.members.visit(*this);
586 void ProgramCompiler::Formatter::visit(FunctionDeclaration &func)
588 append(format("%s %s(", func.return_type, func.name));
589 for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
591 if(i!=func.parameters.begin())
593 SetFlag set(parameter_list);
597 if(func.definition==&func)
600 func.body.visit(*this);
606 void ProgramCompiler::Formatter::visit(Conditional &cond)
609 cond.condition->visit(*this);
612 cond.body.visit(*this);
613 if(!cond.else_body.body.empty())
615 Conditional *else_cond = dynamic_cast<Conditional *>(cond.else_body.body.front().get());
616 if(cond.else_body.body.size()==1 && else_cond)
619 set_source(else_cond->source, else_cond->line);
620 append(format("%selse ", string(indent*2, ' ')));
621 else_cond->visit(*this);
625 append(format("\n%selse\n", string(indent*2, ' ')));
626 cond.else_body.visit(*this);
631 void ProgramCompiler::Formatter::visit(Iteration &iter)
633 if(!iter.init_statement && iter.condition && !iter.loop_expression)
636 iter.condition->visit(*this);
642 if(iter.init_statement)
643 iter.init_statement->visit(*this);
649 iter.condition->visit(*this);
652 if(iter.loop_expression)
655 iter.loop_expression->visit(*this);
660 if(iter.body.body.empty())
665 iter.body.visit(*this);
669 void ProgramCompiler::Formatter::visit(Return &ret)
675 ret.expression->visit(*this);
680 void ProgramCompiler::Formatter::visit(Jump &jump)
682 append(jump.keyword);
687 ProgramCompiler::DeclarationCombiner::DeclarationCombiner():
691 void ProgramCompiler::DeclarationCombiner::visit(Block &block)
696 SetForScope<bool> set(toplevel, false);
697 BlockModifier::visit(block);
700 void ProgramCompiler::DeclarationCombiner::visit(FunctionDeclaration &func)
702 vector<FunctionDeclaration *> &decls = functions[func.name];
705 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
707 (*i)->definition = func.definition;
708 (*i)->body.body.clear();
711 decls.push_back(&func);
714 void ProgramCompiler::DeclarationCombiner::visit(VariableDeclaration &var)
716 VariableDeclaration *&ptr = variables[var.name];
719 ptr->type = var.type;
720 if(var.init_expression)
721 ptr->init_expression = var.init_expression;
726 for(vector<Layout::Qualifier>::iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ++i)
729 for(vector<Layout::Qualifier>::iterator j=ptr->layout->qualifiers.begin(); (!found && j!=ptr->layout->qualifiers.end()); ++j)
730 if(j->identifier==i->identifier)
737 ptr->layout->qualifiers.push_back(*i);
741 ptr->layout = var.layout;
750 ProgramCompiler::VariableResolver::VariableResolver():
752 record_target(false),
753 assignment_target(0),
754 self_referencing(false)
757 void ProgramCompiler::VariableResolver::apply(Stage &s)
759 SetForScope<Stage *> set(stage, &s);
760 Stage *builtins = get_builtins(stage->type);
762 blocks.push_back(&builtins->content);
763 stage->content.visit(*this);
768 void ProgramCompiler::VariableResolver::visit(Block &block)
770 blocks.push_back(&block);
771 block.variables.clear();
772 TraversingVisitor::visit(block);
776 void ProgramCompiler::VariableResolver::visit(VariableReference &var)
780 for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
783 map<string, VariableDeclaration *>::iterator j = (*i)->variables.find(var.name);
784 if(j!=(*i)->variables.end())
786 var.declaration = j->second;
787 type = j->second->type_declaration;
794 if(assignment_target)
796 record_target = false;
797 assignment_target = 0;
800 assignment_target = var.declaration;
802 else if(var.declaration && var.declaration==assignment_target)
803 self_referencing = true;
806 void ProgramCompiler::VariableResolver::visit(MemberAccess &memacc)
809 TraversingVisitor::visit(memacc);
810 memacc.declaration = 0;
813 map<string, VariableDeclaration *>::iterator i = type->members.variables.find(memacc.member);
814 if(i!=type->members.variables.end())
816 memacc.declaration = i->second;
817 type = i->second->type_declaration;
824 void ProgramCompiler::VariableResolver::visit(BinaryExpression &binary)
829 SetForScope<bool> set(record_target, false);
830 binary.right->visit(*this);
833 binary.left->visit(*this);
837 TraversingVisitor::visit(binary);
842 void ProgramCompiler::VariableResolver::visit(Assignment &assign)
845 SetFlag set(record_target);
846 assignment_target = 0;
847 assign.left->visit(*this);
850 self_referencing = false;
851 assign.right->visit(*this);
853 assign.self_referencing = (self_referencing || assign.oper!="=");
854 assign.target_declaration = assignment_target;
857 void ProgramCompiler::VariableResolver::visit(StructDeclaration &strct)
859 TraversingVisitor::visit(strct);
860 blocks.back()->types[strct.name] = &strct;
863 void ProgramCompiler::VariableResolver::visit(VariableDeclaration &var)
865 for(vector<Block *>::iterator i=blocks.end(); i!=blocks.begin(); )
868 map<string, StructDeclaration *>::iterator j = (*i)->types.find(var.type);
869 if(j!=(*i)->types.end())
870 var.type_declaration = j->second;
873 if(!block_interface.empty() && var.interface.empty())
874 var.interface = block_interface;
876 TraversingVisitor::visit(var);
877 blocks.back()->variables[var.name] = &var;
878 if(anonymous && blocks.size()>1)
879 blocks[blocks.size()-2]->variables[var.name] = &var;
882 void ProgramCompiler::VariableResolver::visit(InterfaceBlock &iface)
884 SetFlag set(anonymous);
885 SetForScope<string> set2(block_interface, iface.interface);
886 TraversingVisitor::visit(iface);
890 void ProgramCompiler::FunctionResolver::visit(FunctionCall &call)
892 map<string, vector<FunctionDeclaration *> >::iterator i = functions.find(call.name);
893 if(i!=functions.end())
894 call.declaration = i->second.back();
896 TraversingVisitor::visit(call);
899 void ProgramCompiler::FunctionResolver::visit(FunctionDeclaration &func)
901 vector<FunctionDeclaration *> &decls = functions[func.name];
904 for(vector<FunctionDeclaration *>::iterator i=decls.begin(); i!=decls.end(); ++i)
905 (*i)->definition = func.definition;
907 decls.push_back(&func);
909 else if(!decls.empty() && decls.back()->definition)
910 func.definition = decls.back()->definition;
912 decls.push_back(&func);
914 TraversingVisitor::visit(func);
918 ProgramCompiler::InterfaceGenerator::InterfaceGenerator():
922 string ProgramCompiler::InterfaceGenerator::get_out_prefix(StageType type)
926 else if(type==GEOMETRY)
932 void ProgramCompiler::InterfaceGenerator::apply(Stage &s)
934 SetForScope<Stage *> set(stage, &s);
936 in_prefix = get_out_prefix(stage->previous->type);
937 out_prefix = get_out_prefix(stage->type);
938 stage->content.visit(*this);
941 void ProgramCompiler::InterfaceGenerator::visit(Block &block)
943 SetForScope<unsigned> set(scope_level, scope_level+1);
944 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
950 for(map<string, RefPtr<VariableDeclaration> >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j)
952 NodeList<Statement>::iterator k = block.body.insert(i, j->second);
955 iface_declarations.clear();
958 apply_and_increment(block, i);
962 string ProgramCompiler::InterfaceGenerator::change_prefix(const string &name, const string &prefix) const
964 unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size());
965 return prefix+name.substr(offset);
968 bool ProgramCompiler::InterfaceGenerator::generate_interface(VariableDeclaration &var, const string &iface, const string &name)
970 const map<string, VariableDeclaration *> &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables);
971 if(stage_vars.count(name) || iface_declarations.count(name))
974 VariableDeclaration* iface_var = new VariableDeclaration;
975 iface_var->sampling = var.sampling;
976 iface_var->interface = iface;
977 iface_var->type = var.type;
978 iface_var->type_declaration = var.type_declaration;
979 iface_var->name = name;
980 if(stage->type==GEOMETRY)
981 iface_var->array = ((var.array && var.interface!="in") || iface=="in");
983 iface_var->array = var.array;
985 iface_var->array_size = var.array_size;
987 iface_var->linked_declaration = &var;
988 iface_declarations[name] = iface_var;
993 ExpressionStatement &ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right)
995 Assignment *assign = new Assignment;
996 VariableReference *ref = new VariableReference;
1000 assign->right = right;
1002 ExpressionStatement *stmt = new ExpressionStatement;
1003 stmt->expression = assign;
1005 insert_nodes.push_back(stmt);
1010 void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var)
1012 if(var.declaration || !stage->previous)
1014 if(iface_declarations.count(var.name))
1017 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
1018 map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
1019 if(i==prev_out.end())
1020 i = prev_out.find(in_prefix+var.name);
1021 if(i!=prev_out.end())
1023 generate_interface(*i->second, "in", i->second->name);
1024 var.name = i->second->name;
1028 void ProgramCompiler::InterfaceGenerator::visit(VariableDeclaration &var)
1030 if(var.interface=="out")
1033 stage->out_variables[var.name] = &var;
1034 else if(generate_interface(var, "out", change_prefix(var.name, string())))
1037 if(var.init_expression)
1039 ExpressionStatement &stmt = insert_assignment(var.name, var.init_expression->clone());
1040 stmt.source = var.source;
1041 stmt.line = var.line;
1046 else if(var.interface=="in")
1048 stage->in_variables[var.name] = &var;
1049 if(var.linked_declaration)
1050 var.linked_declaration->linked_declaration = &var;
1051 else if(stage->previous)
1053 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
1054 map<string, VariableDeclaration *>::const_iterator i = prev_out.find(var.name);
1055 if(i!=prev_out.end())
1057 var.linked_declaration = i->second;
1058 i->second->linked_declaration = &var;
1063 TraversingVisitor::visit(var);
1066 void ProgramCompiler::InterfaceGenerator::visit(Passthrough &pass)
1068 vector<VariableDeclaration *> pass_vars;
1070 for(map<string, VariableDeclaration *>::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i)
1071 pass_vars.push_back(i->second);
1072 for(map<string, RefPtr<VariableDeclaration> >::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i)
1073 if(i->second->interface=="in")
1074 pass_vars.push_back(i->second.get());
1078 const map<string, VariableDeclaration *> &prev_out = stage->previous->out_variables;
1079 for(map<string, VariableDeclaration *>::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i)
1081 bool linked = false;
1082 for(vector<VariableDeclaration *>::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j)
1083 linked = ((*j)->linked_declaration==i->second);
1085 if(!linked && generate_interface(*i->second, "in", i->second->name))
1086 pass_vars.push_back(i->second);
1090 if(stage->type==GEOMETRY)
1092 VariableReference *ref = new VariableReference;
1093 ref->name = "gl_in";
1095 BinaryExpression *subscript = new BinaryExpression;
1096 subscript->left = ref;
1097 subscript->oper = "[";
1098 subscript->right = pass.subscript;
1099 subscript->after = "]";
1101 MemberAccess *memacc = new MemberAccess;
1102 memacc->left = subscript;
1103 memacc->member = "gl_Position";
1105 insert_assignment("gl_Position", memacc);
1108 for(vector<VariableDeclaration *>::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i)
1110 string out_name = change_prefix((*i)->name, out_prefix);
1111 generate_interface(**i, "out", out_name);
1113 VariableReference *ref = new VariableReference;
1114 ref->name = (*i)->name;
1117 BinaryExpression *subscript = new BinaryExpression;
1118 subscript->left = ref;
1119 subscript->oper = "[";
1120 subscript->right = pass.subscript;
1121 subscript->after = "]";
1122 insert_assignment(out_name, subscript);
1125 insert_assignment(out_name, ref);
1132 ProgramCompiler::DeclarationReorderer::DeclarationReorderer():
1134 kind(NO_DECLARATION)
1137 void ProgramCompiler::DeclarationReorderer::visit(FunctionCall &call)
1139 FunctionDeclaration *def = call.declaration;
1141 def = def->definition;
1142 if(def && !ordered_funcs.count(def))
1143 needed_funcs.insert(def);
1146 void ProgramCompiler::DeclarationReorderer::visit(Block &block)
1148 SetForScope<unsigned> set(scope_level, scope_level+1);
1150 return Visitor::visit(block);
1152 NodeList<Statement>::iterator struct_insert_point = block.body.end();
1153 NodeList<Statement>::iterator variable_insert_point = block.body.end();
1154 NodeList<Statement>::iterator function_insert_point = block.body.end();
1155 unsigned unordered_func_count = 0;
1156 bool ordered_any_funcs = false;
1158 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
1160 kind = NO_DECLARATION;
1164 if(kind==STRUCT && struct_insert_point!=block.body.end())
1166 block.body.insert(struct_insert_point, *i);
1169 else if(kind>STRUCT && struct_insert_point==block.body.end())
1170 struct_insert_point = i;
1172 if(kind==VARIABLE && variable_insert_point!=block.body.end())
1174 block.body.insert(variable_insert_point, *i);
1177 else if(kind>VARIABLE && variable_insert_point==block.body.end())
1178 variable_insert_point = i;
1182 if(function_insert_point==block.body.end())
1183 function_insert_point = i;
1185 if(needed_funcs.empty())
1187 ordered_funcs.insert(i->get());
1188 if(i!=function_insert_point)
1190 block.body.insert(function_insert_point, *i);
1194 ++function_insert_point;
1195 ordered_any_funcs = true;
1198 ++unordered_func_count;
1203 if(function_insert_point==i)
1204 ++function_insert_point;
1205 block.body.erase(i++);
1210 if(i==block.body.end() && unordered_func_count)
1212 if(!ordered_any_funcs)
1213 // A subset of the remaining functions forms a recursive loop
1214 /* TODO pick a function and move it up, adding any necessary
1218 i = function_insert_point;
1219 unordered_func_count = 0;
1224 void ProgramCompiler::DeclarationReorderer::visit(ProgramSyntax::VariableDeclaration &var)
1226 Visitor::visit(var);
1230 void ProgramCompiler::DeclarationReorderer::visit(FunctionDeclaration &func)
1232 needed_funcs.clear();
1233 func.body.visit(*this);
1234 needed_funcs.erase(&func);
1239 ProgramCompiler::InlineableFunctionLocator::InlineableFunctionLocator():
1243 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionCall &call)
1245 FunctionDeclaration *def = call.declaration;
1246 if(def && def->definition!=def)
1247 def = def->definition;
1251 unsigned &count = refcounts[def];
1253 if(count>1 || def==in_function)
1254 inlineable.erase(def);
1257 TraversingVisitor::visit(call);
1260 void ProgramCompiler::InlineableFunctionLocator::visit(FunctionDeclaration &func)
1262 unsigned &count = refcounts[func.definition];
1263 if(!count && func.parameters.empty())
1264 inlineable.insert(func.definition);
1266 SetForScope<FunctionDeclaration *> set(in_function, &func);
1267 TraversingVisitor::visit(func);
1271 ProgramCompiler::FunctionInliner::FunctionInliner():
1275 ProgramCompiler::FunctionInliner::FunctionInliner(const set<FunctionDeclaration *> &in):
1280 void ProgramCompiler::FunctionInliner::visit_and_inline(RefPtr<Expression> &ptr)
1285 ptr = inline_result;
1288 void ProgramCompiler::FunctionInliner::visit(Block &block)
1293 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
1301 void ProgramCompiler::FunctionInliner::visit(UnaryExpression &unary)
1303 visit_and_inline(unary.expression);
1307 void ProgramCompiler::FunctionInliner::visit(BinaryExpression &binary)
1309 visit_and_inline(binary.left);
1310 visit_and_inline(binary.right);
1314 void ProgramCompiler::FunctionInliner::visit(MemberAccess &memacc)
1316 visit_and_inline(memacc.left);
1320 void ProgramCompiler::FunctionInliner::visit(FunctionCall &call)
1322 for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
1323 visit_and_inline(*i);
1325 FunctionDeclaration *def = call.declaration;
1326 if(def && def->definition!=def)
1327 def = def->definition;
1329 if(def && inlineable.count(def))
1338 void ProgramCompiler::FunctionInliner::visit(VariableDeclaration &var)
1340 if(var.init_expression)
1341 visit_and_inline(var.init_expression);
1345 void ProgramCompiler::FunctionInliner::visit(Return &ret)
1347 TraversingVisitor::visit(ret);
1350 inline_result = ret.expression->clone();
1354 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator():
1360 ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v):
1361 variable_values(&v),
1366 void ProgramCompiler::ExpressionEvaluator::visit(Literal &literal)
1368 if(literal.token=="true")
1370 else if(literal.token=="false")
1373 result = lexical_cast<float>(literal.token);
1374 result_valid = true;
1377 void ProgramCompiler::ExpressionEvaluator::visit(ParenthesizedExpression &parexp)
1379 parexp.expression->visit(*this);
1382 void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var)
1384 if(!var.declaration)
1389 ValueMap::const_iterator i = variable_values->find(var.declaration);
1390 if(i!=variable_values->end())
1391 i->second->visit(*this);
1393 else if(var.declaration->init_expression)
1394 var.declaration->init_expression->visit(*this);
1397 void ProgramCompiler::ExpressionEvaluator::visit(UnaryExpression &unary)
1399 result_valid = false;
1400 unary.expression->visit(*this);
1407 result_valid = false;
1410 void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary)
1412 result_valid = false;
1413 binary.left->visit(*this);
1417 float left_result = result;
1418 result_valid = false;
1419 binary.right->visit(*this);
1423 if(binary.oper=="<")
1424 result = (left_result<result);
1425 else if(binary.oper=="<=")
1426 result = (left_result<=result);
1427 else if(binary.oper==">")
1428 result = (left_result>result);
1429 else if(binary.oper==">=")
1430 result = (left_result>=result);
1431 else if(binary.oper=="==")
1432 result = (left_result==result);
1433 else if(binary.oper=="!=")
1434 result = (left_result!=result);
1435 else if(binary.oper=="&&")
1436 result = (left_result && result);
1437 else if(binary.oper=="||")
1438 result = (left_result || result);
1440 result_valid = false;
1444 ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator():
1449 void ProgramCompiler::ConstantConditionEliminator::visit(Block &block)
1451 SetForScope<unsigned> set(scope_level, scope_level+1);
1452 BlockModifier::visit(block);
1454 for(map<string, VariableDeclaration *>::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i)
1455 variable_values.erase(i->second);
1458 void ProgramCompiler::ConstantConditionEliminator::visit(UnaryExpression &unary)
1460 if(VariableReference *var = dynamic_cast<VariableReference *>(unary.expression.get()))
1461 if(unary.oper=="++" || unary.oper=="--")
1462 variable_values.erase(var->declaration);
1465 void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign)
1467 variable_values.erase(assign.target_declaration);
1470 void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var)
1472 if(var.constant || scope_level>1)
1473 variable_values[&var] = var.init_expression.get();
1476 void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond)
1480 ExpressionEvaluator eval(variable_values);
1481 cond.condition->visit(eval);
1482 if(eval.result_valid)
1484 flatten_block(eval.result ? cond.body : cond.else_body);
1489 TraversingVisitor::visit(cond);
1492 void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter)
1498 /* If the loop condition is always false on the first iteration, the
1499 entire loop can be removed */
1500 if(iter.init_statement)
1501 iter.init_statement->visit(*this);
1502 ExpressionEvaluator eval(variable_values);
1503 iter.condition->visit(eval);
1504 if(eval.result_valid && !eval.result)
1511 /* Record all assignments that occur inside the loop body so those
1512 variables won't be considered as constant */
1513 SetFlag set_record(record_only);
1514 TraversingVisitor::visit(iter);
1517 TraversingVisitor::visit(iter);
1519 if(VariableDeclaration *init_decl = dynamic_cast<VariableDeclaration *>(iter.init_statement.get()))
1520 variable_values.erase(init_decl);
1524 ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator():
1527 assignment_target(false),
1528 assign_to_subscript(false),
1532 void ProgramCompiler::UnusedVariableLocator::apply(Stage &s)
1534 variables.push_back(BlockVariableMap());
1536 BlockVariableMap &global_variables = variables.back();
1537 for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i)
1539 if(i->first->interface=="out" && (s.type==FRAGMENT || i->first->linked_declaration || !i->first->name.compare(0, 3, "gl_")))
1541 if(!i->second.referenced)
1543 unused_nodes.insert(i->first);
1544 clear_assignments(i->second, true);
1547 variables.pop_back();
1550 void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var)
1552 map<VariableDeclaration *, Node *>::iterator i = aggregates.find(var.declaration);
1553 if(i!=aggregates.end())
1554 unused_nodes.erase(i->second);
1556 if(var.declaration && !assignment_target)
1558 VariableInfo &var_info = variables.back()[var.declaration];
1559 var_info.assignments.clear();
1560 var_info.referenced = true;
1564 void ProgramCompiler::UnusedVariableLocator::visit(MemberAccess &memacc)
1566 TraversingVisitor::visit(memacc);
1567 unused_nodes.erase(memacc.declaration);
1570 void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary)
1572 if(binary.oper=="[")
1574 if(assignment_target)
1575 assign_to_subscript = true;
1576 binary.left->visit(*this);
1577 SetForScope<bool> set(assignment_target, false);
1578 binary.right->visit(*this);
1581 TraversingVisitor::visit(binary);
1584 void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign)
1587 assign_to_subscript = false;
1588 SetForScope<bool> set(assignment_target, !assign.self_referencing);
1589 assign.left->visit(*this);
1591 assign.right->visit(*this);
1592 assignment = &assign;
1595 void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool chained)
1597 VariableInfo &var_info = variables.back()[&var];
1599 clear_assignments(var_info, true);
1600 var_info.assignments.push_back(&node);
1601 var_info.conditionally_assigned = false;
1604 void ProgramCompiler::UnusedVariableLocator::clear_assignments(VariableInfo &var_info, bool mark_unused)
1608 for(vector<Node *>::iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i)
1609 unused_nodes.insert(*i);
1611 var_info.assignments.clear();
1614 void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr)
1617 TraversingVisitor::visit(expr);
1618 if(assignment && assignment->target_declaration)
1619 record_assignment(*assignment->target_declaration, expr, (assignment->self_referencing || assign_to_subscript));
1622 void ProgramCompiler::UnusedVariableLocator::visit(StructDeclaration &strct)
1624 SetForScope<Node *> set(aggregate, &strct);
1625 unused_nodes.insert(&strct);
1626 TraversingVisitor::visit(strct);
1629 void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var)
1632 aggregates[&var] = aggregate;
1635 variables.back()[&var].local = true;
1636 if(var.init_expression)
1637 record_assignment(var, *var.init_expression, false);
1639 unused_nodes.erase(var.type_declaration);
1640 TraversingVisitor::visit(var);
1643 void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface)
1645 SetForScope<Node *> set(aggregate, &iface);
1646 unused_nodes.insert(&iface);
1647 TraversingVisitor::visit(iface);
1650 void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func)
1652 variables.push_back(BlockVariableMap());
1655 SetForScope<bool> set(global_scope, false);
1656 for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1658 func.body.visit(*this);
1661 BlockVariableMap &block_variables = variables.back();
1662 for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1663 i->second.conditionally_assigned = true;
1664 for(NodeArray<VariableDeclaration>::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i)
1665 block_variables[i->get()].referenced = true;
1666 merge_down_variables();
1669 void ProgramCompiler::UnusedVariableLocator::merge_down_variables()
1671 BlockVariableMap &parent_variables = variables[variables.size()-2];
1672 BlockVariableMap &block_variables = variables.back();
1673 for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1677 if(!i->second.referenced)
1678 unused_nodes.insert(i->first);
1679 clear_assignments(i->second, true);
1683 BlockVariableMap::iterator j = parent_variables.find(i->first);
1684 if(j==parent_variables.end())
1685 parent_variables.insert(*i);
1688 if(i->second.referenced || !i->second.conditionally_assigned)
1689 clear_assignments(j->second, !i->second.referenced);
1690 j->second.conditionally_assigned = i->second.conditionally_assigned;
1691 j->second.referenced |= i->second.referenced;
1692 j->second.assignments.insert(j->second.assignments.end(), i->second.assignments.begin(), i->second.assignments.end());
1695 variables.pop_back();
1698 void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond)
1700 cond.condition->visit(*this);
1701 variables.push_back(BlockVariableMap());
1702 cond.body.visit(*this);
1704 BlockVariableMap if_variables;
1705 swap(variables.back(), if_variables);
1706 cond.else_body.visit(*this);
1708 BlockVariableMap &else_variables = variables.back();
1709 for(BlockVariableMap::iterator i=else_variables.begin(); i!=else_variables.end(); ++i)
1711 BlockVariableMap::iterator j = if_variables.find(i->first);
1712 if(j!=if_variables.end())
1714 i->second.assignments.insert(i->second.assignments.end(), j->second.assignments.begin(), j->second.assignments.end());
1715 i->second.conditionally_assigned |= j->second.conditionally_assigned;
1716 if_variables.erase(j);
1719 i->second.conditionally_assigned = true;
1722 for(BlockVariableMap::iterator i=if_variables.begin(); i!=if_variables.end(); ++i)
1724 i->second.conditionally_assigned = true;
1725 else_variables.insert(*i);
1728 merge_down_variables();
1731 void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter)
1733 variables.push_back(BlockVariableMap());
1734 TraversingVisitor::visit(iter);
1736 BlockVariableMap &block_variables = variables.back();
1737 for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i)
1738 if(!i->second.local && i->second.referenced)
1739 i->second.assignments.clear();
1741 merge_down_variables();
1745 ProgramCompiler::UnusedVariableLocator::VariableInfo::VariableInfo():
1747 conditionally_assigned(false),
1752 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call)
1754 TraversingVisitor::visit(call);
1756 unused_nodes.erase(call.declaration);
1757 if(call.declaration && call.declaration->definition!=call.declaration)
1758 used_definitions.insert(call.declaration->definition);
1761 void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func)
1763 TraversingVisitor::visit(func);
1765 if((func.name!="main" || func.body.body.empty()) && !used_definitions.count(&func))
1766 unused_nodes.insert(&func);
1770 ProgramCompiler::NodeRemover::NodeRemover(const set<Node *> &r):
1774 void ProgramCompiler::NodeRemover::visit(Block &block)
1776 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); )
1779 if(to_remove.count(i->get()))
1780 block.body.erase(i++);
1786 void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var)
1788 if(to_remove.count(&var))
1790 stage->in_variables.erase(var.name);
1791 stage->out_variables.erase(var.name);
1792 stage->locations.erase(var.name);
1793 if(var.linked_declaration)
1794 var.linked_declaration->linked_declaration = 0;
1796 else if(var.init_expression && to_remove.count(var.init_expression.get()))
1797 var.init_expression = 0;
1800 void ProgramCompiler::NodeRemover::visit(Iteration &iter)
1802 if(to_remove.count(iter.init_statement.get()))
1803 iter.init_statement = 0;
1804 TraversingVisitor::visit(iter);
1808 void ProgramCompiler::PrecisionRemover::visit(Precision &)
1813 void ProgramCompiler::PrecisionRemover::visit(VariableDeclaration &var)
1815 var.precision.clear();
1819 ProgramCompiler::DefaultPrecisionGenerator::DefaultPrecisionGenerator():
1823 void ProgramCompiler::DefaultPrecisionGenerator::visit(Block &block)
1827 SetForScope<bool> set(toplevel, false);
1828 BlockModifier::visit(block);
1831 Visitor::visit(block);
1834 void ProgramCompiler::DefaultPrecisionGenerator::visit(Precision &prec)
1836 have_default.insert(prec.type);
1839 void ProgramCompiler::DefaultPrecisionGenerator::visit(VariableDeclaration &var)
1841 if(var.type_declaration)
1844 string type = var.type;
1845 if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
1847 else if(!type.compare(0, 3, "ivec") || type=="uint")
1850 if(!have_default.count(type))
1852 Precision *prec = new Precision;
1853 if(!type.compare(0, 7, "sampler"))
1854 prec->precision = "lowp";
1855 else if(stage->type==FRAGMENT)
1856 prec->precision = "mediump";
1858 prec->precision = "highp";
1860 insert_nodes.push_back(prec);
1862 have_default.insert(type);
1867 ProgramCompiler::LegacyConverter::LegacyConverter():
1868 target_api(get_gl_api()),
1869 target_version(get_glsl_version()),
1873 ProgramCompiler::LegacyConverter::LegacyConverter(const Version &v):
1874 target_api(get_gl_api()),
1879 bool ProgramCompiler::LegacyConverter::check_version(const Version &feature_version) const
1881 if(target_version<feature_version)
1883 else if(stage->required_version<feature_version)
1884 stage->required_version = feature_version;
1889 bool ProgramCompiler::LegacyConverter::check_extension(const Extension &extension) const
1894 vector<const Extension *>::iterator i = find(stage->required_extensions, &extension);
1895 if(i==stage->required_extensions.end())
1896 stage->required_extensions.push_back(&extension);
1901 bool ProgramCompiler::LegacyConverter::supports_unified_interface_syntax() const
1903 if(target_api==OPENGL_ES2)
1904 return check_version(Version(3, 0));
1906 return check_version(Version(1, 30));
1909 void ProgramCompiler::LegacyConverter::visit(VariableReference &var)
1911 if(var.declaration==frag_out && !supports_unified_interface_syntax())
1913 var.name = "gl_FragColor";
1914 var.declaration = 0;
1917 else if(var.declaration)
1918 type = var.declaration->type;
1923 void ProgramCompiler::LegacyConverter::visit(Assignment &assign)
1925 TraversingVisitor::visit(assign);
1926 if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
1927 assign.target_declaration = 0;
1930 bool ProgramCompiler::LegacyConverter::supports_unified_sampling_functions() const
1932 if(target_api==OPENGL_ES2)
1933 return check_version(Version(3, 0));
1935 return check_version(Version(1, 30));
1938 void ProgramCompiler::LegacyConverter::visit(FunctionCall &call)
1940 if(call.name=="texture" && !call.declaration && !supports_unified_sampling_functions())
1942 NodeArray<Expression>::iterator i = call.arguments.begin();
1943 if(i!=call.arguments.end())
1946 if(type=="sampler1D")
1947 call.name = "texture1D";
1948 else if(type=="sampler2D")
1949 call.name = "texture2D";
1950 else if(type=="sampler3D")
1951 call.name = "texture3D";
1952 else if(type=="samplerCube")
1953 call.name = "textureCube";
1954 else if(type=="sampler1DShadow")
1955 call.name = "shadow1D";
1956 else if(type=="sampler2DShadow")
1957 call.name = "shadow2D";
1958 else if(type=="sampler1DArray")
1960 check_extension(EXT_texture_array);
1961 call.name = "texture1DArray";
1963 else if(type=="sampler2DArray")
1965 check_extension(EXT_texture_array);
1966 call.name = "texture2DArray";
1968 else if(type=="sampler1DArrayShadow")
1970 check_extension(EXT_texture_array);
1971 call.name = "shadow1DArray";
1973 else if(type=="sampler2DArrayShadow")
1975 check_extension(EXT_texture_array);
1976 call.name = "shadow2DArray";
1979 for(; i!=call.arguments.end(); ++i)
1984 TraversingVisitor::visit(call);
1987 bool ProgramCompiler::LegacyConverter::supports_interface_layouts() const
1989 if(target_api==OPENGL_ES2)
1990 return check_version(Version(3, 0));
1991 else if(check_version(Version(3, 30)))
1994 return check_extension(ARB_explicit_attrib_location);
1997 bool ProgramCompiler::LegacyConverter::supports_centroid_sampling() const
1999 if(target_api==OPENGL_ES2)
2000 return check_version(Version(3, 0));
2001 else if(check_version(Version(1, 20)))
2004 return check_extension(EXT_gpu_shader4);
2007 bool ProgramCompiler::LegacyConverter::supports_sample_sampling() const
2009 if(target_api==OPENGL_ES2)
2010 return check_version(Version(3, 20));
2011 else if(check_version(Version(4, 0)))
2014 return check_extension(ARB_gpu_shader5);
2017 void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var)
2019 if(var.layout && !supports_interface_layouts())
2021 vector<Layout::Qualifier>::iterator i;
2022 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
2023 if(i!=var.layout->qualifiers.end())
2025 unsigned location = lexical_cast<unsigned>(i->value);
2026 if(stage->type==VERTEX && var.interface=="in")
2028 stage->locations[var.name] = location;
2029 var.layout->qualifiers.erase(i);
2031 else if(stage->type==FRAGMENT && var.interface=="out")
2034 static Require _req(EXT_gpu_shader4);
2035 stage->locations[var.name] = location;
2036 var.layout->qualifiers.erase(i);
2039 if(var.layout->qualifiers.empty())
2044 if(var.sampling=="centroid")
2046 if(!supports_centroid_sampling())
2047 var.sampling = string();
2049 else if(var.sampling=="sample")
2051 if(!supports_sample_sampling())
2052 var.sampling = string();
2055 if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
2057 if(stage->type==FRAGMENT && var.interface=="out")
2064 TraversingVisitor::visit(var);
2067 bool ProgramCompiler::LegacyConverter::supports_interface_blocks(const string &iface) const
2069 if(target_api==OPENGL_ES2)
2071 if(iface=="uniform")
2072 return check_version(Version(3, 0));
2074 return check_version(Version(3, 20));
2076 else if(check_version(Version(1, 50)))
2078 else if(iface=="uniform")
2079 return check_extension(ARB_uniform_buffer_object);
2084 void ProgramCompiler::LegacyConverter::visit(InterfaceBlock &iface)
2086 if(!supports_interface_blocks(iface.interface))
2087 flatten_block(iface.members);