[Mesa-dev] [PATCH] glsl: Indirect array indexing on non-last SSBO member must fail compilation
Nicolai Hähnle
nhaehnle at gmail.com
Wed Oct 19 18:06:20 UTC 2016
On 18.10.2016 14:15, Iago Toral Quiroga wrote:
> After the changes in comit 5b2675093e863a52, we moved this check to the
> linker, but the spec expects this to be checked at compile-time. There are
> dEQP tests that expect an error at compile time and the spec seems to confirm
> that expectation:
>
> "Except for the last declared member of a shader storage block (section 4.3.9
> “Interface Blocks”), the size of an array must be declared (explicitly sized)
> before it is indexed with anything other than an integral constant expression.
> The size of any array must be declared before passing it as an argument to a
> function. Violation of any of these rules result in compile-time errors. It
> is legal to declare an array without a size (unsized) and then later
> redeclare the same name as an array of the same type and specify a size, or
> index it only with integral constant expressions (implicitly sized)."
>
> Commit 5b2675093e863a52 tries to take care of the case where we have implicitly
> sized arrays in SSBOs and it does so by checking the max_array_access field
> in ir_variable during linking. In this patch we change the approach: we look
> for indirect access on SSBO arrays, and when we find one, we emit a
> compile-time error if the accessed member is not the last in the SSBO
> definition.
>
> There is a corner case that the specs do not address directly though and that
> dEQP checks for: the case of an unsized array in an SSBO definition that is
> not defined last but is never used in the shader code either. The following
> dEQP tests expect a compile-time error in this scenario:
>
> dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader.compile_compute_shader
> dEQP-GLES31.functional.debug.negative_coverage.get_error.shader.compile_compute_shader
> dEQP-GLES31.functional.debug.negative_coverage.log.shader.compile_compute_shader
>
> However, since the unsized array is never used it is never indexed with a
> non-constant expression, so by the spec quotation above, it should be valid and
> the tests are probably incorrect.
Makes sense to me.
Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>
> ---
> src/compiler/glsl/ast_array_index.cpp | 14 ++++++++++++++
> src/compiler/glsl/link_uniform_blocks.cpp | 8 +-------
> 2 files changed, 15 insertions(+), 7 deletions(-)
>
> diff --git a/src/compiler/glsl/ast_array_index.cpp b/src/compiler/glsl/ast_array_index.cpp
> index e29dafb..dfa44b7 100644
> --- a/src/compiler/glsl/ast_array_index.cpp
> +++ b/src/compiler/glsl/ast_array_index.cpp
> @@ -233,6 +233,20 @@ _mesa_ast_array_index_to_hir(void *mem_ctx,
> else if (array->variable_referenced()->data.mode !=
> ir_var_shader_storage) {
> _mesa_glsl_error(&loc, state, "unsized array index must be constant");
> + } else {
> + /* Unsized array non-constant indexing on SSBO is allowed only for
> + * the last member of the SSBO definition.
> + */
> + ir_variable *var = array->variable_referenced();
> + const glsl_type *iface_type = var->get_interface_type();
> + int field_index = iface_type->field_index(var->name);
> + /* Field index can be < 0 for instance arrays */
> + if (field_index >= 0 &&
> + field_index != (int) iface_type->length - 1) {
> + _mesa_glsl_error(&loc, state, "Indirect access on unsized "
> + "array is limited to the last member of "
> + "SSBO.");
> + }
> }
> } else if (array->type->without_array()->is_interface()
> && ((array->variable_referenced()->data.mode == ir_var_uniform
> diff --git a/src/compiler/glsl/link_uniform_blocks.cpp b/src/compiler/glsl/link_uniform_blocks.cpp
> index 5b0dff6..bb423c5 100644
> --- a/src/compiler/glsl/link_uniform_blocks.cpp
> +++ b/src/compiler/glsl/link_uniform_blocks.cpp
> @@ -150,13 +150,7 @@ private:
> */
> const glsl_type *type_for_size = type;
> if (type->is_unsized_array()) {
> - if (!last_field) {
> - linker_error(prog, "unsized array `%s' definition: "
> - "only last member of a shader storage block "
> - "can be defined as unsized array",
> - name);
> - }
> -
> + assert(last_field);
> type_for_size = type->without_array();
> }
>
>
More information about the mesa-dev
mailing list