]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/optimize.cpp
Recognize backwards dependencies in GLSL loops
[libs/gl.git] / source / glsl / optimize.cpp
index 0139ec5fbec94d4f1c47493549914d8977b2af8e..b1201e9fb84cec84c8a7236121963f982cfa43cb 100644 (file)
@@ -1056,7 +1056,8 @@ UnusedVariableRemover::UnusedVariableRemover():
        assignment_target(false),
        r_side_effects(false),
        in_struct(false),
-       composite_reference(false)
+       composite_reference(false),
+       in_loop(0)
 { }
 
 bool UnusedVariableRemover::apply(Stage &s)
@@ -1100,6 +1101,7 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n
        var_info.referenced = true;
        if(!assignment_target)
        {
+               bool loop_external = false;
                for(vector<AssignmentInfo *>::const_iterator i=var_info.assignments.begin(); i!=var_info.assignments.end(); ++i)
                {
                        bool covered = true;
@@ -1123,9 +1125,17 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n
                                else
                                        covered = ((*i)->target.chain[j]==target.chain[j]);
                        }
+
                        if(covered)
+                       {
                                (*i)->used_by.push_back(&node);
+                               if((*i)->in_loop<in_loop)
+                                       loop_external = true;
+                       }
                }
+
+               if(loop_external)
+                       loop_ext_refs.push_back(&node);
        }
 }
 
@@ -1247,6 +1257,7 @@ void UnusedVariableRemover::record_assignment(const Assignment::Target &target,
        AssignmentInfo &assign_info = assignments.back();
        assign_info.node = &node;
        assign_info.target = target;
+       assign_info.in_loop = in_loop;
 
        /* An assignment to the target hides any assignments to the same target or
        its subfields. */
@@ -1378,7 +1389,18 @@ void UnusedVariableRemover::visit(Conditional &cond)
 void UnusedVariableRemover::visit(Iteration &iter)
 {
        BlockVariableMap saved_vars = variables;
-       TraversingVisitor::visit(iter);
+       vector<Node *> saved_refs;
+       swap(loop_ext_refs, saved_refs);
+       {
+               SetForScope<unsigned> set_loop(in_loop, in_loop+1);
+               TraversingVisitor::visit(iter);
+       }
+       swap(loop_ext_refs, saved_refs);
+
+       /* Visit the external references of the loop again to record assignments
+       done in the loop as used. */
+       for(vector<Node *>::const_iterator i=saved_refs.begin(); i!=saved_refs.end(); ++i)
+               (*i)->visit(*this);
 
        /* Merge assignments from the iteration, without clearing previous state.
        Further analysis is needed to determine which parts of the iteration body