X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Foptimize.cpp;h=40d1c26f97f5f4886c2c3db4d28c9627aa499eb6;hb=518f751d385b733adbf43fe4056403740709edec;hp=208e17a39b49e6fe1fd92f10b31e65808e77068b;hpb=ab5f2e6f1ddd35f8f117460530d76c0ba0c9bc87;p=libs%2Fgl.git diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index 208e17a3..40d1c26f 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -14,7 +14,7 @@ InlineableFunctionLocator::InlineableFunctionLocator(): void InlineableFunctionLocator::visit(FunctionCall &call) { FunctionDeclaration *def = call.declaration; - if(def && def->definition!=def) + if(def) def = def->definition; if(def) @@ -39,14 +39,54 @@ void InlineableFunctionLocator::visit(FunctionDeclaration &func) } +void InlineDependencyCollector::visit(VariableReference &var) +{ + if(var.declaration) + { + dependencies.insert(var.declaration); + var.declaration->visit(*this); + } +} + +void InlineDependencyCollector::visit(InterfaceBlockReference &iface) +{ + if(iface.declaration) + { + dependencies.insert(iface.declaration); + iface.declaration->visit(*this); + } +} + +void InlineDependencyCollector::visit(FunctionCall &call) +{ + if(call.declaration) + dependencies.insert(call.declaration); + TraversingVisitor::visit(call); +} + +void InlineDependencyCollector::visit(VariableDeclaration &var) +{ + if(var.type_declaration) + { + dependencies.insert(var.type_declaration); + var.type_declaration->visit(*this); + } +} + + FunctionInliner::FunctionInliner(): - extract_result(0) + current_function(0), + extract_result(0), + any_inlined(false) { } -void FunctionInliner::apply(Stage &stage) +bool FunctionInliner::apply(Stage &s) { - inlineable = InlineableFunctionLocator().apply(stage); - visit(stage.content); + stage = &s; + inlineable = InlineableFunctionLocator().apply(s); + any_inlined = false; + s.content.visit(*this); + return any_inlined; } void FunctionInliner::visit_and_inline(RefPtr &ptr) @@ -54,7 +94,10 @@ void FunctionInliner::visit_and_inline(RefPtr &ptr) inline_result = 0; ptr->visit(*this); if(inline_result) + { ptr = inline_result; + any_inlined = true; + } } void FunctionInliner::visit(Block &block) @@ -95,13 +138,16 @@ void FunctionInliner::visit(FunctionCall &call) visit_and_inline(*i); FunctionDeclaration *def = call.declaration; - if(def && def->definition!=def) + if(def) def = def->definition; if(def && inlineable.count(def)) { extract_result = 2; def->visit(*this); + + if(inline_result) + NodeReorderer().apply(*stage, *current_function, InlineDependencyCollector().apply(*def)); } else inline_result = 0; @@ -114,6 +160,12 @@ void FunctionInliner::visit(VariableDeclaration &var) inline_result = 0; } +void FunctionInliner::visit(FunctionDeclaration &func) +{ + SetForScope set_func(current_function, &func); + TraversingVisitor::visit(func); +} + void FunctionInliner::visit(Return &ret) { TraversingVisitor::visit(ret); @@ -124,20 +176,17 @@ void FunctionInliner::visit(Return &ret) ConstantConditionEliminator::ConstantConditionEliminator(): - scope_level(0), - current_block(0), record_only(false) { } void ConstantConditionEliminator::apply(Stage &stage) { - visit(stage.content); + stage.content.visit(*this); NodeRemover().apply(stage, nodes_to_remove); } void ConstantConditionEliminator::visit(Block &block) { - SetForScope set(scope_level, scope_level+1); SetForScope set_block(current_block, &block); for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) { @@ -163,7 +212,13 @@ void ConstantConditionEliminator::visit(Assignment &assign) void ConstantConditionEliminator::visit(VariableDeclaration &var) { - if(var.constant || scope_level>1) + bool constant = var.constant; + if(constant && var.layout) + { + for(vector::const_iterator i=var.layout->qualifiers.begin(); (constant && i!=var.layout->qualifiers.end()); ++i) + constant = (i->name!="constant_id"); + } + if((constant || current_block->parent) && var.init_expression) variable_values[&var] = var.init_expression.get(); } @@ -228,14 +283,13 @@ UnusedVariableRemover::UnusedVariableRemover(): aggregate(0), assignment(0), assignment_target(false), - assign_to_subscript(false), - global_scope(true) + assign_to_subscript(false) { } bool UnusedVariableRemover::apply(Stage &stage) { variables.push_back(BlockVariableMap()); - visit(stage.content); + stage.content.visit(*this); BlockVariableMap &global_variables = variables.back(); for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i) { @@ -263,11 +317,16 @@ void UnusedVariableRemover::visit(VariableReference &var) if(var.declaration && !assignment_target) { VariableInfo &var_info = variables.back()[var.declaration]; - var_info.assignments.clear(); + clear_assignments(var_info, false); var_info.referenced = true; } } +void UnusedVariableRemover::visit(InterfaceBlockReference &iface) +{ + unused_nodes.erase(iface.declaration); +} + void UnusedVariableRemover::visit(MemberAccess &memacc) { TraversingVisitor::visit(memacc); @@ -358,12 +417,9 @@ void UnusedVariableRemover::visit(FunctionDeclaration &func) { variables.push_back(BlockVariableMap()); - { - SetForScope set(global_scope, false); - for(NodeArray::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) - (*i)->visit(*this); - func.body.visit(*this); - } + for(NodeArray::iterator i=func.parameters.begin(); i!=func.parameters.end(); ++i) + (*i)->visit(*this); + func.body.visit(*this); BlockVariableMap &block_variables = variables.back(); for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i) @@ -443,7 +499,7 @@ void UnusedVariableRemover::visit(Iteration &iter) BlockVariableMap &block_variables = variables.back(); for(BlockVariableMap::iterator i=block_variables.begin(); i!=block_variables.end(); ++i) if(!i->second.local && i->second.referenced) - i->second.assignments.clear(); + clear_assignments(i->second, false); merge_down_variables(); } @@ -451,7 +507,7 @@ void UnusedVariableRemover::visit(Iteration &iter) bool UnusedFunctionRemover::apply(Stage &stage) { - visit(stage.content); + stage.content.visit(*this); NodeRemover().apply(stage, unused_nodes); return !unused_nodes.empty(); }