X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fprogramcompiler.cpp;h=f30ccfa6233ad6b6dc8115488210c7f1dbd4c7a5;hp=fd756de0e00cbbca4c5aa18587b251afc4e94ccb;hb=HEAD;hpb=48e37a09b49cd4148db390170cfd07eef92c9d02 diff --git a/source/programcompiler.cpp b/source/programcompiler.cpp deleted file mode 100644 index fd756de0..00000000 --- a/source/programcompiler.cpp +++ /dev/null @@ -1,1416 +0,0 @@ -#include -#include -#include -#include "error.h" -#include "program.h" -#include "programcompiler.h" -#include "resources.h" -#include "shader.h" - -using namespace std; - -namespace { - -const char builtins_src[] = - "////// vertex\n" - "out gl_PerVertex {\n" - " vec4 gl_Position;\n" - " float gl_ClipDistance[];\n" - "};" - "////// geometry\n" - "in gl_PerVertex {\n" - " vec4 gl_Position;\n" - " float gl_ClipDistance[];\n" - "} gl_in[];\n" - "out gl_PerVertex {\n" - " vec4 gl_Position;\n" - " float gl_ClipDistance[];\n" - "};\n"; - -} - -namespace Msp { -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, Resources *res) -{ - resources = res; - module = &parser.parse(io); - process(); -} - -void ProgramCompiler::add_shaders(Program &program) -{ - if(!module) - throw invalid_operation("ProgramCompiler::add_shaders"); - - for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) - { - if(i->type==VERTEX) - { - program.attach_shader_owned(new VertexShader(apply(*i))); - for(map::iterator j=i->locations.begin(); j!=i->locations.end(); ++j) - program.bind_attribute(j->second, j->first); - } - else if(i->type==GEOMETRY) - program.attach_shader_owned(new GeometryShader(apply(*i))); - else if(i->type==FRAGMENT) - { - program.attach_shader_owned(new FragmentShader(apply(*i))); - for(map::iterator j=i->locations.begin(); j!=i->locations.end(); ++j) - program.bind_fragment_data(j->second, j->first); - } - } -} - -Module *ProgramCompiler::create_builtins_module() -{ - ProgramParser parser; - Module *module = new Module(parser.parse(builtins_src)); - for(list::iterator i=module->stages.begin(); i!=module->stages.end(); ++i) - { - VariableResolver resolver; - i->content.visit(resolver); - for(map::iterator j=i->content.variables.begin(); j!=i->content.variables.end(); ++j) - j->second->linked_declaration = j->second; - } - return module; -} - -Module &ProgramCompiler::get_builtins_module() -{ - static RefPtr builtins_module = create_builtins_module(); - return *builtins_module; -} - -Stage *ProgramCompiler::get_builtins(StageType type) -{ - Module &module = get_builtins_module(); - for(list::iterator i=module.stages.begin(); i!=module.stages.end(); ++i) - if(i->type==type) - return &*i; - return 0; -} - -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(); ) - { - if(optimize(*i)) - i = module->stages.begin(); - else - ++i; - } -} - -void ProgramCompiler::import(const string &name) -{ - string fn = name+".glsl"; - RefPtr io = (resources ? resources->open_raw(fn) : Resources::get_builtins().open(fn)); - 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); - - apply(stage); - apply(stage); - apply(stage); - apply(stage); - apply(stage); - apply(stage); - apply(stage); -} - -bool ProgramCompiler::optimize(Stage &stage) -{ - apply(stage); - apply(stage); - - set unused = apply(stage); - set unused2 = apply(stage); - unused.insert(unused2.begin(), unused2.end()); - apply(stage, unused); - - return !unused.empty(); -} - -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()); -} - -template -typename T::ResultType ProgramCompiler::apply(Stage &stage) -{ - T visitor; - visitor.apply(stage); - return visitor.get_result(); -} - -template -typename T::ResultType ProgramCompiler::apply(Stage &stage, const A &arg) -{ - T visitor(arg); - visitor.apply(stage); - return visitor.get_result(); -} - - -ProgramCompiler::Visitor::Visitor(): - stage(0) -{ } - -void ProgramCompiler::Visitor::apply(Stage &s) -{ - SetForScope set(stage, &s); - stage->content.visit(*this); -} - - -ProgramCompiler::Formatter::Formatter(): - indent(0), - parameter_list(false), - else_if(0) -{ } - -void ProgramCompiler::Formatter::apply(ProgramSyntax::Stage &s) -{ - const Version &ver = s.required_version; - if(ver.major) - formatted += format("#version %d%d\n", ver.major, ver.minor); - Visitor::apply(s); -} - -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); - formatted += binary.oper; - binary.right->visit(*this); - formatted += binary.after; -} - -void ProgramCompiler::Formatter::visit(Assignment &assign) -{ - assign.left->visit(*this); - formatted += format(" %s ", assign.oper); - assign.right->visit(*this); -} - -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(else_if) - --else_if; - - 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+(indent>0 || use_braces)); - string spaces(indent*2, ' '); - for(list >::iterator i=block.body.begin(); i!=block.body.end(); ++i) - { - if(i!=block.body.begin()) - formatted += '\n'; - formatted += spaces; - (*i)->visit(*this); - else_if = 0; - } - - 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) -{ - 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 += ')'; -} - -void ProgramCompiler::Formatter::visit(InterfaceLayout &layout) -{ - layout.layout.visit(*this); - 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.layout) - { - var.layout->visit(*this); - formatted += ' '; - } - if(var.constant) - formatted += "const "; - if(!var.sampling.empty()) - formatted += format("%s ", var.sampling); - if(!var.interface.empty() && var.interface!=block_interface) - 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) -{ - SetForScope set(block_interface, iface.interface); - 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==&func) - { - formatted += '\n'; - func.body.visit(*this); - } - else - formatted += ';'; -} - -void ProgramCompiler::Formatter::visit(Conditional &cond) -{ - if(else_if) - formatted.replace(formatted.rfind('\n'), string::npos, 1, ' '); - - indent -= else_if; - - formatted += "if("; - cond.condition->visit(*this); - formatted += ")\n"; - - cond.body.visit(*this); - if(!cond.else_body.body.empty()) - { - formatted += format("\n%selse\n", string(indent*2, ' ')); - SetForScope set(else_if, 2); - 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::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) - { - ptr->type = var.type; - if(var.init_expression) - ptr->init_expression = var.init_expression; - remove_node = true; - } - else - ptr = &var; -} - - -ProgramCompiler::VariableResolver::VariableResolver(): - anonymous(false), - record_target(false), - assignment_target(0), - self_referencing(false) -{ } - -void ProgramCompiler::VariableResolver::apply(Stage &s) -{ - SetForScope set(stage, &s); - Stage *builtins = get_builtins(stage->type); - if(builtins) - blocks.push_back(&builtins->content); - stage->content.visit(*this); - if(builtins) - blocks.pop_back(); -} - -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; - } - } - - if(record_target) - { - if(assignment_target) - { - record_target = false; - assignment_target = 0; - } - else - assignment_target = var.declaration; - } - else if(var.declaration && var.declaration==assignment_target) - self_referencing = true; -} - -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=="[") - { - { - SetForScope set(record_target, false); - binary.right->visit(*this); - } - type = 0; - binary.left->visit(*this); - } - else - { - TraversingVisitor::visit(binary); - type = 0; - } -} - -void ProgramCompiler::VariableResolver::visit(Assignment &assign) -{ - { - SetFlag set(record_target); - assignment_target = 0; - assign.left->visit(*this); - } - - self_referencing = false; - assign.right->visit(*this); - - assign.self_referencing = (self_referencing || assign.oper!="="); - assign.target_declaration = assignment_target; -} - -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; - } - - if(!block_interface.empty() && var.interface.empty()) - var.interface = block_interface; - - 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); - SetForScope set2(block_interface, iface.interface); - TraversingVisitor::visit(iface); -} - - -void ProgramCompiler::FunctionResolver::visit(FunctionCall &call) -{ - map >::iterator i = functions.find(call.name); - if(i!=functions.end()) - call.declaration = i->second.back(); - - TraversingVisitor::visit(call); -} - -void ProgramCompiler::FunctionResolver::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; - decls.clear(); - decls.push_back(&func); - } - else if(!decls.empty() && decls.back()->definition) - func.definition = decls.back()->definition; - else - decls.push_back(&func); - - TraversingVisitor::visit(func); -} - - -ProgramCompiler::BlockModifier::BlockModifier(): - remove_node(false) -{ } - -void ProgramCompiler::BlockModifier::flatten_block(Block &block) -{ - for(list >::iterator i=block.body.begin(); i!=block.body.end(); ++i) - insert_nodes.push_back((*i)->clone()); - remove_node = true; -} - -void ProgramCompiler::BlockModifier::apply_and_increment(Block &block, list >::iterator &i) -{ - 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; -} - -void ProgramCompiler::BlockModifier::visit(Block &block) -{ - for(list >::iterator i=block.body.begin(); i!=block.body.end(); ) - { - (*i)->visit(*this); - apply_and_increment(block, i); - } -} - - -ProgramCompiler::InterfaceGenerator::InterfaceGenerator(): - scope_level(0) -{ } - -string ProgramCompiler::InterfaceGenerator::get_out_prefix(StageType type) -{ - if(type==VERTEX) - return "_vs_out_"; - else if(type==GEOMETRY) - return "_gs_out_"; - else - return string(); -} - -void ProgramCompiler::InterfaceGenerator::apply(Stage &s) -{ - SetForScope set(stage, &s); - if(stage->previous) - in_prefix = get_out_prefix(stage->previous->type); - out_prefix = get_out_prefix(stage->type); - stage->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(); - } - - apply_and_increment(block, i); - } -} - -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 &var, const string &iface, const string &name) -{ - const map &stage_vars = (iface=="in" ? stage->in_variables : stage->out_variables); - if(stage_vars.count(name) || iface_declarations.count(name)) - return false; - - VariableDeclaration* iface_var = new VariableDeclaration; - iface_var->sampling = var.sampling; - iface_var->interface = iface; - iface_var->type = var.type; - iface_var->type_declaration = var.type_declaration; - iface_var->name = name; - if(stage->type==GEOMETRY) - iface_var->array = ((var.array && var.interface!="in") || iface=="in"); - else - iface_var->array = var.array; - if(iface_var->array) - iface_var->array_size = var.array_size; - if(iface=="in") - iface_var->linked_declaration = &var; - iface_declarations[name] = iface_var; - - return true; -} - -void ProgramCompiler::InterfaceGenerator::insert_assignment(const string &left, ProgramSyntax::Expression *right) -{ - Assignment *assign = new Assignment; - VariableReference *ref = new VariableReference; - ref->name = left; - assign->left = ref; - assign->oper = "="; - assign->right = right; - - ExpressionStatement *stmt = new ExpressionStatement; - stmt->expression = assign; - insert_nodes.push_back(stmt); -} - -void ProgramCompiler::InterfaceGenerator::visit(VariableReference &var) -{ - if(var.declaration || !stage->previous) - return; - if(iface_declarations.count(var.name)) - return; - - const map &prev_out = stage->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) - stage->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") - { - stage->in_variables[var.name] = &var; - if(var.linked_declaration) - var.linked_declaration->linked_declaration = &var; - else if(stage->previous) - { - const map &prev_out = stage->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) -{ - vector pass_vars; - - for(map::const_iterator i=stage->in_variables.begin(); i!=stage->in_variables.end(); ++i) - pass_vars.push_back(i->second); - for(map::const_iterator i=iface_declarations.begin(); i!=iface_declarations.end(); ++i) - if(i->second->interface=="in") - pass_vars.push_back(i->second); - - if(stage->previous) - { - const map &prev_out = stage->previous->out_variables; - for(map::const_iterator i=prev_out.begin(); i!=prev_out.end(); ++i) - { - bool linked = false; - for(vector::const_iterator j=pass_vars.begin(); (!linked && j!=pass_vars.end()); ++j) - linked = ((*j)->linked_declaration==i->second); - - if(!linked && generate_interface(*i->second, "in", i->second->name)) - pass_vars.push_back(i->second); - } - } - - if(stage->type==GEOMETRY) - { - VariableReference *ref = new VariableReference; - ref->name = "gl_in"; - - BinaryExpression *subscript = new BinaryExpression; - subscript->left = ref; - subscript->oper = "["; - subscript->right = pass.subscript; - subscript->after = "]"; - - MemberAccess *memacc = new MemberAccess; - memacc->left = subscript; - memacc->member = "gl_Position"; - - insert_assignment("gl_Position", memacc); - } - - for(vector::const_iterator i=pass_vars.begin(); i!=pass_vars.end(); ++i) - { - string out_name = change_prefix((*i)->name, out_prefix); - generate_interface(**i, "out", out_name); - - VariableReference *ref = new VariableReference; - ref->name = (*i)->name; - 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); -} - - -ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(): - variable_values(0), - result(0.0f), - result_valid(false) -{ } - -ProgramCompiler::ExpressionEvaluator::ExpressionEvaluator(const ValueMap &v): - variable_values(&v), - result(0.0f), - result_valid(false) -{ } - -void ProgramCompiler::ExpressionEvaluator::visit(Literal &literal) -{ - if(literal.token=="true") - result = 1.0f; - else if(literal.token=="false") - result = 0.0f; - else - result = lexical_cast(literal.token); - result_valid = true; -} - -void ProgramCompiler::ExpressionEvaluator::visit(VariableReference &var) -{ - if(!var.declaration) - return; - - if(variable_values) - { - ValueMap::const_iterator i = variable_values->find(var.declaration); - if(i!=variable_values->end()) - i->second->visit(*this); - } - else if(var.declaration->init_expression) - var.declaration->init_expression->visit(*this); -} - -void ProgramCompiler::ExpressionEvaluator::visit(UnaryExpression &unary) -{ - result_valid = false; - unary.expression->visit(*this); - if(!result_valid) - return; - - if(unary.oper=="!") - result = !result; - else - result_valid = false; -} - -void ProgramCompiler::ExpressionEvaluator::visit(BinaryExpression &binary) -{ - result_valid = false; - binary.left->visit(*this); - if(!result_valid) - return; - - float left_result = result; - result_valid = false; - binary.right->visit(*this); - if(!result_valid) - return; - - if(binary.oper=="<") - result = (left_result") - result = (left_result>result); - else if(binary.oper==">=") - result = (left_result>=result); - else if(binary.oper=="==") - result = (left_result==result); - else if(binary.oper=="!=") - result = (left_result!=result); - else if(binary.oper=="&&") - result = (left_result && result); - else if(binary.oper=="||") - result = (left_result || result); - else - result_valid = false; -} - - -ProgramCompiler::ConstantConditionEliminator::ConstantConditionEliminator(): - scope_level(0) -{ } - -void ProgramCompiler::ConstantConditionEliminator::visit(Block &block) -{ - SetForScope set(scope_level, scope_level+1); - BlockModifier::visit(block); - - for(map::const_iterator i=block.variables.begin(); i!=block.variables.end(); ++i) - variable_values.erase(i->second); -} - -void ProgramCompiler::ConstantConditionEliminator::visit(Assignment &assign) -{ - variable_values.erase(assign.target_declaration); -} - -void ProgramCompiler::ConstantConditionEliminator::visit(VariableDeclaration &var) -{ - if(var.constant || scope_level>1) - variable_values[&var] = &*var.init_expression; -} - -void ProgramCompiler::ConstantConditionEliminator::visit(Conditional &cond) -{ - ExpressionEvaluator eval(variable_values); - cond.condition->visit(eval); - if(eval.result_valid) - flatten_block(eval.result ? cond.body : cond.else_body); - else - TraversingVisitor::visit(cond); -} - -void ProgramCompiler::ConstantConditionEliminator::visit(Iteration &iter) -{ - if(iter.condition) - { - ExpressionEvaluator eval; - iter.condition->visit(eval); - if(eval.result_valid && !eval.result) - { - remove_node = true; - return; - } - } - - TraversingVisitor::visit(iter); -} - - -ProgramCompiler::UnusedVariableLocator::UnusedVariableLocator(): - aggregate(0), - assignment(0), - assignment_target(false) -{ } - -void ProgramCompiler::UnusedVariableLocator::apply(Stage &s) -{ - assignments.push_back(BlockAssignmentMap()); - Visitor::apply(s); - assignments.pop_back(); -} - -void ProgramCompiler::UnusedVariableLocator::visit(VariableReference &var) -{ - unused_nodes.erase(var.declaration); - - map::iterator i = aggregates.find(var.declaration); - if(i!=aggregates.end()) - unused_nodes.erase(i->second); - - if(assignment_target) - return; - - for(vector::iterator j=assignments.end(); j!=assignments.begin(); ) - { - --j; - BlockAssignmentMap::iterator k = j->find(var.declaration); - if(k!=j->end()) - { - for(vector::iterator l=k->second.nodes.begin(); l!=k->second.nodes.end(); ++l) - unused_nodes.erase(*l); - j->erase(k); - break; - } - } -} - -void ProgramCompiler::UnusedVariableLocator::visit(MemberAccess &memacc) -{ - TraversingVisitor::visit(memacc); - unused_nodes.erase(memacc.declaration); -} - -void ProgramCompiler::UnusedVariableLocator::visit(BinaryExpression &binary) -{ - if(binary.oper=="[") - { - binary.left->visit(*this); - SetForScope set(assignment_target, false); - binary.right->visit(*this); - } - else - TraversingVisitor::visit(binary); -} - -void ProgramCompiler::UnusedVariableLocator::visit(Assignment &assign) -{ - { - SetForScope set(assignment_target, !assign.self_referencing); - assign.left->visit(*this); - } - assign.right->visit(*this); - assignment = &assign; -} - -void ProgramCompiler::UnusedVariableLocator::record_assignment(VariableDeclaration &var, Node &node, bool self_ref) -{ - unused_nodes.insert(&node); - BlockAssignmentMap &block_assignments = assignments.back(); - AssignmentList &var_assignments = block_assignments[&var]; - if(!self_ref) - var_assignments.nodes.clear(); - var_assignments.nodes.push_back(&node); - var_assignments.conditional = false; - var_assignments.self_referencing = self_ref; -} - -void ProgramCompiler::UnusedVariableLocator::visit(ExpressionStatement &expr) -{ - assignment = 0; - TraversingVisitor::visit(expr); - if(assignment && assignment->target_declaration) - record_assignment(*assignment->target_declaration, expr, assignment->self_referencing); -} - -void ProgramCompiler::UnusedVariableLocator::visit(StructDeclaration &strct) -{ - SetForScope set(aggregate, &strct); - unused_nodes.insert(&strct); - TraversingVisitor::visit(strct); -} - -void ProgramCompiler::UnusedVariableLocator::visit(VariableDeclaration &var) -{ - if(aggregate) - aggregates[&var] = aggregate; - else - { - unused_nodes.insert(&var); - if(var.init_expression) - record_assignment(var, *var.init_expression, false); - } - unused_nodes.erase(var.type_declaration); - TraversingVisitor::visit(var); -} - -void ProgramCompiler::UnusedVariableLocator::visit(InterfaceBlock &iface) -{ - SetForScope set(aggregate, &iface); - unused_nodes.insert(&iface); - TraversingVisitor::visit(iface); -} - -void ProgramCompiler::UnusedVariableLocator::visit(FunctionDeclaration &func) -{ - assignments.push_back(BlockAssignmentMap()); - - for(vector >::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) - (*i)->visit(*this); - func.body.visit(*this); - - BlockAssignmentMap &block_assignments = assignments.back(); - for(map::iterator i=func.body.variables.begin(); i!=func.body.variables.end(); ++i) - block_assignments.erase(i->second); - for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i) - { - if(i->first->interface=="out" && stage->type!=FRAGMENT && !i->first->linked_declaration) - continue; - - for(vector::iterator j=i->second.nodes.begin(); j!=i->second.nodes.end(); ++j) - unused_nodes.erase(*j); - } - - assignments.pop_back(); -} - -void ProgramCompiler::UnusedVariableLocator::merge_down_assignments() -{ - BlockAssignmentMap &parent_assignments = assignments[assignments.size()-2]; - BlockAssignmentMap &block_assignments = assignments.back(); - for(BlockAssignmentMap::iterator i=block_assignments.begin(); i!=block_assignments.end(); ++i) - { - BlockAssignmentMap::iterator j = parent_assignments.find(i->first); - if(j==parent_assignments.end()) - parent_assignments.insert(*i); - else if(i->second.self_referencing || i->second.conditional) - { - j->second.nodes.insert(j->second.nodes.end(), i->second.nodes.begin(), i->second.nodes.end()); - j->second.conditional |= i->second.conditional; - j->second.self_referencing |= i->second.self_referencing; - } - else - j->second = i->second; - } - assignments.pop_back(); -} - -void ProgramCompiler::UnusedVariableLocator::visit(Conditional &cond) -{ - cond.condition->visit(*this); - assignments.push_back(BlockAssignmentMap()); - cond.body.visit(*this); - - BlockAssignmentMap if_assignments; - swap(assignments.back(), if_assignments); - cond.else_body.visit(*this); - - BlockAssignmentMap &else_assignments = assignments.back(); - for(BlockAssignmentMap::iterator i=else_assignments.begin(); i!=else_assignments.end(); ++i) - { - BlockAssignmentMap::iterator j = if_assignments.find(i->first); - if(j!=if_assignments.end()) - { - i->second.nodes.insert(i->second.nodes.end(), j->second.nodes.begin(), j->second.nodes.end()); - i->second.conditional |= j->second.conditional; - i->second.self_referencing |= j->second.self_referencing; - if_assignments.erase(j); - } - else - i->second.conditional = true; - } - - for(BlockAssignmentMap::iterator i=if_assignments.begin(); i!=if_assignments.end(); ++i) - { - i->second.conditional = true; - else_assignments.insert(*i); - } - - merge_down_assignments(); -} - -void ProgramCompiler::UnusedVariableLocator::visit(Iteration &iter) -{ - assignments.push_back(BlockAssignmentMap()); - TraversingVisitor::visit(iter); - merge_down_assignments(); -} - - -void ProgramCompiler::UnusedFunctionLocator::visit(FunctionCall &call) -{ - TraversingVisitor::visit(call); - - unused_nodes.erase(call.declaration); - if(call.declaration && call.declaration->definition!=call.declaration) - used_definitions.insert(call.declaration->definition); -} - -void ProgramCompiler::UnusedFunctionLocator::visit(FunctionDeclaration &func) -{ - TraversingVisitor::visit(func); - - if(func.name!="main" && !used_definitions.count(&func)) - unused_nodes.insert(&func); -} - - -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(); ) - { - (*i)->visit(*this); - if(to_remove.count(&**i)) - block.body.erase(i++); - else - ++i; - } -} - -void ProgramCompiler::NodeRemover::visit(VariableDeclaration &var) -{ - if(to_remove.count(&var)) - { - stage->in_variables.erase(var.name); - stage->out_variables.erase(var.name); - stage->locations.erase(var.name); - if(var.linked_declaration) - var.linked_declaration->linked_declaration = 0; - } - else if(var.init_expression && to_remove.count(&*var.init_expression)) - var.init_expression = 0; -} - - -ProgramCompiler::LegacyConverter::LegacyConverter(): - target_version(get_glsl_version()) -{ } - -ProgramCompiler::LegacyConverter::LegacyConverter(const Version &v): - target_version(v) -{ } - -bool ProgramCompiler::LegacyConverter::check_version(const Version &feature_version) -{ - if(target_versionrequired_versionrequired_version = feature_version; - - return true; -} - -void ProgramCompiler::LegacyConverter::visit(VariableReference &var) -{ - if(var.name==frag_out_name && !check_version(Version(1, 30))) - { - var.name = "gl_FragColor"; - var.declaration = 0; - type = "vec4"; - } - else if(var.declaration) - type = var.declaration->type; - else - type = string(); -} - -void ProgramCompiler::LegacyConverter::visit(FunctionCall &call) -{ - if(call.name=="texture" && !call.declaration && !check_version(Version(1, 30))) - { - vector >::iterator i = call.arguments.begin(); - if(i!=call.arguments.end()) - { - (*i)->visit(*this); - if(type=="sampler1D") - call.name = "texture1D"; - else if(type=="sampler2D") - call.name = "texture2D"; - else if(type=="sampler3D") - call.name = "texture3D"; - else if(type=="sampler1DShadow") - call.name = "shadow1D"; - else if(type=="sampler2DShadow") - call.name = "shadow2D"; - - for(; i!=call.arguments.end(); ++i) - (*i)->visit(*this); - } - } - else - TraversingVisitor::visit(call); -} - -void ProgramCompiler::LegacyConverter::visit(VariableDeclaration &var) -{ - if(var.layout && !check_version(Version(3, 30))) - { - vector::iterator i; - for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ; - if(i!=var.layout->qualifiers.end()) - { - unsigned location = lexical_cast(i->value); - if(stage->type==VERTEX && var.interface=="in") - { - stage->locations[var.name] = location; - var.layout->qualifiers.erase(i); - } - else if(stage->type==FRAGMENT && var.interface=="out") - { - stage->locations[var.name] = location; - var.layout->qualifiers.erase(i); - } - - if(var.layout->qualifiers.empty()) - var.layout = 0; - } - } - - if((var.interface=="in" || var.interface=="out") && !check_version(Version(1, 30))) - { - if(stage->type==VERTEX && var.interface=="in") - var.interface = "attribute"; - else if((stage->type==VERTEX && var.interface=="out") || (stage->type==FRAGMENT && var.interface=="in")) - var.interface = "varying"; - else if(stage->type==FRAGMENT && var.interface=="out") - { - frag_out_name = var.name; - remove_node = true; - } - } - - TraversingVisitor::visit(var); -} - -void ProgramCompiler::LegacyConverter::visit(InterfaceBlock &iface) -{ - if(!check_version(Version(1, 50))) - flatten_block(iface.members); -} - -} // namespace GL -} // namespace Msp