]> git.tdb.fi Git - libs/gl.git/commitdiff
Fix GLSL matrix construction from individual elements
authorMikko Rasa <tdb@tdb.fi>
Sun, 7 Nov 2021 14:12:11 +0000 (16:12 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sun, 7 Nov 2021 14:13:55 +0000 (16:13 +0200)
source/glsl/resolve.cpp
tests/glsl/matrix_from_elements.glsl [new file with mode: 0644]

index eb99bec2ab57d9c801724b8803a3397e270ae363..406d7780e810181ffc8650e9c0ba8c20466d67aa 100644 (file)
@@ -972,6 +972,11 @@ void ExpressionResolver::visit_constructor(FunctionCall &call)
                {
                        unsigned column_count = basic->size&0xFFFF;
                        unsigned row_count = basic->size>>16;
+
+                       vector<RefPtr<Expression> > columns;
+                       columns.reserve(column_count);
+                       bool changed_columns = false;
+
                        if(call.arguments.size()==1)
                        {
                                /* A matrix can be constructed from a single element or another
@@ -994,8 +999,6 @@ void ExpressionResolver::visit_constructor(FunctionCall &call)
                                        current_block->body.insert(insert_point, temporary);
 
                                        // Create expressions to build each column.
-                                       vector<RefPtr<Expression> > columns;
-                                       columns.reserve(column_count);
                                        for(unsigned j=0; j<column_count; ++j)
                                        {
                                                RefPtr<VariableReference> ref = new VariableReference;
@@ -1016,13 +1019,7 @@ void ExpressionResolver::visit_constructor(FunctionCall &call)
                                                        truncate_vector(columns.back(), row_count);
                                        }
 
-                                       call.arguments.resize(column_count);
-                                       copy(columns.begin(), columns.end(), call.arguments.begin());
-
-                                       /* Let VariableResolver process the new nodes and finish
-                                       resolving the constructor on the next pass. */
-                                       r_any_resolved = true;
-                                       return;
+                                       changed_columns = true;
                                }
                                else
                                        return;
@@ -1031,9 +1028,6 @@ void ExpressionResolver::visit_constructor(FunctionCall &call)
                        {
                                /* Construct a matrix from individual components in column-major
                                order.  Arguments must align at column boundaries. */
-                               vector<RefPtr<Expression> > columns;
-                               columns.reserve(column_count);
-
                                vector<RefPtr<Expression> > column_args;
                                column_args.reserve(row_count);
                                unsigned column_component_count = 0;
@@ -1067,11 +1061,24 @@ void ExpressionResolver::visit_constructor(FunctionCall &call)
                                                else if(column_component_count>row_count)
                                                        // Argument alignment mismatch.
                                                        return;
+
+                                               changed_columns = true;
                                        }
                                }
                        }
                        else
                                return;
+
+                       if(changed_columns)
+                       {
+                               call.arguments.resize(column_count);
+                               copy(columns.begin(), columns.end(), call.arguments.begin());
+
+                               /* Let VariableResolver process the new nodes and finish
+                               resolving the constructor on the next pass. */
+                               r_any_resolved = true;
+                               return;
+                       }
                }
                else
                        return;
diff --git a/tests/glsl/matrix_from_elements.glsl b/tests/glsl/matrix_from_elements.glsl
new file mode 100644 (file)
index 0000000..42b1655
--- /dev/null
@@ -0,0 +1,31 @@
+uniform Transform
+{
+       vec3 translation;
+       float rotation;
+};
+
+#pragma MSP stage(vertex)
+layout(location=0) in vec2 position;
+void main()
+{
+       float c = cos(rotation);
+       float s = sin(rotation);
+       mat3 m = mat3(c, s, 0.0, -s, c, 0.0, translation);
+       gl_Position = vec4((m*vec3(position, 1.0)).xy, 0.0, 1.0);
+}
+
+/* Expected output: vertex
+layout(binding=48) uniform Transform
+{
+       vec3 translation;
+       float rotation;
+};
+layout(location=0) in vec2 position;
+void main()
+{
+       float c = cos(rotation);
+       float s = sin(rotation);
+
+       gl_Position = vec4((mat3(vec3(c, s, 0.0), vec3(-s, c, 0.0), translation)*vec3(position, 1.0)).xy, 0.0, 1.0);
+}
+*/