summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/ast_function.cpp13
-rw-r--r--src/glsl/ir.cpp7
-rw-r--r--src/glsl/ir.h19
-rw-r--r--src/glsl/ir_validate.cpp11
-rw-r--r--src/glsl/link_uniforms.cpp10
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp2
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp8
-rw-r--r--src/mesa/program/ir_to_mesa.cpp2
-rw-r--r--src/mesa/state_tracker/st_glsl_to_tgsi.cpp5
9 files changed, 70 insertions, 7 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 803edf5..ff5ecb9 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->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 b9df976..2c45b9e 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 48b6795..43a2bf0 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -1425,9 +1425,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 238546b..67a6e1b 100644
--- a/src/glsl/link_uniforms.cpp
+++ b/src/glsl/link_uniforms.cpp
@@ -231,9 +231,15 @@ program_resource_visitor::recursion(const glsl_type *t, char **name,
if (record_type == NULL && t->fields.array->is_record())
record_type = t->fields.array;
- record_array_count *= t->length;
+ 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 < t->length; i++) {
+ record_array_count *= length;
+
+ 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 ac086a7..3443e5c 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -1585,6 +1585,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;
@@ -1791,6 +1795,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 afb400f..4201a80 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 5896f65..633e90f 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;