From 87101e7d83420a733f9d62b1926b158da921ea70 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 1 Mar 2024 17:11:57 -0800 Subject: [PATCH] intel/compiler: Ensure load_barycentric_at_sample and load_interpolated_input remain together This previously worked by luck because we were incorrectly calling nir_opt_remove_phis before calling nir_convert_from_ssa. See also #10727. No shader-db or fossil-db changes on any Intel platform. v2: Handle the load_interpolated_input and load_barycentric_at_sample as separate passes. Based on discussion with Ken starting at https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28136#note_2330424. Fixes: 74a40cc4b6e ("intel/fs: move lower of non-uniform at_sample barycentric to NIR") Reviewed-by: Kenneth Graunke Part-of: --- ..._lower_non_uniform_barycentric_at_sample.c | 73 ++++++++++++++++++- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/src/intel/compiler/intel_nir_lower_non_uniform_barycentric_at_sample.c b/src/intel/compiler/intel_nir_lower_non_uniform_barycentric_at_sample.c index 49fd1b44add..d2538c841e0 100644 --- a/src/intel/compiler/intel_nir_lower_non_uniform_barycentric_at_sample.c +++ b/src/intel/compiler/intel_nir_lower_non_uniform_barycentric_at_sample.c @@ -48,6 +48,9 @@ intel_nir_lower_non_uniform_barycentric_at_sample_instr(nir_builder *b, !nir_src_is_divergent(intrin->src[0])) return false; + if (intrin->def.parent_instr->pass_flags != 0) + return false; + nir_def *sample_id = intrin->src[0].ssa; b->cursor = nir_instr_remove(&intrin->instr); @@ -59,6 +62,7 @@ intel_nir_lower_non_uniform_barycentric_at_sample_instr(nir_builder *b, nir_push_if(b, nir_ieq(b, sample_id, first_sample_id)); { nir_builder_instr_insert(b, &intrin->instr); + intrin->def.parent_instr->pass_flags = 1; nir_src_rewrite(&intrin->src[0], first_sample_id); @@ -69,12 +73,77 @@ intel_nir_lower_non_uniform_barycentric_at_sample_instr(nir_builder *b, return true; } +static bool +intel_nir_lower_non_uniform_interpolated_input_instr(nir_builder *b, + nir_instr *instr, + void *cb_data) +{ + if (instr->type != nir_instr_type_intrinsic) + return false; + + nir_intrinsic_instr *load_ii = nir_instr_as_intrinsic(instr); + if (load_ii->intrinsic != nir_intrinsic_load_interpolated_input) + return false; + + assert(load_ii->src[0].ssa->parent_instr->type == nir_instr_type_intrinsic); + + nir_intrinsic_instr *bary = + nir_instr_as_intrinsic(load_ii->src[0].ssa->parent_instr); + if (bary->intrinsic != nir_intrinsic_load_barycentric_at_sample) + return false; + + if (nir_src_is_always_uniform(bary->src[0]) || + !nir_src_is_divergent(bary->src[0])) + return false; + + nir_def *sample_id = bary->src[0].ssa; + + b->cursor = nir_instr_remove(&load_ii->instr); + + nir_push_loop(b); + { + nir_def *first_sample_id = nir_read_first_invocation(b, sample_id); + + nir_push_if(b, nir_ieq(b, sample_id, first_sample_id)); + { + nir_def *new_bary = nir_load_barycentric_at_sample( + b, bary->def.bit_size, first_sample_id, + .interp_mode = nir_intrinsic_interp_mode(bary)); + + /* Set pass_flags so that the other lowering pass won't try to also + * lower this new load_barycentric_at_sample. + */ + new_bary->parent_instr->pass_flags = 1; + + nir_builder_instr_insert(b, &load_ii->instr); + + nir_src_rewrite(&load_ii->src[0], new_bary); + + nir_jump(b, nir_jump_break); + } + } + + return true; +} + bool intel_nir_lower_non_uniform_barycentric_at_sample(nir_shader *nir) { - return nir_shader_instructions_pass( + bool progress; + + nir_shader_clear_pass_flags(nir); + + progress = nir_shader_instructions_pass( + nir, + intel_nir_lower_non_uniform_interpolated_input_instr, + nir_metadata_none, + NULL); + + progress = nir_shader_instructions_pass( nir, intel_nir_lower_non_uniform_barycentric_at_sample_instr, nir_metadata_none, - NULL); + NULL) || progress; + + return progress; }