]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/optimize.cpp
Refactor a common part in LocationAllocator into a function
[libs/gl.git] / source / glsl / optimize.cpp
index 42e4a86ec7feb3466f7e0a119b4bf1a4feb28916..96a75d603d6db5bdaaae35de41bbe16fb938cecf 100644 (file)
@@ -356,7 +356,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 +402,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 +428,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 +441,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 +454,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;
@@ -717,6 +721,11 @@ void AggregateDismantler::visit(VariableDeclaration &var)
        }
 }
 
+void AggregateDismantler::visit(FunctionDeclaration &func)
+{
+       func.body.visit(*this);
+}
+
 
 template<typename T>
 T ConstantFolder::evaluate_logical(char oper, T left, T right)
@@ -1255,23 +1264,15 @@ bool UnusedVariableRemover::apply(Stage &s)
 
        for(const auto &kvp: variables)
        {
-               if(kvp.second.output)
+               if(!kvp.second.referenced)
+                       unused_nodes.insert(kvp.first);
+               else if(kvp.second.output)
                {
                        /* The last visible assignments of output variables are used by the
                        next stage or the API. */
                        for(AssignmentInfo *a: kvp.second.assignments)
                                unused_nodes.erase(a->node);
                }
-
-               if(!kvp.second.output && !kvp.second.referenced)
-               {
-                       // Don't remove variables from inside interface blocks.
-                       if(!kvp.second.interface_block)
-                               unused_nodes.insert(kvp.first);
-               }
-               else if(kvp.second.interface_block)
-                       // Interface blocks are kept if even one member is used.
-                       unused_nodes.erase(kvp.second.interface_block);
        }
 
        NodeRemover().apply(s, unused_nodes);
@@ -1287,36 +1288,12 @@ void UnusedVariableRemover::referenced(const Assignment::Target &target, Node &n
        {
                bool loop_external = false;
                for(AssignmentInfo *a: var_info.assignments)
-               {
-                       bool covered = true;
-                       for(unsigned j=0; (covered && j<a->target.chain_len && j<target.chain_len); ++j)
-                       {
-                               Assignment::Target::ChainType type1 = static_cast<Assignment::Target::ChainType>(a->target.chain[j]&0xC0);
-                               Assignment::Target::ChainType type2 = static_cast<Assignment::Target::ChainType>(target.chain[j]&0xC0);
-                               unsigned index1 = a->target.chain[j]&0x3F;
-                               unsigned index2 = target.chain[j]&0x3F;
-                               if(type1==Assignment::Target::SWIZZLE || type2==Assignment::Target::SWIZZLE)
-                               {
-                                       if(type1==Assignment::Target::SWIZZLE && type2==Assignment::Target::SWIZZLE)
-                                               covered = index1&index2;
-                                       else if(type1==Assignment::Target::ARRAY && index1<4)
-                                               covered = index2&(1<<index1);
-                                       else if(type2==Assignment::Target::ARRAY && index2<4)
-                                               covered = index1&(1<<index2);
-                                       /* If it's some other combination (shouldn't happen), leave
-                                       covered as true */
-                               }
-                               else
-                                       covered = (type1==type2 && (index1==index2 || index1==0x3F || index2==0x3F));
-                       }
-
-                       if(covered)
+                       if(targets_overlap(a->target, target))
                        {
                                a->used_by.push_back(&node);
                                if(a->in_loop<in_loop)
                                        loop_external = true;
                        }
-               }
 
                if(loop_external)
                        loop_ext_refs.push_back(&node);
@@ -1327,7 +1304,7 @@ void UnusedVariableRemover::visit(VariableReference &var)
 {
        if(composite_reference)
                r_reference.declaration = var.declaration;
-       else
+       else if(var.declaration)
                referenced(var.declaration, var);
 }
 
@@ -1335,7 +1312,7 @@ void UnusedVariableRemover::visit(InterfaceBlockReference &iface)
 {
        if(composite_reference)
                r_reference.declaration = iface.declaration;
-       else
+       else if(iface.declaration)
                referenced(iface.declaration, iface);
 }
 
@@ -1387,6 +1364,7 @@ void UnusedVariableRemover::visit(BinaryExpression &binary)
                {
                        SetFlag clear_assignment(assignment_target, false);
                        SetFlag clear_composite(composite_reference, false);
+                       SetForScope<Assignment::Target> clear_reference(r_reference, Assignment::Target());
                        binary.right->visit(*this);
                }
 
@@ -1488,14 +1466,14 @@ void UnusedVariableRemover::visit(VariableDeclaration &var)
                return;
 
        VariableInfo &var_info = variables[&var];
-       var_info.interface_block = interface_block;
 
        /* 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->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_")));
+       var_info.output = (var.interface=="out" && (stage->type==Stage::FRAGMENT || var.linked_declaration || !var.name.compare(0, 3, "gl_")));
+
+       // Linked outputs are automatically referenced.
+       if(var_info.output && var.linked_declaration)
+               var_info.referenced = true;
 
        if(var.init_expression)
        {
@@ -1576,8 +1554,14 @@ void UnusedVariableRemover::visit(Iteration &iter)
        vector<Node *> saved_refs;
        swap(loop_ext_refs, saved_refs);
        {
+               if(iter.init_statement)
+                       iter.init_statement->visit(*this);
                SetForScope<unsigned> set_loop(in_loop, in_loop+1);
-               TraversingVisitor::visit(iter);
+               if(iter.condition)
+                       iter.condition->visit(*this);
+               iter.body.visit(*this);
+               if(iter.loop_expression)
+                       iter.loop_expression->visit(*this);
        }
        swap(loop_ext_refs, saved_refs);