summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYevhenii Kolesnikov <yevhenii.kolesnikov@globallogic.com>2021-07-14 20:39:45 +0300
committerDylan Baker <dylan.c.baker@intel.com>2021-07-27 11:43:34 -0700
commit0028e826c5933fd2805439dac11868bd4e1410f0 (patch)
tree8790e4e5a655f3b628b9adea0c0483ae4009761e
parentfc9650d1f398933dcf0ae1c1ca970b574b44bf17 (diff)
downloadmesa-0028e826c5933fd2805439dac11868bd4e1410f0.tar.gz
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: 273f61a0051a ("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> (cherry picked from commit 441826aaaac54e84629269c4622be2f17a465209)
-rw-r--r--.pick_status.json2
-rw-r--r--src/compiler/glsl/ir.cpp1
-rw-r--r--src/compiler/glsl/ir_expression_operation.py5
-rw-r--r--src/compiler/glsl/ir_validate.cpp5
-rw-r--r--src/compiler/glsl/linker.cpp39
-rw-r--r--src/mesa/program/ir_to_mesa.cpp1
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp1
7 files changed, 53 insertions, 1 deletions
diff --git a/.pick_status.json b/.pick_status.json
index e2e9c7f72d9..9e087012cce 100644
--- a/.pick_status.json
+++ b/.pick_status.json
@@ -103,7 +103,7 @@
"description": "glsl: Add operator for .length() method on implicitly-sized arrays",
"nominated": true,
"nomination_type": 1,
- "resolution": 0,
+ "resolution": 1,
"main_sha": null,
"because_sha": "273f61a0051a794d1a39d70fb1dbf46a3ca3c63f"
},
diff --git a/src/compiler/glsl/ir.cpp b/src/compiler/glsl/ir.cpp
index 97b302a744a..f9e9c321db4 100644
--- a/src/compiler/glsl/ir.cpp
+++ b/src/compiler/glsl/ir.cpp
@@ -438,6 +438,7 @@ ir_expression::ir_expression(int op, ir_rvalue *op0)
case ir_unop_get_buffer_size:
case ir_unop_ssbo_unsized_array_length:
+ case ir_unop_implicitly_sized_array_length:
this->type = glsl_type::int_type;
break;
diff --git a/src/compiler/glsl/ir_expression_operation.py b/src/compiler/glsl/ir_expression_operation.py
index 0d8d7a6f9ed..c9f9831c346 100644
--- a/src/compiler/glsl/ir_expression_operation.py
+++ b/src/compiler/glsl/ir_expression_operation.py
@@ -591,6 +591,11 @@ ir_expression_operation = [
# of its length.
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.
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))),
diff --git a/src/compiler/glsl/ir_validate.cpp b/src/compiler/glsl/ir_validate.cpp
index c9d5ca1e356..c60c36cd260 100644
--- a/src/compiler/glsl/ir_validate.cpp
+++ b/src/compiler/glsl/ir_validate.cpp
@@ -633,6 +633,11 @@ ir_validate::visit_leave(ir_expression *ir)
assert(ir->operands[0]->type->is_unsized_array());
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:
assert(ir->operands[0]->type->is_double());
assert(ir->type->is_float());
diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp
index a5ae7a30bf0..b598b63c09f 100644
--- a/src/compiler/glsl/linker.cpp
+++ b/src/compiler/glsl/linker.cpp
@@ -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
* 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.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_uniform_blocks(mem_ctx, ctx, prog, linked, &ubo_blocks,
&num_ubo_blocks, &ssbo_blocks, &num_ssbo_blocks);
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index eaaf8daab1c..96aa399aa63 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -1351,6 +1351,7 @@ ir_to_mesa_visitor::visit(ir_expression *ir)
break;
case ir_unop_ssbo_unsized_array_length:
+ case ir_unop_implicitly_sized_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 4f62622ed16..3ecdb8374b0 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -2458,6 +2458,7 @@ glsl_to_tgsi_visitor::visit_expression(ir_expression* ir, st_src_reg *op)
case ir_binop_carry:
case ir_binop_borrow:
case ir_unop_ssbo_unsized_array_length:
+ case ir_unop_implicitly_sized_array_length:
case ir_unop_atan:
case ir_binop_atan2:
case ir_unop_clz: