X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=82a324dec52d8e7c9e92b8d8c56cb15264e423f3;hb=a0caabaed3aeb8947133d78986bfb4ae5ae3c893;hp=fdbc83c7d4be404d7f07fe5a7c4757ac74596926;hpb=2b073e0a3808f8ece4b93669395e4b812214cf5d;p=libs%2Fgl.git diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp index fdbc83c7..82a324de 100644 --- a/source/programcompiler.cpp +++ b/source/programcompiler.cpp @@ -4,6 +4,7 @@ #include "error.h" #include "program.h" #include "programcompiler.h" +#include "resources.h" #include "shader.h" using namespace std; @@ -34,17 +35,20 @@ namespace GL { using namespace ProgramSyntax; ProgramCompiler::ProgramCompiler(): + resources(0), module(0) { } void ProgramCompiler::compile(const string &source) { + resources = 0; module = &parser.parse(source); process(); } -void ProgramCompiler::compile(IO::Base &io) +void ProgramCompiler::compile(IO::Base &io, Resources *res) { + resources = res; module = &parser.parse(io); process(); } @@ -58,11 +62,11 @@ void ProgramCompiler::add_shaders(Program &program) for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) { if(i->type==VERTEX) - program.attach_shader_owned(new VertexShader(head+create_source(*i))); + program.attach_shader_owned(new VertexShader(head+apply(*i))); else if(i->type==GEOMETRY) - program.attach_shader_owned(new GeometryShader(head+create_source(*i))); + program.attach_shader_owned(new GeometryShader(head+apply(*i))); else if(i->type==FRAGMENT) - program.attach_shader_owned(new FragmentShader(head+create_source(*i))); + program.attach_shader_owned(new FragmentShader(head+apply(*i))); } program.bind_attribute(VERTEX4, "vertex"); @@ -102,6 +106,11 @@ Stage *ProgramCompiler::get_builtins(StageType type) void ProgramCompiler::process() { + list imports = apply >(module->shared); + for(list::iterator i=imports.end(); i!=imports.begin(); ) + import((*--i)->module); + apply(module->shared, set(imports.begin(), imports.end())); + for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) generate(*i); for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ) @@ -113,6 +122,39 @@ void ProgramCompiler::process() } } +void ProgramCompiler::import(const string &name) +{ + if(!resources) + throw runtime_error("no resources"); + RefPtr io = resources->open_raw(name+".glsl"); + if(!io) + throw runtime_error(format("module %s not found", name)); + ProgramParser import_parser; + Module &imported_module = import_parser.parse(*io); + + inject_block(module->shared.content, imported_module.shared.content); + apply(module->shared); + for(list::iterator i=imported_module.stages.begin(); i!=imported_module.stages.end(); ++i) + { + list::iterator j; + for(j=module->stages.begin(); (j!=module->stages.end() && j->typetype); ++j) ; + if(j==module->stages.end() || j->type>i->type) + { + j = module->stages.insert(j, *i); + list::iterator k = j; + if(++k!=module->stages.end()) + k->previous = &*j; + if(j!=module->stages.begin()) + j->previous = &*--(k=j); + } + else + { + inject_block(j->content, i->content); + apply(*j); + } + } +} + void ProgramCompiler::generate(Stage &stage) { inject_block(stage.content, module->shared.content); @@ -125,14 +167,10 @@ void ProgramCompiler::generate(Stage &stage) bool ProgramCompiler::optimize(Stage &stage) { - UnusedVariableLocator unused_locator; - unused_locator.apply(stage); + set unused = apply(stage); + apply(stage, unused); - NodeRemover remover; - remover.to_remove = unused_locator.unused_nodes; - remover.apply(stage); - - return !unused_locator.unused_nodes.empty(); + return !unused.empty(); } void ProgramCompiler::inject_block(Block &target, const Block &source) @@ -143,17 +181,19 @@ void ProgramCompiler::inject_block(Block &target, const Block &source) } template -void ProgramCompiler::apply(Stage &stage) +typename T::ResultType ProgramCompiler::apply(Stage &stage) { T visitor; visitor.apply(stage); + return visitor.get_result(); } -string ProgramCompiler::create_source(Stage &stage) +template +typename T::ResultType ProgramCompiler::apply(Stage &stage, const A &arg) { - Formatter formatter; - formatter.apply(stage); - return formatter.formatted; + T visitor(arg); + visitor.apply(stage); + return visitor.get_result(); } @@ -171,7 +211,7 @@ void ProgramCompiler::Visitor::apply(Stage &s) ProgramCompiler::Formatter::Formatter(): indent(0), parameter_list(false), - else_if(false) + else_if(0) { } void ProgramCompiler::Formatter::visit(Literal &literal) @@ -241,31 +281,32 @@ void ProgramCompiler::Formatter::visit(ExpressionStatement &expr) void ProgramCompiler::Formatter::visit(Block &block) { - if(block.use_braces) - { - if(else_if) - { - formatted += '\n'; - else_if = false; - } - formatted += format("%s{\n", string(indent*2, ' ')); - } + if(else_if) + --else_if; - bool change_indent = (!formatted.empty() && !else_if); - indent += change_indent; + unsigned brace_indent = indent; + bool use_braces = (block.use_braces || (indent && block.body.size()!=1)); + if(use_braces) + formatted += format("%s{\n", string(brace_indent*2, ' ')); + + SetForScope set(indent, indent+!formatted.empty()); string spaces(indent*2, ' '); for(list >::iterator i=block.body.begin(); i!=block.body.end(); ++i) { if(i!=block.body.begin()) formatted += '\n'; - if(!else_if) - formatted += spaces; + formatted += spaces; (*i)->visit(*this); + else_if = 0; } - indent -= change_indent; - if(block.use_braces) - formatted += format("\n%s}", string(indent*2, ' ')); + if(use_braces) + formatted += format("\n%s}", string(brace_indent*2, ' ')); +} + +void ProgramCompiler::Formatter::visit(Import &import) +{ + formatted += format("import %s;", import.module); } void ProgramCompiler::Formatter::visit(Layout &layout) @@ -333,7 +374,7 @@ void ProgramCompiler::Formatter::visit(FunctionDeclaration &func) (*i)->visit(*this); } formatted += ')'; - if(func.definition) + if(func.definition==&func) { formatted += '\n'; func.body.visit(*this); @@ -345,10 +386,9 @@ void ProgramCompiler::Formatter::visit(FunctionDeclaration &func) void ProgramCompiler::Formatter::visit(Conditional &cond) { if(else_if) - { - formatted += ' '; - else_if = false; - } + formatted.replace(formatted.rfind('\n'), string::npos, 1, ' '); + + indent -= else_if; formatted += "if("; cond.condition->visit(*this); @@ -357,8 +397,8 @@ void ProgramCompiler::Formatter::visit(Conditional &cond) cond.body.visit(*this); if(!cond.else_body.body.empty()) { - formatted += format("\n%selse", string(indent*2, ' ')); - SetFlag set(else_if); + formatted += format("\n%selse\n", string(indent*2, ' ')); + SetForScope set(else_if, 2); cond.else_body.visit(*this); } } @@ -383,6 +423,56 @@ void ProgramCompiler::Formatter::visit(Return &ret) } +ProgramCompiler::DeclarationCombiner::DeclarationCombiner(): + toplevel(true), + remove_node(false) +{ } + +void ProgramCompiler::DeclarationCombiner::visit(Block &block) +{ + if(!toplevel) + return; + + SetForScope set(toplevel, false); + for(list >::iterator i=block.body.begin(); i!=block.body.end(); ) + { + remove_node = false; + (*i)->visit(*this); + if(remove_node) + block.body.erase(i++); + else + ++i; + } +} + +void ProgramCompiler::DeclarationCombiner::visit(FunctionDeclaration &func) +{ + vector &decls = functions[func.name]; + if(func.definition) + { + for(vector::iterator i=decls.begin(); i!=decls.end(); ++i) + { + (*i)->definition = func.definition; + (*i)->body.body.clear(); + } + } + decls.push_back(&func); +} + +void ProgramCompiler::DeclarationCombiner::visit(VariableDeclaration &var) +{ + VariableDeclaration *&ptr = variables[var.name]; + if(ptr) + { + if(var.init_expression) + ptr->init_expression = var.init_expression; + remove_node = true; + } + else + ptr = &var; +} + + ProgramCompiler::VariableResolver::VariableResolver(): anonymous(false), record_target(false), @@ -949,6 +1039,10 @@ void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter) } +ProgramCompiler::NodeRemover::NodeRemover(const set &r): + to_remove(r) +{ } + void ProgramCompiler::NodeRemover::visit(Block &block) { for(list >::iterator i=block.body.begin(); i!=block.body.end(); )