]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/optimize.cpp
Recognize swizzles in GLSL
[libs/gl.git] / source / glsl / optimize.cpp
index 1aad8d1b311adcecf27904b8e29efb49892d98a6..414cf38754191a85d8b6643811c3dc5c4764f4b4 100644 (file)
@@ -202,6 +202,7 @@ void FunctionInliner::visit_and_inline(RefPtr<Expression> &ptr)
                ptr = r_inline_result;
                r_any_inlined = true;
        }
+       r_inline_result = 0;
 }
 
 void FunctionInliner::visit(Block &block)
@@ -218,20 +219,22 @@ void FunctionInliner::visit(Block &block)
 void FunctionInliner::visit(UnaryExpression &unary)
 {
        visit_and_inline(unary.expression);
-       r_inline_result = 0;
 }
 
 void FunctionInliner::visit(BinaryExpression &binary)
 {
        visit_and_inline(binary.left);
        visit_and_inline(binary.right);
-       r_inline_result = 0;
 }
 
 void FunctionInliner::visit(MemberAccess &memacc)
 {
        visit_and_inline(memacc.left);
-       r_inline_result = 0;
+}
+
+void FunctionInliner::visit(Swizzle &swizzle)
+{
+       visit_and_inline(swizzle.left);
 }
 
 void FunctionInliner::visit(FunctionCall &call)
@@ -259,8 +262,6 @@ void FunctionInliner::visit(FunctionCall &call)
                inlined further. */
                inlineable.erase(current_function);
        }
-       else
-               r_inline_result = 0;
 }
 
 void FunctionInliner::visit(ExpressionStatement &expr)
@@ -272,7 +273,6 @@ void FunctionInliner::visit(VariableDeclaration &var)
 {
        if(var.init_expression)
                visit_and_inline(var.init_expression);
-       r_inline_result = 0;
 }
 
 void FunctionInliner::visit(FunctionDeclaration &func)
@@ -364,6 +364,7 @@ void ExpressionInliner::visit_and_record(RefPtr<Expression> &ptr, const Operator
                        r_ref_info->inline_on_rhs = on_rhs;
                }
        }
+       r_ref_info = 0;
 }
 
 void ExpressionInliner::inline_expression(Expression &expr, RefPtr<Expression> &ptr, const Operator *outer_oper, const Operator *inner_oper, bool on_rhs)
@@ -439,16 +440,21 @@ void ExpressionInliner::visit(VariableReference &var)
 void ExpressionInliner::visit(MemberAccess &memacc)
 {
        visit_and_record(memacc.left, memacc.oper, false);
-       r_ref_info = 0;
        r_oper = memacc.oper;
        r_trivial = false;
 }
 
+void ExpressionInliner::visit(Swizzle &swizzle)
+{
+       visit_and_record(swizzle.left, swizzle.oper, false);
+       r_oper = swizzle.oper;
+       r_trivial = false;
+}
+
 void ExpressionInliner::visit(UnaryExpression &unary)
 {
        SetFlag set_target(mutating, mutating || unary.oper->token[1]=='+' || unary.oper->token[1]=='-');
        visit_and_record(unary.expression, unary.oper, false);
-       r_ref_info = 0;
        r_oper = unary.oper;
        r_trivial = false;
 }
@@ -460,7 +466,6 @@ void ExpressionInliner::visit(BinaryExpression &binary)
                SetFlag clear_target(mutating, false);
                visit_and_record(binary.right, binary.oper, true);
        }
-       r_ref_info = 0;
        r_oper = binary.oper;
        r_trivial = false;
 }
@@ -489,7 +494,6 @@ void ExpressionInliner::visit(Assignment &assign)
                }
        }
 
-       r_ref_info = 0;
        r_oper = assign.oper;
        r_trivial = false;
 }
@@ -498,7 +502,6 @@ void ExpressionInliner::visit(FunctionCall &call)
 {
        for(NodeArray<Expression>::iterator i=call.arguments.begin(); i!=call.arguments.end(); ++i)
                visit_and_record(*i, 0, false);
-       r_ref_info = 0;
        r_oper = 0;
        r_trivial = false;
 }
@@ -677,6 +680,11 @@ void UnusedTypeRemover::visit(VariableDeclaration &var)
        unused_nodes.erase(var.type_declaration);
 }
 
+void UnusedTypeRemover::visit(InterfaceBlock &iface)
+{
+       unused_nodes.erase(iface.type_declaration);
+}
+
 void UnusedTypeRemover::visit(FunctionDeclaration &func)
 {
        unused_nodes.erase(func.return_type_declaration);
@@ -699,9 +707,19 @@ bool UnusedVariableRemover::apply(Stage &stage)
        BlockVariableMap &global_variables = variables.back();
        for(BlockVariableMap::iterator i=global_variables.begin(); i!=global_variables.end(); ++i)
        {
+               string interface = i->first->interface;
+               bool linked = i->first->linked_declaration;
+               map<VariableDeclaration *, Node *>::iterator j = aggregates.find(i->first);
+               if(j!=aggregates.end())
+                       if(InterfaceBlock *iface = dynamic_cast<InterfaceBlock *>(j->second))
+                       {
+                               interface = iface->interface;
+                               linked = iface->linked_block;
+                       }
+
                /* Don't remove output variables which are used by the next stage or the
                graphics API. */
-               if(i->first->interface=="out" && (stage.type==Stage::FRAGMENT || i->first->linked_declaration || !i->first->name.compare(0, 3, "gl_")))
+               if(interface=="out" && (stage.type==Stage::FRAGMENT || linked || !i->first->name.compare(0, 3, "gl_")))
                        continue;
 
                // Mark other unreferenced global variables as unused.
@@ -746,6 +764,13 @@ void UnusedVariableRemover::visit(MemberAccess &memacc)
        unused_nodes.erase(memacc.declaration);
 }
 
+void UnusedVariableRemover::visit(Swizzle &swizzle)
+{
+       if(assignment_target)
+               r_assign_to_subfield = true;
+       TraversingVisitor::visit(swizzle);
+}
+
 void UnusedVariableRemover::visit(UnaryExpression &unary)
 {
        TraversingVisitor::visit(unary);
@@ -842,7 +867,7 @@ void UnusedVariableRemover::visit(InterfaceBlock &iface)
 {
        SetForScope<Node *> set(aggregate, &iface);
        unused_nodes.insert(&iface);
-       TraversingVisitor::visit(iface);
+       iface.struct_declaration->members.visit(*this);
 }
 
 void UnusedVariableRemover::visit(FunctionDeclaration &func)