glsl: Track matrix layout of variables using two bits
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 18 Jul 2014 18:23:06 +0000 (11:23 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 4 Aug 2014 21:40:07 +0000 (14:40 -0700)
Fixes gles3conform failures in:

ES3-CTS.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.3
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.13

Causes gles3conform failures in:

ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.9

This failure will be fixed shortly.

v2: Use without_array() instead of older predicates.

v3: s/GLSL_MATRIX_LAYOUT_DEFAULT/GLSL_MATRIX_LAYOUT_INHERITED/g

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com> [v1]
src/glsl/ast_to_hir.cpp
src/glsl/ir.h
src/glsl/link_uniform_blocks.cpp
src/glsl/link_uniforms.cpp

index d5699935e604270ed2be700af12c956b0cda99ce..b4670076f61b87f9db9a6f2ca01497456812aca8 100644 (file)
@@ -5072,7 +5072,7 @@ ast_process_structure_or_interface_block(exec_list *instructions,
                                          YYLTYPE &loc,
                                          glsl_struct_field **fields_ret,
                                          bool is_interface,
-                                         bool block_row_major,
+                                         enum glsl_matrix_layout matrix_layout,
                                          bool allow_reserved_names,
                                          ir_variable_mode var_mode)
 {
@@ -5210,13 +5210,22 @@ ast_process_structure_or_interface_block(exec_list *instructions,
           */
          if (field_type->without_array()->is_matrix()
              || field_type->without_array()->is_record()) {
-            fields[i].matrix_layout = block_row_major
-               ? GLSL_MATRIX_LAYOUT_ROW_MAJOR
-               : GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
+            /* If no layout is specified for the field, inherit the layout
+             * from the block.
+             */
+            fields[i].matrix_layout = matrix_layout;
+
             if (qual->flags.q.row_major)
                fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR;
             else if (qual->flags.q.column_major)
                fields[i].matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
+
+            /* If we're processing an interface block, the matrix layout must
+             * be decided by this point.
+             */
+            assert(!is_interface
+                   || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR
+                   || fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR);
          }
 
          i++;
@@ -5271,7 +5280,7 @@ ast_struct_specifier::hir(exec_list *instructions,
                                                loc,
                                                &fields,
                                                false,
-                                               false,
+                                               GLSL_MATRIX_LAYOUT_INHERITED,
                                                false /* allow_reserved_names */,
                                                ir_var_auto);
 
@@ -5371,8 +5380,13 @@ ast_interface_block::hir(exec_list *instructions,
       assert(!"interface block layout qualifier not found!");
    }
 
+   enum glsl_matrix_layout matrix_layout = GLSL_MATRIX_LAYOUT_INHERITED;
+   if (this->layout.flags.q.row_major)
+      matrix_layout = GLSL_MATRIX_LAYOUT_ROW_MAJOR;
+   else if (this->layout.flags.q.column_major)
+      matrix_layout = GLSL_MATRIX_LAYOUT_COLUMN_MAJOR;
+
    bool redeclaring_per_vertex = strcmp(this->block_name, "gl_PerVertex") == 0;
-   bool block_row_major = this->layout.flags.q.row_major;
    exec_list declared_variables;
    glsl_struct_field *fields;
 
@@ -5388,7 +5402,7 @@ ast_interface_block::hir(exec_list *instructions,
                                                loc,
                                                &fields,
                                                true,
-                                               block_row_major,
+                                               matrix_layout,
                                                redeclaring_per_vertex,
                                                var_mode);
 
@@ -5596,6 +5610,9 @@ ast_interface_block::hir(exec_list *instructions,
                                       var_mode);
       }
 
+      var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
+         ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
+
       if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
          handle_geometry_shader_input_decl(state, loc, var);
 
@@ -5636,6 +5653,13 @@ ast_interface_block::hir(exec_list *instructions,
          var->data.sample = fields[i].sample;
          var->init_interface_type(block_type);
 
+         if (fields[i].matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED) {
+            var->data.matrix_layout = matrix_layout == GLSL_MATRIX_LAYOUT_INHERITED
+               ? GLSL_MATRIX_LAYOUT_COLUMN_MAJOR : matrix_layout;
+         } else {
+            var->data.matrix_layout = fields[i].matrix_layout;
+         }
+
          if (fields[i].stream != -1 &&
              ((unsigned)fields[i].stream) != this->layout.stream) {
             _mesa_glsl_error(&loc, state,
index de28f87e63b1c53e4078b76ac96a9bdb64c965d0..49f74face65631af7627292098b52a3915281b40 100644 (file)
@@ -659,6 +659,11 @@ public:
        */
       unsigned location_frac:2;
 
+      /**
+       * Layout of the matrix.  Uses glsl_matrix_layout values.
+       */
+      unsigned matrix_layout:2;
+
       /**
        * Non-zero if this variable was created by lowering a named interface
        * block which was not an array.
index 3768205ee1f138c7c47f168cba1429092cc0e182..536fcd45878c164b79a3357b12a58281af3ebb29 100644 (file)
@@ -77,7 +77,7 @@ private:
 
       v->Name = ralloc_strdup(mem_ctx, name);
       v->Type = type;
-      v->RowMajor = row_major;
+      v->RowMajor = type->without_array()->is_matrix() && row_major;
 
       if (this->is_array_instance) {
          v->IndexName = ralloc_strdup(mem_ctx, name);
index 5137e3a3910c9864c56db7f0ccb44e814d1005f8..ecd414b8ceb41c2b946bf56956f38af54e1372b8 100644 (file)
@@ -71,6 +71,8 @@ void
 program_resource_visitor::process(ir_variable *var)
 {
    const glsl_type *t = var->type;
+   const bool row_major =
+      var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR;
 
    /* false is always passed for the row_major parameter to the other
     * processing functions because no information is available to do
@@ -108,7 +110,7 @@ program_resource_visitor::process(ir_variable *var)
           * lowering is only applied to non-uniform interface blocks, so we
           * can safely pass false for row_major.
           */
-         recursion(var->type, &name, new_length, false, NULL, false);
+         recursion(var->type, &name, new_length, row_major, NULL, false);
       }
       ralloc_free(name);
    } else if (var->data.from_named_ifc_block_nonarray) {
@@ -132,22 +134,22 @@ program_resource_visitor::process(ir_variable *var)
        * is only applied to non-uniform interface blocks, so we can safely
        * pass false for row_major.
        */
-      recursion(var->type, &name, strlen(name), false, NULL, false);
+      recursion(var->type, &name, strlen(name), row_major, NULL, false);
       ralloc_free(name);
    } else if (t->without_array()->is_record()) {
       char *name = ralloc_strdup(NULL, var->name);
-      recursion(var->type, &name, strlen(name), false, NULL, false);
+      recursion(var->type, &name, strlen(name), row_major, NULL, false);
       ralloc_free(name);
    } else if (t->is_interface()) {
       char *name = ralloc_strdup(NULL, var->type->name);
-      recursion(var->type, &name, strlen(name), false, NULL, false);
+      recursion(var->type, &name, strlen(name), row_major, NULL, false);
       ralloc_free(name);
    } else if (t->is_array() && t->fields.array->is_interface()) {
       char *name = ralloc_strdup(NULL, var->type->fields.array->name);
-      recursion(var->type, &name, strlen(name), false, NULL, false);
+      recursion(var->type, &name, strlen(name), row_major, NULL, false);
       ralloc_free(name);
    } else {
-      this->visit_field(t, var->name, false, NULL, false);
+      this->visit_field(t, var->name, row_major, NULL, false);
    }
 }
 
@@ -181,8 +183,23 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
             ralloc_asprintf_rewrite_tail(name, &new_length, ".%s", field);
          }
 
+         /* The layout of structures at the top level of the block is set
+          * during parsing.  For matrices contained in multiple levels of
+          * structures in the block, the inner structures have no layout.
+          * These cases must potentially inherit the layout from the outer
+          * levels.
+          */
+         bool field_row_major = row_major;
+         const enum glsl_matrix_layout matrix_layout =
+            glsl_matrix_layout(t->fields.structure[i].matrix_layout);
+         if (matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR) {
+            field_row_major = true;
+         } else if (matrix_layout == GLSL_MATRIX_LAYOUT_COLUMN_MAJOR) {
+            field_row_major = false;
+         }
+
          recursion(t->fields.structure[i].type, name, new_length,
-                   t->fields.structure[i].matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR,
+                   field_row_major,
                    record_type,
                    (i + 1) == t->length);