From 8fc640b256fe40bb4262a640cdcfc27bc9895e1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Mon, 25 Nov 2024 20:41:53 -0500 Subject: [PATCH] nir/lower_io_to_temporaries: fix interp_deref_at_* lowering The pass converts: ... %.. = load_deref(input) to: temp = copy_deref(input) // beginning of the shader ... %.. = load_deref(temp) If interp_deref_at_* occurs between copy_deref and load_deref, the interp_deref_at_* lowering overwrites temp, so all future load_deref(temp) return the result of interp_deref_at_* instead of copy_deref, which is incorrect. The issue manifests when the same input is used by both load_deref and interp_deref_at_* in the same shader and when interp_deref_at_* happens to be before load_deref. This fixes it by using a completely new temporary for each instance of interp_deref_at_*. Reviewed-by: Alyssa Rosenzweig Part-of: --- .../nir/nir_lower_io_to_temporaries.c | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/compiler/nir/nir_lower_io_to_temporaries.c b/src/compiler/nir/nir_lower_io_to_temporaries.c index 5ab89bd1a79..bb6d0f3dbf9 100644 --- a/src/compiler/nir/nir_lower_io_to_temporaries.c +++ b/src/compiler/nir/nir_lower_io_to_temporaries.c @@ -236,14 +236,27 @@ fixup_interpolation_instr(struct lower_io_state *state, nir_variable *input = entry->data; nir_deref_instr *input_root = nir_build_deref_var(b, input); + /* We can't reuse the original temporary because it contains the original + * value of the input that's used throughout the whole shader to replace + * the original load_deref, so we can't overwrite it. Create a new + * temporary that's only used for this interp_deref_at_* opcode. + */ + char *var_name = ralloc_asprintf(NULL, "%s-interp", input->name); + nir_variable *var = nir_local_variable_create(b->impl, input->type, var_name); + ralloc_free(var_name); + nir_deref_instr *new_temp_root = nir_build_deref_var(b, var); + /* Emit the interpolation instructions. */ - emit_interp(b, interp_path.path + 1, temp_root, input_root, interp); + emit_interp(b, interp_path.path + 1, new_temp_root, input_root, interp); /* Now the temporary contains the interpolation results, and we can just - * load from it. We can reuse the original deref, since it points to the - * correct part of the temporary. + * load from it. + * + * Clone the original deref chain, but use the new temporary variable. */ - nir_def *load = nir_load_deref(b, nir_src_as_deref(interp->src[0])); + nir_deref_instr *new_temp_leaf = + nir_clone_deref_instr(b, var, nir_src_as_deref(interp->src[0])); + nir_def *load = nir_load_deref(b, new_temp_leaf); nir_def_replace(&interp->def, load); nir_deref_path_finish(&interp_path);