From d972a6ac4c8e16bc656d87620fdb298aa6059c68 Mon Sep 17 00:00:00 2001 From: Andrii Simiklit Date: Mon, 31 Aug 2020 15:09:43 +0300 Subject: [PATCH] nir: get rid of OOB dereferences in nir_lower_io_arrays_to_elements This patch fixes mesa compiler crash in i965 on shaders like the following one: ``` in VS_OUTPUT { mat4 data; } vs_output; out vec4 fs_output; vec4 convert(in float val) { return vec4(val); } void main() { fs_output = vec4(0.0); for (int a = -1; a < 5; a++) { for (int b = -1; b < 5; b++) { fs_output += convert(vs_output.data[b][a]); } } } ``` Section 5.11 (Out-of-Bounds Accesses) of the GLSL 4.60 spec says: In the subsections described above for array, vector, matrix and structure accesses, any out-of-bounds access produced undefined behavior.... Out-of-bounds reads return undefined values, which include values from other variables of the active program or zero. Out-of-bounds writes may be discarded or overwrite other variables of the active program. GL_KHR_robustness and GL_ARB_robustness encourage us to return zero for reads. Reviewed-by: Rhys Perry Signed-off-by: Andrii Simiklit Part-of: --- src/compiler/nir/nir_lower_io_arrays_to_elements.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/compiler/nir/nir_lower_io_arrays_to_elements.c b/src/compiler/nir/nir_lower_io_arrays_to_elements.c index 376326575b0..26036673ed0 100644 --- a/src/compiler/nir/nir_lower_io_arrays_to_elements.c +++ b/src/compiler/nir/nir_lower_io_arrays_to_elements.c @@ -115,6 +115,18 @@ lower_array(nir_builder *b, nir_intrinsic_instr *intr, nir_variable *var, { b->cursor = nir_before_instr(&intr->instr); + if (nir_deref_instr_is_known_out_of_bounds(nir_src_as_deref(intr->src[0]))) { + /* See Section 5.11 (Out-of-Bounds Accesses) of the GLSL 4.60 */ + if (intr->intrinsic != nir_intrinsic_store_deref) { + nir_ssa_def *zero = nir_imm_zero(b, intr->dest.ssa.num_components, + intr->dest.ssa.bit_size); + nir_ssa_def_rewrite_uses(&intr->dest.ssa, + nir_src_for_ssa(zero)); + } + nir_instr_remove(&intr->instr); + return; + } + nir_variable **elements = get_array_elements(varyings, var, b->shader->info.stage);