X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=f30ccfa6233ad6b6dc8115488210c7f1dbd4c7a5;hp=6bf5ba66a83ed851075e48fda66f33a3a17b5d6e;hb=HEAD;hpb=961715848c111907b5f443c5b545a429b40583e6 diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp deleted file mode 100644 index 6bf5ba66..00000000 --- a/source/programcompiler.cpp +++ /dev/null @@ -1,659 +0,0 @@ -#include -#include -#include -#include "error.h" -#include "program.h" -#include "programcompiler.h" -#include "shader.h" - -using namespace std; - -namespace Msp { -namespace GL { - -using namespace ProgramSyntax; - -ProgramCompiler::ProgramCompiler(): - module(0) -{ } - -void ProgramCompiler::compile(const string &source) -{ - module = &parser.parse(source); - process(); -} - -void ProgramCompiler::compile(IO::Base &io) -{ - module = &parser.parse(io); - process(); -} - -void ProgramCompiler::add_shaders(Program &program) -{ - if(!module) - throw invalid_operation("ProgramCompiler::add_shaders"); - - string head = "#version 150\n"; - if(module->vertex_context.present) - program.attach_shader_owned(new VertexShader(head+format_context(module->vertex_context))); - if(module->geometry_context.present) - program.attach_shader_owned(new GeometryShader(head+format_context(module->geometry_context))); - if(module->fragment_context.present) - program.attach_shader_owned(new FragmentShader(head+format_context(module->fragment_context))); - - program.bind_attribute(VERTEX4, "vertex"); - program.bind_attribute(NORMAL3, "normal"); - program.bind_attribute(COLOR4_FLOAT, "color"); - program.bind_attribute(TEXCOORD4, "texcoord"); -} - -void ProgramCompiler::process() -{ - if(module->vertex_context.present) - process(module->vertex_context); - if(module->geometry_context.present) - process(module->geometry_context); - if(module->fragment_context.present) - process(module->fragment_context); -} - -void ProgramCompiler::process(Context &context) -{ - inject_block(context.content, module->global_context.content); - - resolve_variables(context); - - InterfaceGenerator generator; - generator.visit(context); - - resolve_variables(context); - - VariableRenamer renamer; - context.content.visit(renamer); - - while(1) - { - UnusedVariableLocator unused_locator; - context.content.visit(unused_locator); - - NodeRemover remover; - remover.to_remove.insert(unused_locator.unused_variables.begin(), unused_locator.unused_variables.end()); - context.content.visit(remover); - - if(!remover.n_removed) - break; - } -} - -void ProgramCompiler::inject_block(Block &target, const Block &source) -{ - list >::iterator insert_point = target.body.begin(); - for(list >::const_iterator i=source.body.begin(); i!=source.body.end(); ++i) - target.body.insert(insert_point, (*i)->clone()); -} - -void ProgramCompiler::resolve_variables(Context &context) -{ - VariableResolver resolver; - context.content.visit(resolver); -} - -string ProgramCompiler::format_context(Context &context) -{ - Formatter formatter; - context.content.visit(formatter); - return formatter.formatted; -} - - -ProgramCompiler::Formatter::Formatter(): - indent(0), - parameter_list(false), - else_if(false) -{ } - -void ProgramCompiler::Formatter::visit(Literal &literal) -{ - formatted += literal.token; -} - -void ProgramCompiler::Formatter::visit(ParenthesizedExpression &parexpr) -{ - formatted += '('; - parexpr.expression->visit(*this); - formatted += ')'; -} - -void ProgramCompiler::Formatter::visit(VariableReference &var) -{ - formatted += var.name; -} - -void ProgramCompiler::Formatter::visit(MemberAccess &memacc) -{ - memacc.left->visit(*this); - formatted += format(".%s", memacc.member); -} - -void ProgramCompiler::Formatter::visit(UnaryExpression &unary) -{ - if(unary.prefix) - formatted += unary.oper; - unary.expression->visit(*this); - if(!unary.prefix) - formatted += unary.oper; -} - -void ProgramCompiler::Formatter::visit(BinaryExpression &binary) -{ - binary.left->visit(*this); - if(binary.assignment) - formatted += format(" %s ", binary.oper); - else - formatted += binary.oper; - binary.right->visit(*this); - formatted += binary.after; -} - -void ProgramCompiler::Formatter::visit(FunctionCall &call) -{ - formatted += format("%s(", call.name); - for(vector >::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) - { - if(i!=call.arguments.begin()) - formatted += ", "; - (*i)->visit(*this); - } - formatted += ')'; -} - -void ProgramCompiler::Formatter::visit(ExpressionStatement &expr) -{ - expr.expression->visit(*this); - formatted += ';'; -} - -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, ' ')); - } - - bool change_indent = (!formatted.empty() && !else_if); - indent += change_indent; - 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; - (*i)->visit(*this); - } - indent -= change_indent; - - if(block.use_braces) - formatted += format("\n%s}", string(indent*2, ' ')); -} - -void ProgramCompiler::Formatter::visit(Layout &layout) -{ - formatted += "layout("; - for(vector::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i) - { - if(i!=layout.qualifiers.begin()) - formatted += ", "; - formatted += i->identifier; - if(!i->value.empty()) - formatted += format("=%s", i->value); - } - formatted += format(") %s;", layout.interface); -} - -void ProgramCompiler::Formatter::visit(StructDeclaration &strct) -{ - formatted += format("struct %s\n", strct.name); - strct.members.visit(*this); - formatted += ';'; -} - -void ProgramCompiler::Formatter::visit(VariableDeclaration &var) -{ - if(var.constant) - formatted += "const "; - if(!var.sampling.empty()) - formatted += format("%s ", var.sampling); - if(!var.interface.empty()) - formatted += format("%s ", var.interface); - formatted += format("%s %s", var.type, var.name); - if(var.array) - { - formatted += '['; - if(var.array_size) - var.array_size->visit(*this); - formatted += ']'; - } - if(var.init_expression) - { - formatted += " = "; - var.init_expression->visit(*this); - } - if(!parameter_list) - formatted += ';'; -} - -void ProgramCompiler::Formatter::visit(InterfaceBlock &iface) -{ - formatted += format("%s %s\n", iface.interface, iface.name); - iface.members.visit(*this); - formatted += ';'; -} - -void ProgramCompiler::Formatter::visit(FunctionDeclaration &func) -{ - formatted += format("%s %s(", func.return_type, func.name); - for(vector >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) - { - if(i!=func.parameters.begin()) - formatted += ", "; - SetFlag set(parameter_list); - (*i)->visit(*this); - } - formatted += ')'; - if(func.definition) - { - formatted += '\n'; - func.body.visit(*this); - } - else - formatted += ';'; -} - -void ProgramCompiler::Formatter::visit(Conditional &cond) -{ - if(else_if) - { - formatted += ' '; - else_if = false; - } - - formatted += "if("; - cond.condition->visit(*this); - formatted += ")\n"; - - cond.body.visit(*this); - if(!cond.else_body.body.empty()) - { - formatted += format("\n%selse", string(indent*2, ' ')); - SetFlag set(else_if); - cond.else_body.visit(*this); - } -} - -void ProgramCompiler::Formatter::visit(Iteration &iter) -{ - formatted += "for("; - iter.init_statement->visit(*this); - formatted += ' '; - iter.condition->visit(*this); - formatted += "; "; - iter.loop_expression->visit(*this); - formatted += ")\n"; - iter.body.visit(*this); -} - -void ProgramCompiler::Formatter::visit(Return &ret) -{ - formatted += "return "; - ret.expression->visit(*this); - formatted += ';'; -} - - -ProgramCompiler::VariableResolver::VariableResolver(): - anonymous(false) -{ } - -void ProgramCompiler::VariableResolver::visit(Block &block) -{ - blocks.push_back(&block); - block.variables.clear(); - TraversingVisitor::visit(block); - blocks.pop_back(); -} - -void ProgramCompiler::VariableResolver::visit(VariableReference &var) -{ - var.declaration = 0; - type = 0; - for(vector::iterator i=blocks.end(); i!=blocks.begin(); ) - { - --i; - map::iterator j = (*i)->variables.find(var.name); - if(j!=(*i)->variables.end()) - { - var.declaration = j->second; - type = j->second->type_declaration; - break; - } - } -} - -void ProgramCompiler::VariableResolver::visit(MemberAccess &memacc) -{ - type = 0; - TraversingVisitor::visit(memacc); - memacc.declaration = 0; - if(type) - { - map::iterator i = type->members.variables.find(memacc.member); - if(i!=type->members.variables.end()) - { - memacc.declaration = i->second; - type = i->second->type_declaration; - } - else - type = 0; - } -} - -void ProgramCompiler::VariableResolver::visit(BinaryExpression &binary) -{ - if(binary.oper=="[") - { - binary.right->visit(*this); - type = 0; - binary.left->visit(*this); - } - else - { - TraversingVisitor::visit(binary); - type = 0; - } -} - -void ProgramCompiler::VariableResolver::visit(StructDeclaration &strct) -{ - TraversingVisitor::visit(strct); - blocks.back()->types[strct.name] = &strct; -} - -void ProgramCompiler::VariableResolver::visit(VariableDeclaration &var) -{ - for(vector::iterator i=blocks.end(); i!=blocks.begin(); ) - { - --i; - map::iterator j = (*i)->types.find(var.type); - if(j!=(*i)->types.end()) - var.type_declaration = j->second; - } - - TraversingVisitor::visit(var); - blocks.back()->variables[var.name] = &var; - if(anonymous && blocks.size()>1) - blocks[blocks.size()-2]->variables[var.name] = &var; -} - -void ProgramCompiler::VariableResolver::visit(InterfaceBlock &iface) -{ - SetFlag set(anonymous); - TraversingVisitor::visit(iface); -} - - -ProgramCompiler::InterfaceGenerator::InterfaceGenerator(): - context(0), - scope_level(0), - remove_node(false) -{ } - -string ProgramCompiler::InterfaceGenerator::get_out_prefix(ContextType type) -{ - if(type==VERTEX) - return "_vs_out_"; - else if(type==GEOMETRY) - return "_gs_out_"; - else - return string(); -} - -void ProgramCompiler::InterfaceGenerator::visit(Context &ctx) -{ - SetForScope set(context, &ctx); - if(context->previous) - in_prefix = get_out_prefix(context->previous->type); - out_prefix = get_out_prefix(context->type); - ctx.content.visit(*this); -} - -void ProgramCompiler::InterfaceGenerator::visit(Block &block) -{ - SetForScope set(scope_level, scope_level+1); - for(list >::iterator i=block.body.begin(); i!=block.body.end(); ) - { - (*i)->visit(*this); - - if(scope_level==1) - { - for(map >::iterator j=iface_declarations.begin(); j!=iface_declarations.end(); ++j) - { - list >::iterator k = block.body.insert(i, j->second); - (*k)->visit(*this); - } - iface_declarations.clear(); - } - - for(list >::iterator j=insert_nodes.begin(); j!=insert_nodes.end(); ++j) - block.body.insert(i, *j); - insert_nodes.clear(); - - if(remove_node) - block.body.erase(i++); - else - ++i; - remove_node = false; - } -} - -string ProgramCompiler::InterfaceGenerator::change_prefix(const string &name, const string &prefix) const -{ - unsigned offset = (name.compare(0, in_prefix.size(), in_prefix) ? 0 : in_prefix.size()); - return prefix+name.substr(offset); -} - -bool ProgramCompiler::InterfaceGenerator::generate_interface(VariableDeclaration &out, const string &iface, const string &name) -{ - const map &context_vars = (iface=="in" ? context->in_variables : context->out_variables); - if(context_vars.count(name) || iface_declarations.count(name)) - return false; - - VariableDeclaration* iface_var = new VariableDeclaration; - iface_var->sampling = out.sampling; - iface_var->interface = iface; - iface_var->type = out.type; - iface_var->type_declaration = out.type_declaration; - iface_var->name = name; - iface_var->array = (out.array || (context->type==GEOMETRY && iface=="in")); - iface_var->array_size = out.array_size; - if(iface=="in") - iface_var->linked_declaration = &out; - iface_declarations[iface_var->name] = iface_var; - - return true; -} - -void ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right) -{ - BinaryExpression *assign = new BinaryExpression; - VariableReference *ref = new VariableReference; - ref->name = left; - assign->left = ref; - assign->oper = "="; - assign->right = right; - assign->assignment = true; - - ExpressionStatement *stmt = new ExpressionStatement; - stmt->expression = assign; - insert_nodes.push_back(stmt); -} - -void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var) -{ - if(var.declaration || !context->previous) - return; - if(iface_declarations.count(var.name)) - return; - - const map &prev_out = context->previous->out_variables; - map::const_iterator i = prev_out.find(var.name); - if(i==prev_out.end()) - i = prev_out.find(in_prefix+var.name); - if(i!=prev_out.end()) - generate_interface(*i->second, "in", var.name); -} - -void ProgramCompiler::InterfaceGenerator::visit(VariableDeclaration &var) -{ - if(var.interface=="out") - { - if(scope_level==1) - context->out_variables[var.name] = &var; - else if(generate_interface(var, "out", change_prefix(var.name, string()))) - { - remove_node = true; - if(var.init_expression) - insert_assignment(var.name, var.init_expression->clone()); - } - } - else if(var.interface=="in") - { - context->in_variables[var.name] = &var; - if(context->previous) - { - const map &prev_out = context->previous->out_variables; - map::const_iterator i = prev_out.find(var.name); - if(i!=prev_out.end()) - { - var.linked_declaration = i->second; - i->second->linked_declaration = &var; - } - } - } - - TraversingVisitor::visit(var); -} - -void ProgramCompiler::InterfaceGenerator::visit(Passthrough &pass) -{ - if(context->previous) - { - const map &prev_out = context->previous->out_variables; - for(map::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i) - { - string out_name = change_prefix(i->second->name, out_prefix); - generate_interface(*i->second, "in", i->second->name); - generate_interface(*i->second, "out", out_name); - - VariableReference *ref = new VariableReference; - ref->name = i->first; - if(pass.subscript) - { - BinaryExpression *subscript = new BinaryExpression; - subscript->left = ref; - subscript->oper = "["; - subscript->right = pass.subscript; - subscript->after = "]"; - insert_assignment(out_name, subscript); - } - else - insert_assignment(out_name, ref); - } - } - - remove_node = true; -} - - -void ProgramCompiler::VariableRenamer::visit(VariableReference &var) -{ - if(var.declaration) - var.name = var.declaration->name; -} - -void ProgramCompiler::VariableRenamer::visit(VariableDeclaration &var) -{ - if(var.linked_declaration) - var.name = var.linked_declaration->name; - TraversingVisitor::visit(var); -} - - -void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var) -{ - unused_variables.erase(var.declaration); -} - -void ProgramCompiler::UnusedVariableLocator::visit(MemberAccess &memacc) -{ - TraversingVisitor::visit(memacc); - unused_variables.erase(memacc.declaration); -} - -void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var) -{ - unused_variables.insert(&var); - TraversingVisitor::visit(var); -} - - -ProgramCompiler::NodeRemover::NodeRemover(): - n_removed(0), - immutable_block(false), - remove_block(false) -{ } - -void ProgramCompiler::NodeRemover::visit(Block &block) -{ - remove_block = immutable_block; - for(list >::iterator i=block.body.begin(); i!=block.body.end(); ) - { - bool remove = false; - if(to_remove.count(&**i)) - remove = !immutable_block; - else - { - remove_block = false; - (*i)->visit(*this); - remove = remove_block; - } - - if(remove) - block.body.erase(i++); - else - ++i; - - n_removed += remove; - } -} - -void ProgramCompiler::NodeRemover::visit(StructDeclaration &strct) -{ - SetFlag set(immutable_block); - TraversingVisitor::visit(strct); -} - -void ProgramCompiler::NodeRemover::visit(InterfaceBlock &iface) -{ - SetFlag set(immutable_block); - TraversingVisitor::visit(iface); -} - -} // namespace GL -} // namespace Msp