X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Foptimize.cpp;h=7b3f8f28c8ad00007b520446ed5c2cc1180c49d0;hp=0d428149dcc667ca6a7990c5d760a9ca22ea9aee;hb=4fb346536bfefd612635a248f558b1f1471deae6;hpb=3e262649c1b98462bcaa2c66bc4fb4ee916dc9de diff --git a/source/glsl/optimize.cpp b/source/glsl/optimize.cpp index 0d428149..7b3f8f28 100644 --- a/source/glsl/optimize.cpp +++ b/source/glsl/optimize.cpp @@ -34,8 +34,12 @@ void InlineableFunctionLocator::visit(FunctionCall &call) void InlineableFunctionLocator::visit(FunctionDeclaration &func) { + bool has_out_params = false; + for(NodeArray::const_iterator i=func.parameters.begin(); (!has_out_params && i!=func.parameters.end()); ++i) + has_out_params = ((*i)->interface=="out"); + unsigned &count = refcounts[func.definition]; - if(count<=1 && func.parameters.empty()) + if(count<=1 && !has_out_params) inlineable.insert(func.definition); SetForScope set(current_function, &func); @@ -69,9 +73,9 @@ InlineContentInjector::InlineContentInjector(): pass(DEPENDS) { } -const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_func, Block &tgt_blk, const NodeList::iterator &ins_pt, FunctionDeclaration &src) +const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_func, Block &tgt_blk, const NodeList::iterator &ins_pt, FunctionCall &call) { - source_func = &src; + source_func = call.declaration->definition; // Collect all declarations the inlined function depends on. pass = DEPENDS; @@ -87,9 +91,22 @@ const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &ta pass = INLINE; staging_block.parent = &tgt_blk; staging_block.variables.clear(); - remap_prefix = source_func->name; - for(NodeList::iterator i=src.body.body.begin(); i!=src.body.body.end(); ++i) + std::vector > params; + params.reserve(source_func->parameters.size()); + for(NodeArray::iterator i=source_func->parameters.begin(); i!=source_func->parameters.end(); ++i) + { + RefPtr var = (*i)->clone(); + var->interface.clear(); + + SetForScope set_pass(pass, RENAME); + var->visit(*this); + + staging_block.body.push_back_nocopy(var); + params.push_back(var); + } + + for(NodeList::iterator i=source_func->body.body.begin(); i!=source_func->body.body.end(); ++i) { r_inlined_statement = 0; (*i)->visit(*this); @@ -99,8 +116,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 @@ -114,9 +130,12 @@ const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &ta global identifiers used by the source function. */ pass = RENAME; staging_block.parent = source_func->body.parent; - remap_prefix = target_func.name; target_func.visit(*this); + // Put the argument expressions in place after all renaming has been done. + for(unsigned i=0; iparameters.size(); ++i) + params[i]->init_expression = call.arguments[i]->clone(); + tgt_blk.body.splice(ins_pt, staging_block.body); NodeReorderer().apply(stage, target_func, dependencies); @@ -167,10 +186,13 @@ 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, remap_prefix); + string mapped_name = get_unused_variable_name(staging_block, var.name); if(mapped_name!=var.name) { staging_block.variables[mapped_name] = &var; @@ -194,7 +216,7 @@ void InlineContentInjector::visit(Return &ret) if(pass==INLINE && ret.expression) { // Create a new variable to hold the return value of the inlined function. - r_result_name = get_unused_variable_name(staging_block, "_return", source_func->name); + r_result_name = get_unused_variable_name(staging_block, "_return"); RefPtr var = new VariableDeclaration; var->source = ret.source; var->line = ret.line; @@ -246,23 +268,23 @@ 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; if(def && inlineable.count(def)) { - string result_name = InlineContentInjector().apply(*stage, *current_function, *current_block, insert_point, *def); + string result_name = InlineContentInjector().apply(*stage, *current_function, *current_block, insert_point, call); // This will later get removed by UnusedVariableRemover. if(result_name.empty()) - result_name = "msp_unused_from_inline"; + result_name = "_msp_unused_from_inline"; RefPtr ref = new VariableReference; ref->name = result_name; @@ -1097,7 +1119,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_"))); @@ -1119,7 +1141,7 @@ void UnusedVariableRemover::visit(InterfaceBlock &iface) else { VariableInfo &var_info = variables[&iface]; - var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.name.compare(0, 3, "gl_"))); + var_info.output = (iface.interface=="out" && (iface.linked_block || !iface.block_name.compare(0, 3, "gl_"))); } }