[Mesa-dev] [PATCH 15/16] glsl: Correctly determine when the field of a UBO is row-major

Ian Romanick idr at freedesktop.org
Mon Jul 21 14:04:31 PDT 2014


From: Ian Romanick <ian.d.romanick at intel.com>

Previously if a field of an block with an instance name was marked
row-major (but block itself was not), we would think the field (and it's
sub-fields) were column-major.

Fixes gles3conform failures in:

ES3-CTS.shaders.uniform_block.random.basic_types.7
ES3-CTS.shaders.uniform_block.random.basic_types.9
ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.1
ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.3
ES3-CTS.shaders.uniform_block.random.nested_structs.3
ES3-CTS.shaders.uniform_block.random.nested_structs.5
ES3-CTS.shaders.uniform_block.random.nested_structs.8
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.3
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.6
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.7
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.8
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.9
ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.0
ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.1
ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.2
ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.3
ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.4
ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.6
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.0
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.1
ES3-CTS.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.5
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.0
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.4
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.7
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.8
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.12
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.14
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.15
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.16
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.1
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.8
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.9
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.10
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.11
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.13
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.14
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.15
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.16
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.17

Fixes gles3conform failures (caused by previous commits) in:

ES3-CTS.shaders.uniform_block.random.basic_types.8
ES3-CTS.shaders.uniform_block.random.basic_arrays.3
ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.0
ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.2
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.9
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.13
ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.18
ES3-CTS.shaders.uniform_block.random.all_shared_buffer.4

Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
---
 src/glsl/lower_ubo_reference.cpp | 137 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 122 insertions(+), 15 deletions(-)

diff --git a/src/glsl/lower_ubo_reference.cpp b/src/glsl/lower_ubo_reference.cpp
index 99bfe97..0ee4e8a 100644
--- a/src/glsl/lower_ubo_reference.cpp
+++ b/src/glsl/lower_ubo_reference.cpp
@@ -40,6 +40,98 @@
 
 using namespace ir_builder;
 
+/**
+ * Determine if a thing being dereferenced is row-major
+ *
+ * There is some trickery here.
+ *
+ * If the thing being dereferenced is a member of uniform block \b without an
+ * instance name, then the name of the \c ir_variable is the field name of an
+ * interface type.  If this field is row-major, then the thing referenced is
+ * row-major.
+ *
+ * If the thing being dereferenced is a member of uniform block \b with an
+ * instance name, then the last dereference in the tree will be an
+ * \c ir_dereference_record.  If that record field is row-major, then the
+ * thing referenced is row-major.
+ */
+static bool
+is_dereferenced_thing_row_major(const ir_dereference *deref)
+{
+   bool matrix = false;
+   const ir_rvalue *ir = deref;
+
+   while (true) {
+      if (ir->type->is_matrix()
+          || (ir->type->is_array() && ir->type->fields.array->is_matrix()))
+         matrix = true;
+
+      switch (ir->ir_type) {
+      case ir_type_dereference_array: {
+         const ir_dereference_array *const array_deref =
+            (const ir_dereference_array *) ir;
+
+         ir = array_deref->array;
+         break;
+      }
+
+      case ir_type_dereference_record: {
+         const ir_dereference_record *const record_deref =
+            (const ir_dereference_record *) ir;
+
+         ir = record_deref->record;
+
+         const int idx = ir->type->field_index(record_deref->field);
+         assert(idx >= 0);
+
+         const enum glsl_matrix_layout matrix_layout =
+            glsl_matrix_layout(ir->type->fields.structure[idx].matrix_layout);
+
+         switch (matrix_layout) {
+         case GLSL_MATRIX_LAYOUT_DEFAULT:
+            break;
+         case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
+            return false;
+         case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
+            return matrix || deref->type->is_record();
+         }
+
+         break;
+      }
+
+      case ir_type_dereference_variable: {
+         const ir_dereference_variable *const var_deref =
+            (const ir_dereference_variable *) ir;
+
+         const enum glsl_matrix_layout matrix_layout =
+            glsl_matrix_layout(var_deref->var->data.matrix_layout);
+
+         switch (matrix_layout) {
+         case GLSL_MATRIX_LAYOUT_DEFAULT:
+            assert(!matrix);
+            return false;
+         case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
+            return false;
+         case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
+            return matrix || deref->type->is_record();
+         }
+
+         unreachable("invalid matrix layout");
+         break;
+      }
+
+      default:
+         return false;
+      }
+   }
+
+   /* The tree must have ended with a dereference that wasn't an
+    * ir_dereference_variable.  That is invalid, and it should be impossible.
+    */
+   unreachable("invalid dereference tree");
+   return false;
+}
+
 namespace {
 class lower_ubo_reference_visitor : public ir_rvalue_enter_visitor {
 public:
@@ -50,7 +142,7 @@ public:
 
    void handle_rvalue(ir_rvalue **rvalue);
    void emit_ubo_loads(ir_dereference *deref, ir_variable *base_offset,
-		       unsigned int deref_offset);
+		       unsigned int deref_offset, bool row_major);
    ir_expression *ubo_load(const struct glsl_type *type,
 			   ir_rvalue *offset);
 
@@ -153,7 +245,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
 
    ir_rvalue *offset = new(mem_ctx) ir_constant(0u);
    unsigned const_offset = 0;
-   bool row_major = ubo_var->RowMajor;
+   bool row_major = is_dereferenced_thing_row_major(deref);
 
    /* Calculate the offset to the start of the region of the UBO
     * dereferenced by *rvalue.  This may be a variable offset if an
@@ -219,14 +311,24 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
 	 unsigned max_field_align = 16;
 	 for (unsigned int i = 0; i < struct_type->length; i++) {
 	    const glsl_type *type = struct_type->fields.structure[i].type;
-	    unsigned field_align = type->std140_base_alignment(row_major);
+
+            ir_dereference_record *field_deref =
+               new(mem_ctx) ir_dereference_record(deref_record->record,
+                                                  struct_type->fields.structure[i].name);
+            const bool field_row_major =
+               is_dereferenced_thing_row_major(field_deref);
+
+            ralloc_free(field_deref);
+
+            unsigned field_align = type->std140_base_alignment(field_row_major);
+
 	    max_field_align = MAX2(field_align, max_field_align);
 	    intra_struct_offset = glsl_align(intra_struct_offset, field_align);
 
 	    if (strcmp(struct_type->fields.structure[i].name,
 		       deref_record->field) == 0)
 	       break;
-	    intra_struct_offset += type->std140_size(row_major);
+            intra_struct_offset += type->std140_size(field_row_major);
 	 }
 
 	 const_offset = glsl_align(const_offset, max_field_align);
@@ -258,7 +360,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
    base_ir->insert_before(assign(load_offset, offset));
 
    deref = new(mem_ctx) ir_dereference_variable(load_var);
-   emit_ubo_loads(deref, load_offset, const_offset);
+   emit_ubo_loads(deref, load_offset, const_offset, row_major);
    *rvalue = deref;
 
    progress = true;
@@ -287,7 +389,8 @@ lower_ubo_reference_visitor::ubo_load(const glsl_type *type,
 void
 lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
 					    ir_variable *base_offset,
-					    unsigned int deref_offset)
+                                            unsigned int deref_offset,
+                                            bool row_major)
 {
    if (deref->type->is_record()) {
       unsigned int field_offset = 0;
@@ -301,18 +404,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
 
 	 field_offset =
 	    glsl_align(field_offset,
-		       field->type->std140_base_alignment(ubo_var->RowMajor));
+                       field->type->std140_base_alignment(row_major));
 
-	 emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset);
+	 emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset,
+                        row_major);
 
-	 field_offset += field->type->std140_size(ubo_var->RowMajor);
+	 field_offset += field->type->std140_size(row_major);
       }
       return;
    }
 
    if (deref->type->is_array()) {
       unsigned array_stride =
-	 glsl_align(deref->type->fields.array->std140_size(ubo_var->RowMajor),
+	 glsl_align(deref->type->fields.array->std140_size(row_major),
 		    16);
 
       for (unsigned i = 0; i < deref->type->length; i++) {
@@ -321,7 +425,8 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
 	    new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
 					      element);
 	 emit_ubo_loads(element_deref, base_offset,
-			deref_offset + i * array_stride);
+			deref_offset + i * array_stride,
+                        row_major);
       }
       return;
    }
@@ -333,16 +438,18 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
 	    new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
 					      col);
 
-         if (ubo_var->RowMajor) {
+         if (row_major) {
             /* For a row-major matrix, the next column starts at the next
              * element.
              */
-            emit_ubo_loads(col_deref, base_offset, deref_offset + i * 4);
+            emit_ubo_loads(col_deref, base_offset, deref_offset + i * 4,
+                           row_major);
          } else {
             /* std140 always rounds the stride of arrays (and matrices) to a
              * vec4, so matrices are always 16 between columns/rows.
              */
-            emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16);
+            emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16,
+                           row_major);
          }
       }
       return;
@@ -351,7 +458,7 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
    assert(deref->type->is_scalar() ||
 	  deref->type->is_vector());
 
-   if (!ubo_var->RowMajor) {
+   if (!row_major) {
       ir_rvalue *offset = add(base_offset,
 			      new(mem_ctx) ir_constant(deref_offset));
       base_ir->insert_before(assign(deref->clone(mem_ctx, NULL),
-- 
1.8.1.4



More information about the mesa-dev mailing list