[Mesa-dev] [PATCH 18/36] glsl ubo/ssbo: Move common code into lower_buffer_access::setup_buffer_access

Iago Toral itoral at igalia.com
Mon Nov 16 04:49:50 PST 2015


On Sat, 2015-11-14 at 13:43 -0800, Jordan Justen wrote:
> This code will also be usable by the pass to lower shared variables.
> 
> Note, that *const_offset is adjusted by setup_buffer_access so it must
> be initialized before calling setup_buffer_access.
> 
> Signed-off-by: Jordan Justen <jordan.l.justen at intel.com>
> Cc: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
> Cc: Iago Toral Quiroga <itoral at igalia.com>
> ---
>  src/glsl/lower_buffer_access.cpp | 167 +++++++++++++++++++++++++++++++++++++++
>  src/glsl/lower_buffer_access.h   |   5 ++
>  src/glsl/lower_ubo_reference.cpp | 160 +------------------------------------
>  3 files changed, 175 insertions(+), 157 deletions(-)
> 
> diff --git a/src/glsl/lower_buffer_access.cpp b/src/glsl/lower_buffer_access.cpp
> index b7fc107..87f64a9 100644
> --- a/src/glsl/lower_buffer_access.cpp
> +++ b/src/glsl/lower_buffer_access.cpp
> @@ -394,4 +394,171 @@ lower_buffer_access::is_dereferenced_thing_row_major(const ir_rvalue *deref)
>     return false;
>  }

Maybe add a comment here explaining that this expects to receive a
constant offset that has already been initialized to the starting offset
of the variable being dereferenced and that this function will only
adjust that to account for the offset of the particular component of the
variable that is accessed by the dereference.

Other than this,
Reviewed-by: Iago Toral Quiroga <itoral at igalia.com>
 
> +void
> +lower_buffer_access::setup_buffer_access(ir_variable *var,
> +                                         ir_rvalue *deref,
> +                                         ir_rvalue **offset,
> +                                         unsigned *const_offset,
> +                                         bool *row_major,
> +                                         int *matrix_columns,
> +                                         unsigned packing)
> +{
> +   *offset = new(mem_ctx) ir_constant(0u);
> +   *row_major = is_dereferenced_thing_row_major(deref);
> +   *matrix_columns = 1;
> +
> +   /* Calculate the offset to the start of the region of the UBO
> +    * dereferenced by *rvalue.  This may be a variable offset if an
> +    * array dereference has a variable index.
> +    */
> +   while (deref) {
> +      switch (deref->ir_type) {
> +      case ir_type_dereference_variable: {
> +         deref = NULL;
> +         break;
> +      }
> +
> +      case ir_type_dereference_array: {
> +         ir_dereference_array *deref_array = (ir_dereference_array *) deref;
> +         unsigned array_stride;
> +         if (deref_array->array->type->is_vector()) {
> +            /* We get this when storing or loading a component out of a vector
> +             * with a non-constant index. This happens for v[i] = f where v is
> +             * a vector (or m[i][j] = f where m is a matrix). If we don't
> +             * lower that here, it gets turned into v = vector_insert(v, i,
> +             * f), which loads the entire vector, modifies one component and
> +             * then write the entire thing back.  That breaks if another
> +             * thread or SIMD channel is modifying the same vector.
> +             */
> +            array_stride = 4;
> +            if (deref_array->array->type->is_double())
> +               array_stride *= 2;
> +         } else if (deref_array->array->type->is_matrix() && *row_major) {
> +            /* When loading a vector out of a row major matrix, the
> +             * step between the columns (vectors) is the size of a
> +             * float, while the step between the rows (elements of a
> +             * vector) is handled below in emit_ubo_loads.
> +             */
> +            array_stride = 4;
> +            if (deref_array->array->type->is_double())
> +               array_stride *= 2;
> +            *matrix_columns = deref_array->array->type->matrix_columns;
> +         } else if (deref_array->type->without_array()->is_interface()) {
> +            /* We're processing an array dereference of an interface instance
> +             * array. The thing being dereferenced *must* be a variable
> +             * dereference because interfaces cannot be embedded in other
> +             * types. In terms of calculating the offsets for the lowering
> +             * pass, we don't care about the array index. All elements of an
> +             * interface instance array will have the same offsets relative to
> +             * the base of the block that backs them.
> +             */
> +            deref = deref_array->array->as_dereference();
> +            break;
> +         } else {
> +            /* Whether or not the field is row-major (because it might be a
> +             * bvec2 or something) does not affect the array itself. We need
> +             * to know whether an array element in its entirety is row-major.
> +             */
> +            const bool array_row_major =
> +               is_dereferenced_thing_row_major(deref_array);
> +
> +            /* The array type will give the correct interface packing
> +             * information
> +             */
> +            if (packing == GLSL_INTERFACE_PACKING_STD430) {
> +               array_stride = deref_array->type->std430_array_stride(array_row_major);
> +            } else {
> +               array_stride = deref_array->type->std140_size(array_row_major);
> +               array_stride = glsl_align(array_stride, 16);
> +            }
> +         }
> +
> +         ir_rvalue *array_index = deref_array->array_index;
> +         if (array_index->type->base_type == GLSL_TYPE_INT)
> +            array_index = i2u(array_index);
> +
> +         ir_constant *const_index =
> +            array_index->constant_expression_value(NULL);
> +         if (const_index) {
> +            *const_offset += array_stride * const_index->value.u[0];
> +         } else {
> +            *offset = add(*offset,
> +                          mul(array_index,
> +                              new(mem_ctx) ir_constant(array_stride)));
> +         }
> +         deref = deref_array->array->as_dereference();
> +         break;
> +      }
> +
> +      case ir_type_dereference_record: {
> +         ir_dereference_record *deref_record = (ir_dereference_record *) deref;
> +         const glsl_type *struct_type = deref_record->record->type;
> +         unsigned intra_struct_offset = 0;
> +
> +         for (unsigned int i = 0; i < struct_type->length; i++) {
> +            const glsl_type *type = struct_type->fields.structure[i].type;
> +
> +            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 = 0;
> +
> +            if (packing == GLSL_INTERFACE_PACKING_STD430)
> +               field_align = type->std430_base_alignment(field_row_major);
> +            else
> +               field_align = type->std140_base_alignment(field_row_major);
> +
> +            intra_struct_offset = glsl_align(intra_struct_offset, field_align);
> +
> +            if (strcmp(struct_type->fields.structure[i].name,
> +                       deref_record->field) == 0)
> +               break;
> +
> +            if (packing == GLSL_INTERFACE_PACKING_STD430)
> +               intra_struct_offset += type->std430_size(field_row_major);
> +            else
> +               intra_struct_offset += type->std140_size(field_row_major);
> +
> +            /* If the field just examined was itself a structure, apply rule
> +             * #9:
> +             *
> +             *     "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 (type->without_array()->is_record()) {
> +               intra_struct_offset = glsl_align(intra_struct_offset,
> +                                                field_align);
> +
> +            }
> +         }
> +
> +         *const_offset += intra_struct_offset;
> +         deref = deref_record->record->as_dereference();
> +         break;
> +      }
> +
> +      case ir_type_swizzle: {
> +         ir_swizzle *deref_swizzle = (ir_swizzle *) deref;
> +
> +         assert(deref_swizzle->mask.num_components == 1);
> +
> +         *const_offset += deref_swizzle->mask.x * sizeof(int);
> +         deref = deref_swizzle->val->as_dereference();
> +         break;
> +      }
> +
> +      default:
> +         assert(!"not reached");
> +         deref = NULL;
> +         break;
> +      }
> +   }
> +}
> +
>  } /* namespace lower_buffer_access */
> diff --git a/src/glsl/lower_buffer_access.h b/src/glsl/lower_buffer_access.h
> index 0698e22..77cf180 100644
> --- a/src/glsl/lower_buffer_access.h
> +++ b/src/glsl/lower_buffer_access.h
> @@ -50,6 +50,11 @@ public:
>  
>     bool is_dereferenced_thing_row_major(const ir_rvalue *deref);
>  
> +   void setup_buffer_access(ir_variable *var, ir_rvalue *deref,
> +                            ir_rvalue **offset, unsigned *const_offset,
> +                            bool *row_major, int *matrix_columns,
> +                            unsigned packing);
> +
>     void *mem_ctx;
>  };
>  
> diff --git a/src/glsl/lower_ubo_reference.cpp b/src/glsl/lower_ubo_reference.cpp
> index 7e1221b..6212b87 100644
> --- a/src/glsl/lower_ubo_reference.cpp
> +++ b/src/glsl/lower_ubo_reference.cpp
> @@ -285,164 +285,10 @@ lower_ubo_reference_visitor::setup_for_load_or_store(ir_variable *var,
>  
>     assert(this->uniform_block);
>  
> -   *offset = new(mem_ctx) ir_constant(0u);
> -   *const_offset = 0;
> -   *row_major = is_dereferenced_thing_row_major(deref);
> -   *matrix_columns = 1;
> -
> -   /* Calculate the offset to the start of the region of the UBO
> -    * dereferenced by *rvalue.  This may be a variable offset if an
> -    * array dereference has a variable index.
> -    */
> -   while (deref) {
> -      switch (deref->ir_type) {
> -      case ir_type_dereference_variable: {
> -         *const_offset += ubo_var->Offset;
> -         deref = NULL;
> -         break;
> -      }
> -
> -      case ir_type_dereference_array: {
> -         ir_dereference_array *deref_array = (ir_dereference_array *) deref;
> -         unsigned array_stride;
> -         if (deref_array->array->type->is_vector()) {
> -            /* We get this when storing or loading a component out of a vector
> -             * with a non-constant index. This happens for v[i] = f where v is
> -             * a vector (or m[i][j] = f where m is a matrix). If we don't
> -             * lower that here, it gets turned into v = vector_insert(v, i,
> -             * f), which loads the entire vector, modifies one component and
> -             * then write the entire thing back.  That breaks if another
> -             * thread or SIMD channel is modifying the same vector.
> -             */
> -            array_stride = 4;
> -            if (deref_array->array->type->is_double())
> -               array_stride *= 2;
> -         } else if (deref_array->array->type->is_matrix() && *row_major) {
> -            /* When loading a vector out of a row major matrix, the
> -             * step between the columns (vectors) is the size of a
> -             * float, while the step between the rows (elements of a
> -             * vector) is handled below in emit_ubo_loads.
> -             */
> -            array_stride = 4;
> -            if (deref_array->array->type->is_double())
> -               array_stride *= 2;
> -            *matrix_columns = deref_array->array->type->matrix_columns;
> -         } else if (deref_array->type->without_array()->is_interface()) {
> -            /* We're processing an array dereference of an interface instance
> -             * array. The thing being dereferenced *must* be a variable
> -             * dereference because interfaces cannot be embedded in other
> -             * types. In terms of calculating the offsets for the lowering
> -             * pass, we don't care about the array index. All elements of an
> -             * interface instance array will have the same offsets relative to
> -             * the base of the block that backs them.
> -             */
> -            deref = deref_array->array->as_dereference();
> -            break;
> -         } else {
> -            /* Whether or not the field is row-major (because it might be a
> -             * bvec2 or something) does not affect the array itself. We need
> -             * to know whether an array element in its entirety is row-major.
> -             */
> -            const bool array_row_major =
> -               is_dereferenced_thing_row_major(deref_array);
> -
> -            /* The array type will give the correct interface packing
> -             * information
> -             */
> -            if (packing == GLSL_INTERFACE_PACKING_STD430) {
> -               array_stride = deref_array->type->std430_array_stride(array_row_major);
> -            } else {
> -               array_stride = deref_array->type->std140_size(array_row_major);
> -               array_stride = glsl_align(array_stride, 16);
> -            }
> -         }
> -
> -         ir_rvalue *array_index = deref_array->array_index;
> -         if (array_index->type->base_type == GLSL_TYPE_INT)
> -            array_index = i2u(array_index);
> -
> -         ir_constant *const_index =
> -            array_index->constant_expression_value(NULL);
> -         if (const_index) {
> -            *const_offset += array_stride * const_index->value.u[0];
> -         } else {
> -            *offset = add(*offset,
> -                          mul(array_index,
> -                              new(mem_ctx) ir_constant(array_stride)));
> -         }
> -         deref = deref_array->array->as_dereference();
> -         break;
> -      }
> -
> -      case ir_type_dereference_record: {
> -         ir_dereference_record *deref_record = (ir_dereference_record *) deref;
> -         const glsl_type *struct_type = deref_record->record->type;
> -         unsigned intra_struct_offset = 0;
> -
> -         for (unsigned int i = 0; i < struct_type->length; i++) {
> -            const glsl_type *type = struct_type->fields.structure[i].type;
> -
> -            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 = 0;
> -
> -            if (packing == GLSL_INTERFACE_PACKING_STD430)
> -               field_align = type->std430_base_alignment(field_row_major);
> -            else
> -               field_align = type->std140_base_alignment(field_row_major);
> -
> -            intra_struct_offset = glsl_align(intra_struct_offset, field_align);
> -
> -            if (strcmp(struct_type->fields.structure[i].name,
> -                       deref_record->field) == 0)
> -               break;
> -
> -            if (packing == GLSL_INTERFACE_PACKING_STD430)
> -               intra_struct_offset += type->std430_size(field_row_major);
> -            else
> -               intra_struct_offset += type->std140_size(field_row_major);
> -
> -            /* If the field just examined was itself a structure, apply rule
> -             * #9:
> -             *
> -             *     "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 (type->without_array()->is_record()) {
> -               intra_struct_offset = glsl_align(intra_struct_offset,
> -                                                field_align);
> -
> -            }
> -         }
> -
> -         *const_offset += intra_struct_offset;
> -         deref = deref_record->record->as_dereference();
> -         break;
> -      }
> -
> -      case ir_type_swizzle: {
> -         ir_swizzle *deref_swizzle = (ir_swizzle *) deref;
> +   *const_offset = ubo_var->Offset;
>  
> -         assert(deref_swizzle->mask.num_components == 1);
> -
> -         *const_offset += deref_swizzle->mask.x * sizeof(int);
> -         deref = deref_swizzle->val->as_dereference();
> -         break;
> -      }
> -
> -      default:
> -         assert(!"not reached");
> -         deref = NULL;
> -         break;
> -      }
> -   }
> +   setup_buffer_access(var, deref, offset, const_offset, row_major,
> +                       matrix_columns, packing);
>  }
>  
>  void




More information about the mesa-dev mailing list