[Mesa-dev] [PATCH v2 44/82] glsl: Add parser/compiler support for std430 interface packing qualifier

Iago Toral Quiroga itoral at igalia.com
Wed Jun 3 00:01:34 PDT 2015


From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>

This commit also adds functions to calculate std430 base alignment and sizes

Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
---
 src/glsl/ast.h                   |   1 +
 src/glsl/ast_to_hir.cpp          |  20 +++++--
 src/glsl/ast_type.cpp            |   1 +
 src/glsl/glsl_parser.yy          |   2 +
 src/glsl/glsl_types.cpp          | 117 +++++++++++++++++++++++++++++++++++++++
 src/glsl/glsl_types.h            |  15 ++++-
 src/glsl/link_uniform_blocks.cpp |  15 ++++-
 src/mesa/main/mtypes.h           |   3 +-
 8 files changed, 165 insertions(+), 9 deletions(-)

diff --git a/src/glsl/ast.h b/src/glsl/ast.h
index 4921229..6cbbf09 100644
--- a/src/glsl/ast.h
+++ b/src/glsl/ast.h
@@ -480,6 +480,7 @@ struct ast_type_qualifier {
 	 /** \name Layout qualifiers for GL_ARB_uniform_buffer_object */
 	 /** \{ */
          unsigned std140:1;
+         unsigned std430:1;
          unsigned shared:1;
          unsigned packed:1;
          unsigned column_major:1;
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 3ec28dd..ae8d303 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -2809,11 +2809,12 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
        var->data.depth_layout = ir_depth_layout_none;
 
    if (qual->flags.q.std140 ||
+       qual->flags.q.std430 ||
        qual->flags.q.packed ||
        qual->flags.q.shared) {
       _mesa_glsl_error(loc, state,
-                       "uniform block layout qualifiers std140, packed, and "
-                       "shared can only be applied to uniform blocks, not "
+                       "uniform block layout qualifiers std140, std430, packed, "
+                       "and shared can only be applied to uniform blocks, not "
                        "members");
    }
 
@@ -5319,12 +5320,14 @@ ast_process_structure_or_interface_block(exec_list *instructions,
          const struct ast_type_qualifier *const qual =
             & decl_list->type->qualifier;
          if (qual->flags.q.std140 ||
+             qual->flags.q.std430 ||
              qual->flags.q.packed ||
              qual->flags.q.shared) {
             _mesa_glsl_error(&loc, state,
                              "uniform/shader storage block layout qualifiers "
-                             "std140, packed, and shared can only be applied "
-                             "to uniform/shader storage blocks, not members");
+                             "std140, std430, packed, and shared can only be "
+                             "applied to uniform/shader storage blocks, not "
+                             "members");
          }
 
          if (qual->flags.q.constant) {
@@ -5535,6 +5538,13 @@ ast_interface_block::hir(exec_list *instructions,
                        this->block_name);
    }
 
+   if (!this->layout.flags.q.buffer &&
+       this->layout.flags.q.std430) {
+      _mesa_glsl_error(&loc, state,
+                       "std430 storage block layout qualifier is supported "
+                       "only for shader storage blocks");
+   }
+
    /* The ast_interface_block has a list of ast_declarator_lists.  We
     * need to turn those into ir_variables with an association
     * with this uniform block.
@@ -5544,6 +5554,8 @@ ast_interface_block::hir(exec_list *instructions,
       packing = GLSL_INTERFACE_PACKING_SHARED;
    } else if (this->layout.flags.q.packed) {
       packing = GLSL_INTERFACE_PACKING_PACKED;
+   } else if (this->layout.flags.q.std430) {
+      packing = GLSL_INTERFACE_PACKING_STD430;
    } else {
       /* The default layout is std140.
        */
diff --git a/src/glsl/ast_type.cpp b/src/glsl/ast_type.cpp
index fa4806a..40c441f 100644
--- a/src/glsl/ast_type.cpp
+++ b/src/glsl/ast_type.cpp
@@ -117,6 +117,7 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
    ubo_layout_mask.flags.q.std140 = 1;
    ubo_layout_mask.flags.q.packed = 1;
    ubo_layout_mask.flags.q.shared = 1;
+   ubo_layout_mask.flags.q.std430 = 1;
 
    ast_type_qualifier ubo_binding_mask;
    ubo_binding_mask.flags.i = 0;
diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy
index 37c4401..4ef946b 100644
--- a/src/glsl/glsl_parser.yy
+++ b/src/glsl/glsl_parser.yy
@@ -1245,6 +1245,8 @@ layout_qualifier_id:
             $$.flags.q.std140 = 1;
          } else if (match_layout_qualifier($1, "shared", state) == 0) {
             $$.flags.q.shared = 1;
+         } else if (match_layout_qualifier($1, "std430", state) == 0) {
+            $$.flags.q.std430 = 1;
          } else if (match_layout_qualifier($1, "column_major", state) == 0) {
             $$.flags.q.column_major = 1;
          /* "row_major" is a reserved word in GLSL 1.30+. Its token is parsed
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index f675e90..9e1e247 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -1281,6 +1281,123 @@ glsl_type::std140_size(bool row_major) const
    return -1;
 }
 
+unsigned
+glsl_type::std430_base_alignment(bool row_major) const
+{
+   unsigned base_alignment = 0;
+   /* When using the "std430" storage layout, shader storage
+    * blocks will be laid out in buffer storage identically to uniform and
+    * shader storage blocks using the "std140" layout, except that the base
+    * alignment of arrays of scalars and vectors in rule (4) and of structures
+    * in rule (9) are not rounded up a multiple of the base alignment of a vec4.
+    */
+
+   /* (1) If the member is a scalar consuming <N> basic machine units, the
+    *     base alignment is <N>.
+    *
+    * (2) If the member is a two- or four-component vector with components
+    *     consuming <N> basic machine units, the base alignment is 2<N> or
+    *     4<N>, respectively.
+    *
+    * (3) If the member is a three-component vector with components consuming
+    *     <N> basic machine units, the base alignment is 4<N>.
+    */
+   if (this->is_array()) {
+      base_alignment = this->fields.array->std430_base_alignment(row_major);
+   } else {
+      /* For the rest of cases, use std140_base_alignment() */
+      base_alignment = this->std140_base_alignment(row_major);
+   }
+   return base_alignment;
+}
+
+unsigned
+glsl_type::std430_size(bool row_major) const
+{
+   unsigned N = is_double() ? 8 : 4;
+
+   /* (1) If the member is a scalar consuming <N> basic machine units, the
+    *     base alignment is <N>.
+    *
+    * (2) If the member is a two- or four-component vector with components
+    *     consuming <N> basic machine units, the base alignment is 2<N> or
+    *     4<N>, respectively.
+    *
+    * (3) If the member is a three-component vector with components consuming
+    *     <N> basic machine units, the base alignment is 4<N>.
+    */
+   if (this->is_scalar() || this->is_vector()) {
+      if (this->vector_elements > 2)
+         return glsl_align(this->vector_elements * N, 16);
+      else
+         return this->vector_elements * N;
+   }
+
+   if (this->without_array()->is_matrix()) {
+      const struct glsl_type *element_type;
+      const struct glsl_type *vec_type;
+      unsigned int array_len;
+
+      if (this->is_array()) {
+	 element_type = this->fields.array;
+	 array_len = this->length;
+      } else {
+	 element_type = this;
+	 array_len = 1;
+      }
+
+      if (row_major) {
+         vec_type = get_instance(element_type->base_type,
+                                 element_type->matrix_columns, 1);
+
+	 array_len *= element_type->vector_elements;
+      } else {
+	 vec_type = get_instance(element_type->base_type,
+				 element_type->vector_elements, 1);
+	 array_len *= element_type->matrix_columns;
+      }
+      const glsl_type *array_type = glsl_type::get_array_instance(vec_type,
+								  array_len);
+
+      return array_type->std430_size(false);
+   }
+
+   /* When using the "std430" storage layout, shader storage
+    * blocks will be laid out in buffer storage identically to uniform and
+    * shader storage blocks using the "std140" layout, except that the base
+    * alignment of arrays of scalars and vectors in rule (4) and of structures
+    * in rule (9) are not rounded up a multiple of the base alignment of a vec4.
+    */
+   if (this->is_array())
+         return this->length * this->fields.array->std430_size(row_major);
+
+   if (this->is_record()) {
+      unsigned size = 0;
+      unsigned max_align = 0;
+
+      for (unsigned i = 0; i < this->length; i++) {
+         bool field_row_major = row_major;
+         const enum glsl_matrix_layout matrix_layout =
+            glsl_matrix_layout(this->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;
+         }
+
+         const struct glsl_type *field_type = this->fields.structure[i].type;
+         unsigned align = field_type->std430_base_alignment(field_row_major);
+         size = glsl_align(size, align);
+         size += field_type->std430_size(field_row_major);
+
+         max_align = MAX2(align, max_align);
+      }
+      size = glsl_align(size, max_align);
+      return size;
+   }
+   /* For the rest of cases, return std140_size(). */
+   return this->std140_size(row_major);
+}
 
 unsigned
 glsl_type::count_attribute_slots() const
diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
index f54a939..42d5ab9 100644
--- a/src/glsl/glsl_types.h
+++ b/src/glsl/glsl_types.h
@@ -76,7 +76,8 @@ enum glsl_sampler_dim {
 enum glsl_interface_packing {
    GLSL_INTERFACE_PACKING_STD140,
    GLSL_INTERFACE_PACKING_SHARED,
-   GLSL_INTERFACE_PACKING_PACKED
+   GLSL_INTERFACE_PACKING_PACKED,
+   GLSL_INTERFACE_PACKING_STD430
 };
 
 enum glsl_matrix_layout {
@@ -320,6 +321,18 @@ struct glsl_type {
    unsigned std140_size(bool row_major) const;
 
    /**
+    * Alignment in bytes of the start of this type in a std430 shader
+    * storage block.
+    */
+   unsigned std430_base_alignment(bool row_major) const;
+
+   /** Size in bytes of this type in a std430 shader storage block.
+    *
+    * Note that this is not GL_BUFFER_SIZE
+    */
+   unsigned std430_size(bool row_major) const;
+
+   /**
     * \brief Can this type be implicitly converted to another?
     *
     * \return True if the types are identical or if this type can be converted
diff --git a/src/glsl/link_uniform_blocks.cpp b/src/glsl/link_uniform_blocks.cpp
index 4df39e2..c891d03 100644
--- a/src/glsl/link_uniform_blocks.cpp
+++ b/src/glsl/link_uniform_blocks.cpp
@@ -119,8 +119,16 @@ private:
          v->IndexName = v->Name;
       }
 
-      const unsigned alignment = type->std140_base_alignment(v->RowMajor);
-      unsigned size = type->std140_size(v->RowMajor);
+      unsigned alignment = 0;
+      unsigned size = 0;
+
+      if (v->Type->interface_packing == GLSL_INTERFACE_PACKING_STD430) {
+         alignment = type->std430_base_alignment(v->RowMajor);
+         size = type->std430_size(v->RowMajor);
+      } else {
+         alignment = type->std140_base_alignment(v->RowMajor);
+         size = type->std140_size(v->RowMajor);
+      }
 
       this->offset = glsl_align(this->offset, alignment);
       v->Offset = this->offset;
@@ -255,7 +263,8 @@ link_uniform_blocks(void *mem_ctx,
                  == unsigned(ubo_packing_shared));
    STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_PACKED)
                  == unsigned(ubo_packing_packed));
-
+   STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD430)
+                 == unsigned(ubo_packing_std430));
 
    hash_table_foreach (block_hash, entry) {
       const struct link_uniform_block_active *const b =
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index f5a1e97..7f372bb 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2551,7 +2551,8 @@ enum gl_uniform_block_packing
 {
    ubo_packing_std140,
    ubo_packing_shared,
-   ubo_packing_packed
+   ubo_packing_packed,
+   ubo_packing_std430
 };
 
 
-- 
1.9.1



More information about the mesa-dev mailing list