]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/optimize.cpp
Fix a name conflict in certain inlining scenarios
[libs/gl.git] / source / glsl / optimize.cpp
index a7f29a16f8991c6342b6e3dcc1de6882da695a7b..64ceddcc16ba92968c2f0d517f0230bb8e739598 100644 (file)
@@ -114,9 +114,13 @@ string InlineContentInjector::apply(Stage &stage, FunctionDeclaration &target_fu
        source_func = call.declaration->definition;
 
        /* Populate referenced_names from the target function so we can rename
-       variables from the inlined function that would conflict. */
+       variables from the inlined function that would conflict.  Only consider
+       names which declared in blocks linearly related to the target block. */
        pass = REFERENCED;
-       target_func.visit(*this);
+       tgt_blk.visit(*this);
+       for(const Block *b=&tgt_blk; b; b=b->parent)
+               for(const auto &kvp: b->variables)
+                       referenced_names.insert(kvp.first);
 
        /* Inline and rename passes must be interleaved so used variable names are
        known when inlining the return statement. */
@@ -356,7 +360,7 @@ void ExpressionInliner::visit(RefPtr<Expression> &expr)
                ExpressionUse use;
                use.reference = &expr;
                use.ref_scope = current_block;
-               use.blocked = access_write;
+               use.blocked = access_write || r_ref_info->blocked;
 
                if(iteration_body && !r_ref_info->trivial)
                {
@@ -402,7 +406,7 @@ void ExpressionInliner::visit(Swizzle &swizzle)
 
 void ExpressionInliner::visit(UnaryExpression &unary)
 {
-       SetFlag set_write(access_write, access_write || unary.oper->token[1]=='+' || unary.oper->token[1]=='-');
+       SetFlag set_write(access_write, (unary.oper->token[1]=='+' || unary.oper->token[1]=='-'));
        visit(unary.expression);
        r_trivial = false;
 }
@@ -428,10 +432,10 @@ void ExpressionInliner::visit(Assignment &assign)
        r_trivial = true;
        visit(assign.right);
 
-       auto i = assignments.find(assign.target);
+       auto i = assignments.find(assign.target.declaration);
        if(i!=assignments.end())
        {
-               if(iteration_body && i->second->expression)
+               if(iteration_body && i->second && i->second->expression)
                {
                        /* Block inlining into previous references within the iteration
                        statement.  On iterations after the first they would refer to the
@@ -441,6 +445,10 @@ void ExpressionInliner::visit(Assignment &assign)
                                        u.blocked = (k==iteration_body);
                }
 
+               for(; (i!=assignments.end() && i->first.declaration==assign.target.declaration); ++i)
+                       if(targets_overlap(i->first, assign.target))
+                               i->second->blocked = true;
+
                expressions.push_back(ExpressionInfo());
                ExpressionInfo &info = expressions.back();
                info.target = assign.target;
@@ -450,7 +458,7 @@ void ExpressionInliner::visit(Assignment &assign)
                info.assign_scope = current_block;
                info.trivial = r_trivial;
 
-               i->second = &info;
+               assignments[assign.target] = &info;
        }
 
        r_trivial = false;