X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Foptimize.cpp;h=927047cc7c1e387890bf4a3d1a4a784e2039c7ac;hb=3415ed0f925d781df9d8243e0f4c454516b1c450;hp=d57002552540c6c375cb7446f8465a9538a0a42d;hpb=22d5405729048ee2677a1e45e309e6328de64a26;p=libs%2Fgl.git diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index d5700255..927047cc 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -1,6 +1,7 @@ #include #include #include "optimize.h" +#include "reflect.h" using namespace std; @@ -8,6 +9,55 @@ namespace Msp { namespace GL { namespace SL { +ConstantSpecializer::ConstantSpecializer(): + values(0) +{ } + +void ConstantSpecializer::apply(Stage &stage, const map &v) +{ + values = &v; + stage.content.visit(*this); +} + +void ConstantSpecializer::visit(VariableDeclaration &var) +{ + bool specializable = false; + if(var.layout) + { + vector &qualifiers = var.layout->qualifiers; + for(vector::iterator i=qualifiers.begin(); (!specializable && i!=qualifiers.end()); ++i) + if(i->name=="constant_id") + { + specializable = true; + qualifiers.erase(i); + } + + if(qualifiers.empty()) + var.layout = 0; + } + + if(specializable) + { + map::const_iterator i = values->find(var.name); + if(i!=values->end()) + { + RefPtr literal = new Literal; + if(var.type=="bool") + { + literal->token = (i->second ? "true" : "false"); + literal->value = static_cast(i->second); + } + else if(var.type=="int") + { + literal->token = lexical_cast(i->second); + literal->value = i->second; + } + var.init_expression = literal; + } + } +} + + InlineableFunctionLocator::InlineableFunctionLocator(): current_function(0), return_count(0) @@ -70,17 +120,13 @@ void InlineableFunctionLocator::visit(Return &ret) InlineContentInjector::InlineContentInjector(): source_func(0), - pass(DEPENDS) + pass(REFERENCED) { } -const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_func, Block &tgt_blk, const NodeList::iterator &ins_pt, FunctionCall &call) +string InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_func, Block &tgt_blk, const NodeList::iterator &ins_pt, FunctionCall &call) { source_func = call.declaration->definition; - // Collect all declarations the inlined function depends on. - pass = DEPENDS; - source_func->visit(*this); - /* Populate referenced_names from the target function so we can rename variables from the inlined function that would conflict. */ pass = REFERENCED; @@ -102,8 +148,7 @@ const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &ta SetForScope set_pass(pass, RENAME); var->visit(*this); - staging_block.body.push_back(0); - staging_block.body.back() = var; + staging_block.body.push_back_nocopy(var); params.push_back(var); } @@ -117,8 +162,7 @@ const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &ta SetForScope set_pass(pass, RENAME); r_inlined_statement->visit(*this); - staging_block.body.push_back(0); - staging_block.body.back() = r_inlined_statement; + staging_block.body.push_back_nocopy(r_inlined_statement); } /* Now collect names from the staging block. Local variables that would @@ -140,7 +184,7 @@ const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &ta tgt_blk.body.splice(ins_pt, staging_block.body); - NodeReorderer().apply(stage, target_func, dependencies); + NodeReorderer().apply(stage, target_func, DependencyCollector().apply(*source_func)); return r_result_name; } @@ -153,31 +197,19 @@ void InlineContentInjector::visit(VariableReference &var) if(i!=staging_block.variables.end()) var.name = i->second->name; } - else if(pass==DEPENDS && var.declaration) - { - dependencies.insert(var.declaration); - var.declaration->visit(*this); - } else if(pass==REFERENCED) referenced_names.insert(var.name); } void InlineContentInjector::visit(InterfaceBlockReference &iface) { - if(pass==DEPENDS && iface.declaration) - { - dependencies.insert(iface.declaration); - iface.declaration->visit(*this); - } - else if(pass==REFERENCED) + if(pass==REFERENCED) referenced_names.insert(iface.name); } void InlineContentInjector::visit(FunctionCall &call) { - if(pass==DEPENDS && call.declaration) - dependencies.insert(call.declaration); - else if(pass==REFERENCED) + if(pass==REFERENCED) referenced_names.insert(call.name); TraversingVisitor::visit(call); } @@ -188,8 +220,11 @@ void InlineContentInjector::visit(VariableDeclaration &var) if(pass==RENAME) { + /* Check against conflicts with the other context as well as variables + already renamed here. */ + bool conflict = (staging_block.variables.count(var.name) || referenced_names.count(var.name)); staging_block.variables[var.name] = &var; - if(referenced_names.count(var.name)) + if(conflict) { string mapped_name = get_unused_variable_name(staging_block, var.name); if(mapped_name!=var.name) @@ -199,11 +234,6 @@ void InlineContentInjector::visit(VariableDeclaration &var) } } } - else if(pass==DEPENDS && var.type_declaration) - { - dependencies.insert(var.type_declaration); - var.type_declaration->visit(*this); - } else if(pass==REFERENCED) referenced_names.insert(var.type); } @@ -267,12 +297,12 @@ void FunctionInliner::visit(Block &block) void FunctionInliner::visit(FunctionCall &call) { + for(NodeArray::iterator i=call.arguments.begin(); (!r_inlined_here && i!=call.arguments.end()); ++i) + visit(*i); + if(r_inlined_here) return; - for(NodeArray::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i) - visit(*i); - FunctionDeclaration *def = call.declaration; if(def) def = def->definition; @@ -318,15 +348,6 @@ void FunctionInliner::visit(Iteration &iter) } -ExpressionInliner::ExpressionInfo::ExpressionInfo(): - expression(0), - assign_scope(0), - inline_point(0), - trivial(false), - available(true) -{ } - - ExpressionInliner::ExpressionInliner(): r_ref_info(0), r_any_inlined(false), @@ -893,33 +914,10 @@ bool UnusedTypeRemover::apply(Stage &stage) return !unused_nodes.empty(); } -void UnusedTypeRemover::visit(Literal &literal) -{ - unused_nodes.erase(literal.type); -} - -void UnusedTypeRemover::visit(UnaryExpression &unary) -{ - unused_nodes.erase(unary.type); - TraversingVisitor::visit(unary); -} - -void UnusedTypeRemover::visit(BinaryExpression &binary) +void UnusedTypeRemover::visit(RefPtr &expr) { - unused_nodes.erase(binary.type); - TraversingVisitor::visit(binary); -} - -void UnusedTypeRemover::visit(TernaryExpression &ternary) -{ - unused_nodes.erase(ternary.type); - TraversingVisitor::visit(ternary); -} - -void UnusedTypeRemover::visit(FunctionCall &call) -{ - unused_nodes.erase(call.type); - TraversingVisitor::visit(call); + unused_nodes.erase(expr->type); + TraversingVisitor::visit(expr); } void UnusedTypeRemover::visit(BasicTypeDeclaration &type) @@ -945,6 +943,7 @@ void UnusedTypeRemover::visit(StructDeclaration &strct) void UnusedTypeRemover::visit(VariableDeclaration &var) { unused_nodes.erase(var.type_declaration); + TraversingVisitor::visit(var); } void UnusedTypeRemover::visit(InterfaceBlock &iface) @@ -964,7 +963,8 @@ UnusedVariableRemover::UnusedVariableRemover(): interface_block(0), r_assignment(0), assignment_target(false), - r_side_effects(false) + r_side_effects(false), + composite_reference(false) { } bool UnusedVariableRemover::apply(Stage &s) @@ -976,10 +976,6 @@ bool UnusedVariableRemover::apply(Stage &s) if(i->used_by.empty()) unused_nodes.insert(i->node); - for(map::const_iterator i=s.interface_blocks.begin(); i!=s.interface_blocks.end(); ++i) - if(i->second->instance_name.empty()) - unused_nodes.insert(i->second); - for(BlockVariableMap::const_iterator i=variables.begin(); i!=variables.end(); ++i) { if(i->second.output) @@ -1013,18 +1009,80 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n if(!assignment_target) { for(vector::const_iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i) - (*i)->used_by.push_back(&node); + { + bool covered = true; + for(unsigned j=0; (covered && j<(*i)->target.chain_len && j((*i)->target.chain[j]&0xC0); + Assignment::Target::ChainType type2 = static_cast(target.chain[j]&0xC0); + if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE) + { + unsigned index1 = (*i)->target.chain[j]&0x3F; + unsigned index2 = target.chain[j]&0x3F; + if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE) + covered = index1&index2; + else if(type1==Assignment::Target::ARRAY && index1<4) + covered = index2&(1<target.chain[j]==target.chain[j]); + } + if(covered) + (*i)->used_by.push_back(&node); + } } } void UnusedVariableRemover::visit(VariableReference &var) { - referenced(var.declaration, var); + if(composite_reference) + r_reference.declaration = var.declaration; + else + referenced(var.declaration, var); } void UnusedVariableRemover::visit(InterfaceBlockReference &iface) { - referenced(iface.declaration, iface); + if(composite_reference) + r_reference.declaration = iface.declaration; + else + referenced(iface.declaration, iface); +} + +void UnusedVariableRemover::visit_composite(Expression &expr) +{ + if(!composite_reference) + r_reference = Assignment::Target(); + + SetFlag set_composite(composite_reference); + expr.visit(*this); +} + +void UnusedVariableRemover::visit(MemberAccess &memacc) +{ + visit_composite(*memacc.left); + + add_to_chain(r_reference, Assignment::Target::MEMBER, memacc.index); + + if(!composite_reference && r_reference.declaration) + referenced(r_reference, memacc); +} + +void UnusedVariableRemover::visit(Swizzle &swizzle) +{ + visit_composite(*swizzle.left); + + unsigned mask = 0; + for(unsigned i=0; itoken[0]=='[') { - binary.left->visit(*this); - SetFlag set(assignment_target, false); - binary.right->visit(*this); + visit_composite(*binary.left); + + { + SetFlag clear_assignment(assignment_target, false); + SetFlag clear_composite(composite_reference, false); + binary.right->visit(*this); + } + + add_to_chain(r_reference, Assignment::Target::ARRAY, 0x3F); + + if(!composite_reference && r_reference.declaration) + referenced(r_reference, binary); } else + { + SetFlag clear_composite(composite_reference, false); TraversingVisitor::visit(binary); + } +} + +void UnusedVariableRemover::visit(TernaryExpression &ternary) +{ + SetFlag clear_composite(composite_reference, false); + TraversingVisitor::visit(ternary); } void UnusedVariableRemover::visit(Assignment &assign) @@ -1059,6 +1135,7 @@ void UnusedVariableRemover::visit(Assignment &assign) void UnusedVariableRemover::visit(FunctionCall &call) { + SetFlag clear_composite(composite_reference, false); TraversingVisitor::visit(call); /* Treat function calls as having side effects so expression statements consisting of nothing but a function call won't be optimized away. */ @@ -1118,7 +1195,7 @@ void UnusedVariableRemover::visit(VariableDeclaration &var) /* Mark variables as output if they're used by the next stage or the graphics API. */ if(interface_block) - var_info.output = (interface_block->interface=="out" && (interface_block->linked_block || !interface_block->name.compare(0, 3, "gl_"))); + var_info.output = (interface_block->interface=="out" && (interface_block->linked_block || !interface_block->block_name.compare(0, 3, "gl_"))); else var_info.output = (var.interface=="out" && (stage->type==Stage::FRAGMENT || var.linked_declaration || !var.name.compare(0, 3, "gl_"))); @@ -1132,16 +1209,8 @@ void UnusedVariableRemover::visit(VariableDeclaration &var) void UnusedVariableRemover::visit(InterfaceBlock &iface) { - if(iface.instance_name.empty()) - { - SetForScope set_block(interface_block, &iface); - iface.struct_declaration->members.visit(*this); - } - else - { - VariableInfo &var_info = variables[&iface]; - var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.name.compare(0, 3, "gl_"))); - } + VariableInfo &var_info = variables[&iface]; + var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.block_name.compare(0, 3, "gl_"))); } void UnusedVariableRemover::merge_variables(const BlockVariableMap &other_vars)