glsl: Add std430 support to program_resource_visitor's member functions
authorSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Fri, 4 Sep 2015 15:53:48 +0000 (17:53 +0200)
committerSamuel Iglesias Gonsalvez <siglesias@igalia.com>
Fri, 25 Sep 2015 06:39:22 +0000 (08:39 +0200)
They are used to calculate the offset, array stride of uniform/shader
storage buffer variables. Take into account this info to get the right
value for std430.

v2:
- Fix commit log line length and indention. (Jordan)

Signed-off-by: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
src/glsl/link_uniform_blocks.cpp
src/glsl/link_uniforms.cpp
src/glsl/linker.h

index c891d030234de34738585a3afe624346b1237590..8f65f4a3ab78d61912ae5276bd4b370544771296 100644 (file)
@@ -68,14 +68,18 @@ private:
    }
 
    virtual void enter_record(const glsl_type *type, const char *,
-                             bool row_major) {
+                             bool row_major, const unsigned packing) {
       assert(type->is_record());
-      this->offset = glsl_align(
+      if (packing == GLSL_INTERFACE_PACKING_STD430)
+         this->offset = glsl_align(
+            this->offset, type->std430_base_alignment(row_major));
+      else
+         this->offset = glsl_align(
             this->offset, type->std140_base_alignment(row_major));
    }
 
    virtual void leave_record(const glsl_type *type, const char *,
-                             bool row_major) {
+                             bool row_major, const unsigned packing) {
       assert(type->is_record());
 
       /* If this is the last field of a structure, apply rule #9.  The
@@ -85,12 +89,17 @@ private:
        *     the member following the sub-structure is rounded up to the next
        *     multiple of the base alignment of the structure."
        */
-      this->offset = glsl_align(
+      if (packing == GLSL_INTERFACE_PACKING_STD430)
+         this->offset = glsl_align(
+            this->offset, type->std430_base_alignment(row_major));
+      else
+         this->offset = glsl_align(
             this->offset, type->std140_base_alignment(row_major));
    }
 
    virtual void visit_field(const glsl_type *type, const char *name,
                             bool row_major, const glsl_type *,
+                            const unsigned packing,
                             bool /* last_field */)
    {
       assert(this->index < this->num_variables);
@@ -122,7 +131,7 @@ private:
       unsigned alignment = 0;
       unsigned size = 0;
 
-      if (v->Type->interface_packing == GLSL_INTERFACE_PACKING_STD430) {
+      if (packing == GLSL_INTERFACE_PACKING_STD430) {
          alignment = type->std430_base_alignment(v->RowMajor);
          size = type->std430_size(v->RowMajor);
       } else {
index 67a6e1bea170fb53c5d4673919e6e45cb81411ab..7d6b51de06d7a9e5b1212df4885a7fff10003138 100644 (file)
@@ -65,7 +65,9 @@ program_resource_visitor::process(const glsl_type *type, const char *name)
 
    unsigned record_array_count = 1;
    char *name_copy = ralloc_strdup(NULL, name);
-   recursion(type, &name_copy, strlen(name), false, NULL, false,
+   unsigned packing = type->interface_packing;
+
+   recursion(type, &name_copy, strlen(name), false, NULL, packing, false,
              record_array_count);
    ralloc_free(name_copy);
 }
@@ -78,6 +80,10 @@ program_resource_visitor::process(ir_variable *var)
    const bool row_major =
       var->data.matrix_layout == GLSL_MATRIX_LAYOUT_ROW_MAJOR;
 
+   const unsigned packing = var->get_interface_type() ?
+      var->get_interface_type()->interface_packing :
+      var->type->interface_packing;
+
    /* false is always passed for the row_major parameter to the other
     * processing functions because no information is available to do
     * otherwise.  See the warning in linker.h.
@@ -114,8 +120,8 @@ 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, row_major, NULL, false,
-                   record_array_count);
+         recursion(var->type, &name, new_length, row_major, NULL, packing,
+                   false, record_array_count);
       }
       ralloc_free(name);
    } else if (var->data.from_named_ifc_block_nonarray) {
@@ -139,26 +145,26 @@ 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), row_major, NULL, false,
-                record_array_count);
+      recursion(var->type, &name, strlen(name), row_major, NULL, packing,
+                false, record_array_count);
       ralloc_free(name);
    } else if (t->without_array()->is_record()) {
       char *name = ralloc_strdup(NULL, var->name);
-      recursion(var->type, &name, strlen(name), row_major, NULL, false,
-                record_array_count);
+      recursion(var->type, &name, strlen(name), row_major, NULL, packing,
+                false, record_array_count);
       ralloc_free(name);
    } else if (t->is_interface()) {
       char *name = ralloc_strdup(NULL, var->type->name);
-      recursion(var->type, &name, strlen(name), row_major, NULL, false,
-                record_array_count);
+      recursion(var->type, &name, strlen(name), row_major, NULL, packing,
+                false, record_array_count);
       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), row_major, NULL, false,
-                record_array_count);
+      recursion(var->type, &name, strlen(name), row_major, NULL, packing,
+                false, record_array_count);
       ralloc_free(name);
    } else {
-      this->visit_field(t, var->name, row_major, NULL, false);
+      this->visit_field(t, var->name, row_major, NULL, packing, false);
    }
 }
 
@@ -166,6 +172,7 @@ void
 program_resource_visitor::recursion(const glsl_type *t, char **name,
                                     size_t name_length, bool row_major,
                                     const glsl_type *record_type,
+                                    const unsigned packing,
                                     bool last_field,
                                     unsigned record_array_count)
 {
@@ -180,7 +187,7 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
          record_type = t;
 
       if (t->is_record())
-         this->enter_record(t, *name, row_major);
+         this->enter_record(t, *name, row_major, packing);
 
       for (unsigned i = 0; i < t->length; i++) {
         const char *field = t->fields.structure[i].name;
@@ -214,6 +221,7 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
          recursion(t->fields.structure[i].type, name, new_length,
                    field_row_major,
                    record_type,
+                   packing,
                    (i + 1) == t->length, record_array_count);
 
          /* Only the first leaf-field of the record gets called with the
@@ -224,7 +232,7 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
 
       if (t->is_record()) {
          (*name)[name_length] = '\0';
-         this->leave_record(t, *name, row_major);
+         this->leave_record(t, *name, row_major, packing);
       }
    } else if (t->is_array() && (t->fields.array->is_record()
                                 || t->fields.array->is_interface())) {
@@ -247,6 +255,7 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
 
          recursion(t->fields.array, name, new_length, row_major,
                    record_type,
+                   packing,
                    (i + 1) == t->length, record_array_count);
 
          /* Only the first leaf-field of the record gets called with the
@@ -256,7 +265,7 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
       }
    } else {
       this->set_record_array_count(record_array_count);
-      this->visit_field(t, *name, row_major, record_type, last_field);
+      this->visit_field(t, *name, row_major, record_type, packing, last_field);
    }
 }
 
@@ -264,6 +273,7 @@ void
 program_resource_visitor::visit_field(const glsl_type *type, const char *name,
                                       bool row_major,
                                       const glsl_type *,
+                                      const unsigned,
                                       bool /* last_field */)
 {
    visit_field(type, name, row_major);
@@ -277,12 +287,14 @@ program_resource_visitor::visit_field(const glsl_struct_field *field)
 }
 
 void
-program_resource_visitor::enter_record(const glsl_type *, const char *, bool)
+program_resource_visitor::enter_record(const glsl_type *, const char *, bool,
+                                       const unsigned)
 {
 }
 
 void
-program_resource_visitor::leave_record(const glsl_type *, const char *, bool)
+program_resource_visitor::leave_record(const glsl_type *, const char *, bool,
+                                       const unsigned)
 {
 }
 
@@ -677,25 +689,34 @@ private:
    }
 
    virtual void enter_record(const glsl_type *type, const char *,
-                             bool row_major) {
+                             bool row_major, const unsigned packing) {
       assert(type->is_record());
       if (this->ubo_block_index == -1)
          return;
-      this->ubo_byte_offset = glsl_align(
+      if (packing == GLSL_INTERFACE_PACKING_STD430)
+         this->ubo_byte_offset = glsl_align(
+            this->ubo_byte_offset, type->std430_base_alignment(row_major));
+      else
+         this->ubo_byte_offset = glsl_align(
             this->ubo_byte_offset, type->std140_base_alignment(row_major));
    }
 
    virtual void leave_record(const glsl_type *type, const char *,
-                             bool row_major) {
+                             bool row_major, const unsigned packing) {
       assert(type->is_record());
       if (this->ubo_block_index == -1)
          return;
-      this->ubo_byte_offset = glsl_align(
+      if (packing == GLSL_INTERFACE_PACKING_STD430)
+         this->ubo_byte_offset = glsl_align(
+            this->ubo_byte_offset, type->std430_base_alignment(row_major));
+      else
+         this->ubo_byte_offset = glsl_align(
             this->ubo_byte_offset, type->std140_base_alignment(row_major));
    }
 
    virtual void visit_field(const glsl_type *type, const char *name,
                             bool row_major, const glsl_type *record_type,
+                            const unsigned packing,
                             bool /* last_field */)
    {
       assert(!type->without_array()->is_record());
@@ -770,16 +791,25 @@ private:
          this->uniforms[id].storage = this->values;
 
       if (this->ubo_block_index != -1) {
-        this->uniforms[id].block_index = this->ubo_block_index;
-
-        const unsigned alignment = type->std140_base_alignment(row_major);
-        this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment);
-        this->uniforms[id].offset = this->ubo_byte_offset;
-        this->ubo_byte_offset += type->std140_size(row_major);
-
-        if (type->is_array()) {
-           this->uniforms[id].array_stride =
-              glsl_align(type->fields.array->std140_size(row_major), 16);
+         this->uniforms[id].block_index = this->ubo_block_index;
+
+         unsigned alignment = type->std140_base_alignment(row_major);
+         if (packing == GLSL_INTERFACE_PACKING_STD430)
+            alignment = type->std430_base_alignment(row_major);
+         this->ubo_byte_offset = glsl_align(this->ubo_byte_offset, alignment);
+         this->uniforms[id].offset = this->ubo_byte_offset;
+         if (packing == GLSL_INTERFACE_PACKING_STD430)
+            this->ubo_byte_offset += type->std430_size(row_major);
+         else
+            this->ubo_byte_offset += type->std140_size(row_major);
+
+         if (type->is_array()) {
+            if (packing == GLSL_INTERFACE_PACKING_STD430)
+               this->uniforms[id].array_stride =
+                  type->fields.array->std430_array_stride(row_major);
+            else
+               this->uniforms[id].array_stride =
+                  glsl_align(type->fields.array->std140_size(row_major), 16);
         } else {
            this->uniforms[id].array_stride = 0;
         }
@@ -790,7 +820,11 @@ private:
             const unsigned items = row_major ? matrix->matrix_columns : matrix->vector_elements;
 
             assert(items <= 4);
-            this->uniforms[id].matrix_stride = glsl_align(items * N, 16);
+            if (packing == GLSL_INTERFACE_PACKING_STD430)
+               this->uniforms[id].matrix_stride = items < 3 ? items * N :
+                                                          glsl_align(items * N, 16);
+            else
+               this->uniforms[id].matrix_stride = glsl_align(items * N, 16);
            this->uniforms[id].row_major = row_major;
         } else {
            this->uniforms[id].matrix_stride = 0;
index b31052e767e14b479a50c98e2b01b4ae4a90f1b5..7c2bd59aeb711e3bec342a8f94ee67f06178fed7 100644 (file)
@@ -150,6 +150,7 @@ protected:
     */
    virtual void visit_field(const glsl_type *type, const char *name,
                             bool row_major, const glsl_type *record_type,
+                            const unsigned packing,
                             bool last_field);
 
    /**
@@ -173,10 +174,10 @@ protected:
    virtual void visit_field(const glsl_struct_field *field);
 
    virtual void enter_record(const glsl_type *type, const char *name,
-                             bool row_major);
+                             bool row_major, const unsigned packing);
 
    virtual void leave_record(const glsl_type *type, const char *name,
-                             bool row_major);
+                             bool row_major, const unsigned packing);
 
    virtual void set_record_array_count(unsigned record_array_count);
 
@@ -190,6 +191,7 @@ private:
     */
    void recursion(const glsl_type *t, char **name, size_t name_length,
                   bool row_major, const glsl_type *record_type,
+                  const unsigned packing,
                   bool last_field, unsigned record_array_count);
 };