[Mesa-dev] [PATCH v5 11/70] glsl: Add parser/compiler support for unsized array's length()

Tapani Pälli tapani.palli at intel.com
Tue Sep 15 02:38:32 PDT 2015



On 09/10/2015 04:35 PM, Iago Toral Quiroga wrote:
> From: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
>
> The unsized array length is computed with the following formula:
>
> array.length() =
>     max((buffer_object_size - offset_of_array) / stride_of_array, 0)
>
> Of these, only the buffer size needs to be provided by the backends, the
> frontend already knows the values of the two other variables.
>
> This patch identifies the cases where we need to get the length of an
> unsized array, injecting ir_unop_ssbo_unsized_array_length expressions
> that will be lowered (in a later patch) to inject the formula mentioned
> above.
>
> It also adds the ir_unop_get_buffer_size expression that drivers will
> implement to provide the buffer length.
>
> v2:
> - Do not define a triop that will force backends to implement the
>    entire formula, they should only need to provide the buffer size
>    since the other values are known by the frontend (Curro).
>
> Signed-off-by: Samuel Iglesias Gonsalvez <siglesias at igalia.com>
> ---
>   src/glsl/ast_function.cpp                             | 13 +++++++++----
>   src/glsl/ir.cpp                                       |  7 +++++++
>   src/glsl/ir.h                                         | 19 ++++++++++++++++++-
>   src/glsl/ir_validate.cpp                              | 11 +++++++++++
>   src/glsl/link_uniforms.cpp                            |  8 +++++++-
>   .../drivers/dri/i965/brw_fs_channel_expressions.cpp   |  2 ++
>   src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp        |  8 ++++++++
>   src/mesa/program/ir_to_mesa.cpp                       |  2 ++
>   src/mesa/state_tracker/st_glsl_to_tgsi.cpp            |  5 +++++
>   9 files changed, 69 insertions(+), 6 deletions(-)
>
> diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
> index 803edf5..0fb8928 100644
> --- a/src/glsl/ast_function.cpp
> +++ b/src/glsl/ast_function.cpp
> @@ -1593,11 +1593,16 @@ ast_function_expression::handle_method(exec_list *instructions,
>
>         if (op->type->is_array()) {
>            if (op->type->is_unsized_array()) {
> -            _mesa_glsl_error(&loc, state, "length called on unsized array");
> -            goto fail;
> +            if (!state->ARB_shader_storage_buffer_object_enable) {

this should be

if (!state->has_shader_storage_buffer_objects())

> +               _mesa_glsl_error(&loc, state, "length called on unsized array"
> +                                             " only available with "
> +                                             "ARB_shader_storage_buffer_object");
> +            }
> +            /* Calculate length of an unsized array in run-time */
> +            result = new(ctx) ir_expression(ir_unop_ssbo_unsized_array_length, op);
> +         } else {
> +            result = new(ctx) ir_constant(op->type->array_size());
>            }
> -
> -         result = new(ctx) ir_constant(op->type->array_size());
>         } else if (op->type->is_vector()) {
>            if (state->ARB_shading_language_420pack_enable) {
>               /* .length() returns int. */
> diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
> index 594fc33..60d8770 100644
> --- a/src/glsl/ir.cpp
> +++ b/src/glsl/ir.cpp
> @@ -342,6 +342,11 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
>   					   op0->type->vector_elements, 1);
>         break;
>
> +   case ir_unop_get_buffer_size:
> +   case ir_unop_ssbo_unsized_array_length:
> +      this->type = glsl_type::int_type;
> +      break;
> +
>      default:
>         assert(!"not reached: missing automatic type setup for ir_expression");
>         this->type = op0->type;
> @@ -571,6 +576,8 @@ static const char *const operator_strs[] = {
>      "noise",
>      "subroutine_to_int",
>      "interpolate_at_centroid",
> +   "get_buffer_size",
> +   "ssbo_unsized_array_length",
>      "+",
>      "-",
>      "*",
> diff --git a/src/glsl/ir.h b/src/glsl/ir.h
> index 9559dc4..ca6179c 100644
> --- a/src/glsl/ir.h
> +++ b/src/glsl/ir.h
> @@ -1423,9 +1423,26 @@ enum ir_expression_operation {
>      ir_unop_interpolate_at_centroid,
>
>      /**
> +    * Ask the driver for the total size of a buffer block.
> +    *
> +    * operand0 is the ir_constant buffer block index in the linked shader.
> +    */
> +   ir_unop_get_buffer_size,
> +
> +   /**
> +    * Calculate length of an unsized array inside a buffer block.
> +    * This opcode is going to be replaced in a lowering pass inside
> +    * the linker.
> +    *
> +    * operand0 is the unsized array's ir_value for the calculation
> +    * of its length.
> +    */
> +   ir_unop_ssbo_unsized_array_length,
> +
> +   /**
>       * A sentinel marking the last of the unary operations.
>       */
> -   ir_last_unop = ir_unop_interpolate_at_centroid,
> +   ir_last_unop = ir_unop_ssbo_unsized_array_length,
>
>      ir_binop_add,
>      ir_binop_sub,
> diff --git a/src/glsl/ir_validate.cpp b/src/glsl/ir_validate.cpp
> index 3f0dea7..935571a 100644
> --- a/src/glsl/ir_validate.cpp
> +++ b/src/glsl/ir_validate.cpp
> @@ -409,6 +409,17 @@ ir_validate::visit_leave(ir_expression *ir)
>         assert(ir->operands[0]->type->is_float());
>         break;
>
> +   case ir_unop_get_buffer_size:
> +      assert(ir->type == glsl_type::int_type);
> +      assert(ir->operands[0]->type == glsl_type::uint_type);
> +      break;
> +
> +   case ir_unop_ssbo_unsized_array_length:
> +      assert(ir->type == glsl_type::int_type);
> +      assert(ir->operands[0]->type->is_array());
> +      assert(ir->operands[0]->type->is_unsized_array());
> +      break;
> +
>      case ir_unop_d2f:
>         assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
>         assert(ir->type->base_type == GLSL_TYPE_FLOAT);
> diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp
> index a0cb618..fefc1ec 100644
> --- a/src/glsl/link_uniforms.cpp
> +++ b/src/glsl/link_uniforms.cpp
> @@ -221,7 +221,13 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
>         if (record_type == NULL && t->fields.array->is_record())
>            record_type = t->fields.array;
>
> -      for (unsigned i = 0; i < t->length; i++) {
> +      unsigned length = t->length;
> +      /* Shader storage block unsized arrays: add subscript [0] to variable
> +       * names */
> +      if (t->is_unsized_array())
> +         length = 1;
> +
> +      for (unsigned i = 0; i < length; i++) {
>   	 size_t new_length = name_length;
>
>   	 /* Append the subscript to the current variable name */
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
> index a8883a3..277b6cc 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
> @@ -379,6 +379,7 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)
>      }
>
>      case ir_binop_ubo_load:
> +   case ir_unop_get_buffer_size:
>         unreachable("not yet supported");
>
>      case ir_triop_fma:
> @@ -430,6 +431,7 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir)
>      case ir_triop_vector_insert:
>      case ir_quadop_bitfield_insert:
>      case ir_quadop_vector:
> +   case ir_unop_ssbo_unsized_array_length:
>         unreachable("should have been lowered");
>
>      case ir_unop_unpack_half_2x16_split_x:
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> index ec41262..c186f48 100644
> --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> @@ -1583,6 +1583,10 @@ vec4_visitor::visit(ir_expression *ir)
>         emit(MOV(result_dst, op[0]));
>         break;
>
> +   case ir_unop_ssbo_unsized_array_length:
> +      unreachable("not reached: should be handled by lower_ubo_reference");
> +      break;
> +
>      case ir_binop_add:
>         emit(ADD(result_dst, op[0], op[1]));
>         break;
> @@ -1789,6 +1793,10 @@ vec4_visitor::visit(ir_expression *ir)
>         emit(RNDE(result_dst, op[0]));
>         break;
>
> +   case ir_unop_get_buffer_size:
> +      unreachable("not reached: not implemented");
> +      break;
> +
>      case ir_binop_min:
>         emit_minmax(BRW_CONDITIONAL_L, result_dst, op[0], op[1]);
>         break;
> diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
> index 0defed8..d506485 100644
> --- a/src/mesa/program/ir_to_mesa.cpp
> +++ b/src/mesa/program/ir_to_mesa.cpp
> @@ -1344,9 +1344,11 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
>      case ir_unop_dFdy_coarse:
>      case ir_unop_dFdy_fine:
>      case ir_unop_subroutine_to_int:
> +   case ir_unop_get_buffer_size:
>         assert(!"not supported");
>         break;
>
> +   case ir_unop_ssbo_unsized_array_length:
>      case ir_quadop_vector:
>         /* This operation should have already been handled.
>          */
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index 6c9f947..d1987a0 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -2217,10 +2217,15 @@ glsl_to_tgsi_visitor::visit(ir_expression *ir)
>      case ir_triop_vector_insert:
>      case ir_binop_carry:
>      case ir_binop_borrow:
> +   case ir_unop_ssbo_unsized_array_length:
>         /* This operation is not supported, or should have already been handled.
>          */
>         assert(!"Invalid ir opcode in glsl_to_tgsi_visitor::visit()");
>         break;
> +
> +   case ir_unop_get_buffer_size:
> +      assert(!"Not implemented yet");
> +      break;
>      }
>
>      this->result = result_src;
>


More information about the mesa-dev mailing list