glsl: Reject row_major and column_major on non-matrix types
authorIan Romanick <ian.d.romanick@intel.com>
Wed, 16 Jan 2013 20:01:50 +0000 (12:01 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Sat, 19 Jan 2013 01:35:32 +0000 (17:35 -0800)
About both row_major and column_major layout qualifiers, the GLSL spec
says:

    "It only affects the layout of matrices."

However, the OpenGL ES 3.0 conformance tests have taken this to mean it
is an error use it elsewhere.  This seems logical given that
'layout(row_major) vec4 foo' is probably not what the programmer meant.

The only catch is dealing with structures that contain matrices.  Layout
qualifiers cannot be applied directly to fields of structures, so the
only way to affect the layout of the fields is to apply a qualifier to
the structure declaration itself.  There is ongoing debate about this
within Khronos, and it seems to be settling in favor of allowing the
qualifiers on structures.  I light of this, I have chosen to allow the
qualifiers on structures but emit a warning since the usage may not be
portable.

Fixes gles3conform test
uniform_buffer_object_layouts_not_for_matrix_type and causes no
regressions.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/glsl/ast_to_hir.cpp

index f934c8e2d301edb3970bde8183f6aa5bdaa0c043..ea5e3b773e380049ab01fa6c7733b0c0dbc09561 100644 (file)
@@ -1933,6 +1933,31 @@ is_varying_var(ir_variable *var, _mesa_glsl_parser_targets target)
 }
 
 
+/**
+ * Matrix layout qualifiers are only allowed on certain types
+ */
+static void
+validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state,
+                               YYLTYPE *loc,
+                               const glsl_type *type)
+{
+   if (!type->is_matrix() && !type->is_record()) {
+      _mesa_glsl_error(loc, state,
+                       "uniform block layout qualifiers row_major and "
+                       "column_major can only be applied to matrix and "
+                       "structure types");
+   } else if (type->is_record()) {
+      /* We allow 'layout(row_major)' on structure types because it's the only
+       * way to get row-major layouts on matrices contained in structures.
+       */
+      _mesa_glsl_warning(loc, state,
+                         "uniform block layout qualifiers row_major and "
+                         "column_major applied to structure types is not "
+                         "strictly conformant and my be rejected by other "
+                         "compilers");
+   }
+}
+
 static void
 apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                                 ir_variable *var,
@@ -2251,12 +2276,14 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
                       "members");
    }
 
-   if (!ubo_qualifiers_valid &&
-       (qual->flags.q.row_major || qual->flags.q.column_major)) {
-      _mesa_glsl_error(loc, state,
-                       "uniform block layout qualifiers row_major and "
-                      "column_major can only be applied to uniform block "
-                      "members");
+   if (qual->flags.q.row_major || qual->flags.q.column_major) {
+      if (!ubo_qualifiers_valid) {
+        _mesa_glsl_error(loc, state,
+                         "uniform block layout qualifiers row_major and "
+                         "column_major can only be applied to uniform block "
+                         "members");
+      } else
+        validate_matrix_layout_for_type(state, loc, var->type);
    }
 }