glsl: Add operator for .length() method on implicitly-sized arrays
ARB_shader_storage_buffer_object extension (promoted to core in 4.3) allows us
to call .length() method on arrays declared without an explicit size. The length is
determined at link time as a maximum array access.
Fixes: 273f61a005
("glsl: Add parser/compiler support for unsized array's length()")
Signed-off-by: Yevhenii Kolesnikov <yevhenii.kolesnikov@globallogic.com>
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11952>
This commit is contained in:
parent
e6cdb01c51
commit
441826aaaa
|
@ -438,6 +438,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
|
||||||
|
|
||||||
case ir_unop_get_buffer_size:
|
case ir_unop_get_buffer_size:
|
||||||
case ir_unop_ssbo_unsized_array_length:
|
case ir_unop_ssbo_unsized_array_length:
|
||||||
|
case ir_unop_implicitly_sized_array_length:
|
||||||
this->type = glsl_type::int_type;
|
this->type = glsl_type::int_type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -591,6 +591,11 @@ ir_expression_operation = [
|
||||||
# of its length.
|
# of its length.
|
||||||
operation("ssbo_unsized_array_length", 1),
|
operation("ssbo_unsized_array_length", 1),
|
||||||
|
|
||||||
|
# Calculate length of an implicitly sized array.
|
||||||
|
# This opcode is going to be replaced with a constant expression at link
|
||||||
|
# time.
|
||||||
|
operation("implicitly_sized_array_length", 1),
|
||||||
|
|
||||||
# 64-bit integer packing ops.
|
# 64-bit integer packing ops.
|
||||||
operation("pack_int_2x32", 1, printable_name="packInt2x32", source_types=(int_type,), dest_type=int64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
|
operation("pack_int_2x32", 1, printable_name="packInt2x32", source_types=(int_type,), dest_type=int64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
|
||||||
operation("pack_uint_2x32", 1, printable_name="packUint2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
|
operation("pack_uint_2x32", 1, printable_name="packUint2x32", source_types=(uint_type,), dest_type=uint64_type, c_expression="data.u64[0] = pack_2x32(op[0]->value.u[0], op[0]->value.u[1])", flags=frozenset((horizontal_operation, non_assign_operation))),
|
||||||
|
|
|
@ -633,6 +633,11 @@ ir_validate::visit_leave(ir_expression *ir)
|
||||||
assert(ir->operands[0]->type->is_unsized_array());
|
assert(ir->operands[0]->type->is_unsized_array());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ir_unop_implicitly_sized_array_length:
|
||||||
|
assert(ir->type == glsl_type::int_type);
|
||||||
|
assert(ir->operands[0]->type->is_array());
|
||||||
|
break;
|
||||||
|
|
||||||
case ir_unop_d2f:
|
case ir_unop_d2f:
|
||||||
assert(ir->operands[0]->type->is_double());
|
assert(ir->operands[0]->type->is_double());
|
||||||
assert(ir->type->is_float());
|
assert(ir->type->is_float());
|
||||||
|
|
|
@ -321,6 +321,39 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class array_length_to_const_visitor : public ir_rvalue_visitor {
|
||||||
|
public:
|
||||||
|
array_length_to_const_visitor()
|
||||||
|
{
|
||||||
|
this->progress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~array_length_to_const_visitor()
|
||||||
|
{
|
||||||
|
/* empty */
|
||||||
|
}
|
||||||
|
|
||||||
|
bool progress;
|
||||||
|
|
||||||
|
virtual void handle_rvalue(ir_rvalue **rvalue)
|
||||||
|
{
|
||||||
|
if (*rvalue == NULL || (*rvalue)->ir_type != ir_type_expression)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ir_expression *expr = (*rvalue)->as_expression();
|
||||||
|
if (expr) {
|
||||||
|
if (expr->operation == ir_unop_implicitly_sized_array_length) {
|
||||||
|
assert(!expr->operands[0]->type->is_unsized_array());
|
||||||
|
ir_constant *constant = new(expr)
|
||||||
|
ir_constant(expr->operands[0]->type->array_size());
|
||||||
|
if (constant) {
|
||||||
|
*rvalue = constant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visitor that determines the highest stream id to which a (geometry) shader
|
* Visitor that determines the highest stream id to which a (geometry) shader
|
||||||
* emits vertices. It also checks whether End{Stream}Primitive is ever called.
|
* emits vertices. It also checks whether End{Stream}Primitive is ever called.
|
||||||
|
@ -2540,6 +2573,12 @@ link_intrastage_shaders(void *mem_ctx,
|
||||||
v.run(linked->ir);
|
v.run(linked->ir);
|
||||||
v.fixup_unnamed_interface_types();
|
v.fixup_unnamed_interface_types();
|
||||||
|
|
||||||
|
/* Now that we know the sizes of all the arrays, we can replace .length()
|
||||||
|
* calls with a constant expression.
|
||||||
|
*/
|
||||||
|
array_length_to_const_visitor len_v;
|
||||||
|
len_v.run(linked->ir);
|
||||||
|
|
||||||
/* Link up uniform blocks defined within this stage. */
|
/* Link up uniform blocks defined within this stage. */
|
||||||
link_uniform_blocks(mem_ctx, ctx, prog, linked, &ubo_blocks,
|
link_uniform_blocks(mem_ctx, ctx, prog, linked, &ubo_blocks,
|
||||||
&num_ubo_blocks, &ssbo_blocks, &num_ssbo_blocks);
|
&num_ubo_blocks, &ssbo_blocks, &num_ssbo_blocks);
|
||||||
|
|
|
@ -1351,6 +1351,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ir_unop_ssbo_unsized_array_length:
|
case ir_unop_ssbo_unsized_array_length:
|
||||||
|
case ir_unop_implicitly_sized_array_length:
|
||||||
case ir_quadop_vector:
|
case ir_quadop_vector:
|
||||||
/* This operation should have already been handled.
|
/* This operation should have already been handled.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -2458,6 +2458,7 @@ glsl_to_tgsi_visitor::visit_expression(ir_expression* ir, st_src_reg *op)
|
||||||
case ir_binop_carry:
|
case ir_binop_carry:
|
||||||
case ir_binop_borrow:
|
case ir_binop_borrow:
|
||||||
case ir_unop_ssbo_unsized_array_length:
|
case ir_unop_ssbo_unsized_array_length:
|
||||||
|
case ir_unop_implicitly_sized_array_length:
|
||||||
case ir_unop_atan:
|
case ir_unop_atan:
|
||||||
case ir_binop_atan2:
|
case ir_binop_atan2:
|
||||||
case ir_unop_clz:
|
case ir_unop_clz:
|
||||||
|
|
Loading…
Reference in New Issue