mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-07 02:10:12 +01:00
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 <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32344>
This commit is contained in:
parent
c23abb12e8
commit
8fc640b256
1 changed files with 17 additions and 4 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue