]> git.tdb.fi Git - libs/gl.git/commitdiff
Fix some issues with inlining variables in GLSL
authorMikko Rasa <tdb@tdb.fi>
Sun, 17 Dec 2023 10:44:51 +0000 (12:44 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 17 Dec 2023 10:44:51 +0000 (12:44 +0200)
source/glsl/optimize.cpp
source/glsl/optimize.h
tests/glsl/swap.glsl [new file with mode: 0644]

index 0086a072d8955483ad14f2248d68018f2ae5d226..6b2f1a0348ec1f8eaa8b380fc543c5a4a7f48e75 100644 (file)
@@ -351,6 +351,17 @@ bool ExpressionInliner::apply(Stage &s)
        return any_inlined;
 }
 
+void ExpressionInliner::visit(Block &block)
+{
+       TraversingVisitor::visit(block);
+
+       /* Block inlining of any assignments from the scope as we leave it.  They
+       may depend on local variables or might not always be executed. */
+       for(ExpressionInfo &e: expressions)
+               if(e.assign_scope==&block)
+                       e.blocked = true;
+}
+
 void ExpressionInliner::visit(NodePtr<Expression> &expr)
 {
        r_ref_info = nullptr;
@@ -371,11 +382,6 @@ void ExpressionInliner::visit(NodePtr<Expression> &expr)
                        for(Block *i=iteration_body->parent; (!use.blocked && i); i=i->parent)
                                use.blocked = (i==r_ref_info->assign_scope);
                }
-
-               /* Block inlining assignments from from inner scopes.  The assignment may
-               depend on local variables of that scope or may not always be executed. */
-               for(Block *i=r_ref_info->assign_scope->parent; (!use.blocked && i); i=i->parent)
-                       use.blocked = (i==current_block);
        }
        r_oper = expr->oper;
        r_ref_info = nullptr;
@@ -459,8 +465,16 @@ void ExpressionInliner::visit(Assignment &assign)
 
                for(; (i!=assignments.end() && i->first.declaration==assign.target.declaration); ++i)
                        if(targets_overlap(i->first, assign.target))
+                       {
                                i->second->blocked = true;
 
+                               /* Block further inlining of any expressions which used the
+                               previous value of this variable. */
+                               for(const ExpressionUse &u: i->second->uses)
+                                       if(u.containing_expr)
+                                               u.containing_expr->blocked = true;
+                       }
+
                info->trivial = r_trivial;
                assignments[assign.target] = info;
        }
index d3d475b636cef153ec1f3fa0f2b31c7ae1bf88c5..55b5e11ba3c77ec58da20730b91760ccac5a9ae6 100644 (file)
@@ -142,6 +142,7 @@ public:
        bool apply(Stage &);
 
 private:
+       void visit(Block &) override;
        void visit(NodePtr<Expression> &) override;
        void visit(VariableReference &) override;
        void visit(MemberAccess &) override;
diff --git a/tests/glsl/swap.glsl b/tests/glsl/swap.glsl
new file mode 100644 (file)
index 0000000..de7d525
--- /dev/null
@@ -0,0 +1,57 @@
+#pragma MSP stage(vertex)
+layout(location=0) in vec4 vertex;
+void main()
+{
+       float x = vertex.x;
+       float y = vertex.y;
+       float z = vertex.z;
+       if(x>y)
+       {
+               float temp = x;
+               x = y;
+               y = temp;
+       }
+       if(y>z)
+       {
+               float temp = y;
+               y = z;
+               z = temp;
+       }
+       if(x>y)
+       {
+               float temp = x;
+               x = y;
+               y = temp;
+       }
+       gl_Position = vec4(x, y, z, 1.0);
+}
+
+/* Expected output: vertex
+layout(location=0) in vec4 vertex;
+void main()
+{
+       float x = vertex.x;
+       float y = vertex.y;
+       float z = vertex.z;
+       if(x>y)
+       {
+               float temp = x;
+               x = y;
+               y = temp;
+       }
+       if(y>z)
+       {
+               float temp = y;
+               y = z;
+               z = temp;
+       }
+       if(x>y)
+       {
+               float temp = x;
+               x = y;
+               y = temp;
+       }
+       gl_Position = vec4(x, y, z, 1.0);
+       gl_Position.z = gl_Position.z*2.0-gl_Position.w;
+}
+*/