[Mesa-dev] [PATCH v5 25/70] glsl: Add std430 related member functions to glsl_type class

Jordan Justen jordan.l.justen at intel.com
Thu Sep 10 11:13:58 PDT 2015


On 2015-09-10 06:35:41, Iago Toral Quiroga wrote:
> From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
> 
> They are used to calculate size, base alignment and array stride values
> for a glsl_type following std430 rules.
> 
> Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
> ---
>  src/glsl/glsl_types.cpp | 209 ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/glsl/glsl_types.h   |  19 +++++
>  2 files changed, 228 insertions(+)
> 
> diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
> index 755618a..d97991a 100644
> --- a/src/glsl/glsl_types.cpp
> +++ b/src/glsl/glsl_types.cpp
> @@ -1357,6 +1357,215 @@ glsl_type::std140_size(bool row_major) const
>     return -1;
>  }
>  
> +unsigned
> +glsl_type::std430_base_alignment(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()) {
> +      switch (this->vector_elements) {
> +      case 1:
> +         return N;
> +      case 2:
> +         return 2 * N;
> +      case 3:
> +      case 4:
> +         return 4 * N;
> +      }
> +   }
> +
> +   /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
> +    *
> +    * "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

Looking at the 4.3 spec (and 4.5), it actually adds "and stride"
following "base alignment". The extension spec *does not* have the
"and stride" text.

This seems to be an inconsistency between the extension spec and the
actual spec, but the OpenGL spec form would produce more tightly
packed arrays.

Maybe we want to confirm what another implementation does?

-Jordan

> +    * 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())
> +      return this->fields.array->std430_base_alignment(row_major);
> +
> +   /* (5) If the member is a column-major matrix with <C> columns and
> +    *     <R> rows, the matrix is stored identically to an array of
> +    *     <C> column vectors with <R> components each, according to
> +    *     rule (4).
> +    *
> +    * (7) If the member is a row-major matrix with <C> columns and <R>
> +    *     rows, the matrix is stored identically to an array of <R>
> +    *     row vectors with <C> components each, according to rule (4).
> +    */
> +   if (this->is_matrix()) {
> +      const struct glsl_type *vec_type, *array_type;
> +      int c = this->matrix_columns;
> +      int r = this->vector_elements;
> +
> +      if (row_major) {
> +         vec_type = get_instance(base_type, c, 1);
> +         array_type = glsl_type::get_array_instance(vec_type, r);
> +      } else {
> +         vec_type = get_instance(base_type, r, 1);
> +         array_type = glsl_type::get_array_instance(vec_type, c);
> +      }
> +
> +      return array_type->std430_base_alignment(false);
> +   }
> +
> +      /* (9) If the member is a structure, the base alignment of the
> +    *     structure is <N>, where <N> is the largest base alignment
> +    *     value of any of its members, and rounded up to the base
> +    *     alignment of a vec4. The individual members of this
> +    *     sub-structure are then assigned offsets by applying this set
> +    *     of rules recursively, where the base offset of the first
> +    *     member of the sub-structure is equal to the aligned offset
> +    *     of the structure. The structure may have padding at the end;
> +    *     the base offset of the member following the sub-structure is
> +    *     rounded up to the next multiple of the base alignment of the
> +    *     structure.
> +    */
> +   if (this->is_record()) {
> +      unsigned base_alignment = 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;
> +         base_alignment = MAX2(base_alignment,
> +                               field_type->std430_base_alignment(field_row_major));
> +      }
> +      return base_alignment;
> +   }
> +   assert(!"not reached");
> +   return -1;
> +}
> +
> +unsigned
> +glsl_type::std430_array_stride(bool row_major) const
> +{
> +   unsigned N = is_double() ? 8 : 4;
> +
> +   /* Notice that the array stride of a vec3 is not 3 * N but 4 * N.
> +    * See OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout"
> +    *
> +    * (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_vector() && this->vector_elements == 3)
> +      return 4 * N;
> +
> +   /* By default use std430_size(row_major) */
> +   return this->std430_size(row_major);
> +}
> +
> +unsigned
> +glsl_type::std430_size(bool row_major) const
> +{
> +   unsigned N = is_double() ? 8 : 4;
> +
> +   /* OpenGL 4.30 spec, section 7.6.2.2 "Standard Uniform Block Layout":
> +    *
> +    * "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_scalar() || this->is_vector())
> +         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);
> +   }
> +
> +   if (this->is_array()) {
> +      if (this->fields.array->is_record())
> +         return this->length * this->fields.array->std430_size(row_major);
> +      else
> +         return this->length * this->fields.array->std430_base_alignment(row_major);
> +   }
> +
> +   if (this->is_record() || this->is_interface()) {
> +      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;
> +   }
> +
> +   assert(!"not reached");
> +   return -1;
> +}
>  
>  unsigned
>  glsl_type::count_attribute_slots() const
> diff --git a/src/glsl/glsl_types.h b/src/glsl/glsl_types.h
> index 02a398f..5a6548d 100644
> --- a/src/glsl/glsl_types.h
> +++ b/src/glsl/glsl_types.h
> @@ -326,6 +326,25 @@ 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;
> +
> +   /**
> +    * Calculate array stride in bytes of this type in a std430 shader storage
> +    * block.
> +    */
> +   unsigned std430_array_stride(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
> -- 
> 1.9.1
> 


More information about the mesa-dev mailing list