diff options
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/ast_function.cpp | 13 | ||||
-rw-r--r-- | src/glsl/ir.cpp | 7 | ||||
-rw-r--r-- | src/glsl/ir.h | 19 | ||||
-rw-r--r-- | src/glsl/ir_validate.cpp | 11 | ||||
-rw-r--r-- | src/glsl/link_uniforms.cpp | 10 |
5 files changed, 53 insertions, 7 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 803edf5a14d..ff5ecb954f0 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 b9df9761920..2c45b9edc0f 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 48b6795cc09..43a2bf0ae1c 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 3f0dea74e27..935571ae1d6 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 238546ba22e..67a6e1bea17 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 */ |