[Mesa-dev] [PATCH] i965/fs: Clamp image array indices to the array bounds on IVB.

Jordan Justen jordan.l.justen at intel.com
Mon Jul 27 14:29:06 PDT 2015


Reviewed-by: Jordan Justen <jordan.l.justen at intel.com>

On 2015-07-27 06:01:31, Francisco Jerez wrote:
> This fixes the spec at arb_shader_image_load_store@invalid index bounds
> piglit tests on IVB, which were causing a GPU hang and then a crash
> due to the invalid binding table index result of the array index
> calculation.  Other generations seem to behave sensibly when an
> invalid surface is provided so it doesn't look like we need to care.
> ---
>  src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 25 +++++++++++++++++++++----
>  1 file changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> index 1671595..b69e96b 100644
> --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
> @@ -1216,14 +1216,31 @@ fs_visitor::get_nir_image_deref(const nir_deref_var *deref)
>           nir_deref_as_array(deref->deref.child);
>        assert(deref->deref.child->deref_type == nir_deref_type_array &&
>               deref_array->deref.child == NULL);
> +      const unsigned size = glsl_get_length(deref->var->type);
> +      const unsigned base = MIN2(deref_array->base_offset, size - 1);
>  
> -      image = offset(image, bld,
> -                     deref_array->base_offset * BRW_IMAGE_PARAM_SIZE);
> +      image = offset(image, bld, base * BRW_IMAGE_PARAM_SIZE);
>  
>        if (deref_array->deref_array_type == nir_deref_array_type_indirect) {
>           fs_reg *tmp = new(mem_ctx) fs_reg(vgrf(glsl_type::int_type));
> -         bld.MUL(*tmp, get_nir_src(deref_array->indirect),
> -                 fs_reg(BRW_IMAGE_PARAM_SIZE));
> +
> +         if (devinfo->gen == 7 && !devinfo->is_haswell) {
> +            /* IVB hangs when trying to access an invalid surface index with
> +             * the dataport.  According to the spec "if the index used to
> +             * select an individual element is negative or greater than or
> +             * equal to the size of the array, the results of the operation
> +             * are undefined but may not lead to termination" -- which is one
> +             * of the possible outcomes of the hang.  Clamp the index to
> +             * prevent access outside of the array bounds.
> +             */
> +            bld.emit_minmax(*tmp, retype(get_nir_src(deref_array->indirect),
> +                                         BRW_REGISTER_TYPE_UD),
> +                            fs_reg(size - base - 1), BRW_CONDITIONAL_L);
> +         } else {
> +            bld.MOV(*tmp, get_nir_src(deref_array->indirect));
> +         }
> +
> +         bld.MUL(*tmp, *tmp, fs_reg(BRW_IMAGE_PARAM_SIZE));
>           image.reladdr = tmp;
>        }
>     }
> -- 
> 2.4.6
> 


More information about the mesa-dev mailing list