]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/optimize.cpp
Use a temporary staging block in InlineContentInjector
[libs/gl.git] / source / glsl / optimize.cpp
index 7473fe2ca598ad996ee6c3263385f938986e80e2..668f7c5ef2553d399feef9c6c60949990fa54150 100644 (file)
@@ -66,18 +66,15 @@ void InlineableFunctionLocator::visit(Return &ret)
 
 InlineContentInjector::InlineContentInjector():
        source_func(0),
-       remap_names(false),
-       deps_only(false)
+       remap_names(0)
 { }
 
 const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_func, Block &tgt_blk, const NodeList<Statement>::iterator &ins_pt, FunctionDeclaration &src)
 {
-       target_block = &tgt_blk;
+       staging_block.parent = &tgt_blk;
        source_func = &src;
        remap_prefix = source_func->name;
 
-       vector<RefPtr<Statement> > inlined;
-       inlined.reserve(src.body.body.size());
        for(NodeList<Statement>::iterator i=src.body.body.begin(); i!=src.body.body.end(); ++i)
        {
                r_inlined_statement = 0;
@@ -87,18 +84,15 @@ const string &InlineContentInjector::apply(Stage &stage, FunctionDeclaration &ta
 
                SetForScope<unsigned> set_remap(remap_names, 2);
                r_inlined_statement->visit(*this);
-               inlined.push_back(r_inlined_statement);
+               staging_block.body.push_back(r_inlined_statement);
        }
 
-       // Insert the variables here to enable further inlinings to avoid conflicts.
-       tgt_blk.variables.insert(variable_map.begin(), variable_map.end());
-
        SetForScope<unsigned> set_remap(remap_names, 1);
        SetForScope<string> set_prefix(remap_prefix, target_func.name);
-       variable_map.clear();
+       staging_block.variables.clear();
        target_func.visit(*this);
 
-       tgt_blk.body.insert(ins_pt, inlined.begin(), inlined.end());
+       tgt_blk.body.splice(ins_pt, staging_block.body);
 
        NodeReorderer().apply(stage, target_func, dependencies);
 
@@ -109,14 +103,13 @@ void InlineContentInjector::visit(VariableReference &var)
 {
        if(remap_names)
        {
-               map<string, VariableDeclaration *>::const_iterator i = variable_map.find(var.name);
-               if(i!=variable_map.end())
+               map<string, VariableDeclaration *>::const_iterator i = staging_block.variables.find(var.name);
+               if(i!=staging_block.variables.end())
                        var.name = i->second->name;
        }
        else if(var.declaration)
        {
-               SetFlag set_deps(deps_only);
-               if(!variable_map.count(var.name))
+               if(!staging_block.variables.count(var.name))
                {
                        dependencies.insert(var.declaration);
                        referenced_names.insert(var.name);
@@ -129,7 +122,6 @@ void InlineContentInjector::visit(InterfaceBlockReference &iface)
 {
        if(!remap_names && iface.declaration)
        {
-               SetFlag set_deps(deps_only);
                dependencies.insert(iface.declaration);
                referenced_names.insert(iface.name);
                iface.declaration->visit(*this);
@@ -154,14 +146,15 @@ void InlineContentInjector::visit(VariableDeclaration &var)
        {
                if(remap_names==2 || referenced_names.count(var.name))
                {
-                       string mapped_name = get_unused_variable_name(*target_block, var.name, remap_prefix);
-                       variable_map[var.name] = &var;
+                       string mapped_name = get_unused_variable_name(staging_block, var.name, remap_prefix);
+                       staging_block.variables[var.name] = &var;
+                       if(mapped_name!=var.name)
+                               staging_block.variables[mapped_name] = &var;
                        var.name = mapped_name;
                }
        }
        else if(var.type_declaration)
        {
-               SetFlag set_deps(deps_only);
                dependencies.insert(var.type_declaration);
                referenced_names.insert(var.type_declaration->name);
                var.type_declaration->visit(*this);
@@ -176,7 +169,7 @@ void InlineContentInjector::visit(Return &ret)
        {
                /* Create a new variable to hold the return value of the inlined
                function. */
-               r_result_name = get_unused_variable_name(*target_block, "_return", source_func->name);
+               r_result_name = get_unused_variable_name(staging_block, "_return", source_func->name);
                RefPtr<VariableDeclaration> var = new VariableDeclaration;
                var->source = ret.source;
                var->line = ret.line;
@@ -190,7 +183,8 @@ void InlineContentInjector::visit(Return &ret)
 
 FunctionInliner::FunctionInliner():
        current_function(0),
-       r_any_inlined(false)
+       r_any_inlined(false),
+       r_inlined_here(false)
 { }
 
 bool FunctionInliner::apply(Stage &s)
@@ -218,7 +212,7 @@ void FunctionInliner::visit(Block &block)
 {
        SetForScope<Block *> set_block(current_block, &block);
        SetForScope<NodeList<Statement>::iterator> save_insert_point(insert_point, block.body.begin());
-       for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
+       for(NodeList<Statement>::iterator i=block.body.begin(); (!r_inlined_here && i!=block.body.end()); ++i)
        {
                insert_point = i;
                (*i)->visit(*this);
@@ -227,6 +221,9 @@ void FunctionInliner::visit(Block &block)
 
 void FunctionInliner::visit(FunctionCall &call)
 {
+       if(r_inlined_here)
+               return;
+
        for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
                visit(*i);
 
@@ -249,6 +246,7 @@ void FunctionInliner::visit(FunctionCall &call)
                /* Inlined variables need to be resolved before this function can be
                inlined further. */
                inlineable.erase(current_function);
+               r_inlined_here = true;
        }
 }
 
@@ -256,6 +254,7 @@ void FunctionInliner::visit(FunctionDeclaration &func)
 {
        SetForScope<FunctionDeclaration *> set_func(current_function, &func);
        TraversingVisitor::visit(func);
+       r_inlined_here = false;
 }
 
 void FunctionInliner::visit(Iteration &iter)