On 15/09/15 11:38, Tapani Pälli wrote: > > > On 09/10/2015 04:35 PM, Iago Toral Quiroga wrote: >> From: Samuel Iglesias Gonsalvez <sigles...@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 <sigles...@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()) >
Oh, nice catch! Thanks, Sam >> + _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; >> > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev