From ba5eb2f5c18c2124c63f6f45748fd9600fbed0e7 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Fri, 14 Apr 2023 18:25:46 +0800 Subject: [PATCH] radeonsi: add si_mark_divergent_texture_non_uniform MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit For handle divergent index problem later for both llvm and aco. Reviewed-by: Marek Olšák Signed-off-by: Qiang Yu Part-of: --- src/gallium/drivers/radeonsi/si_shader_nir.c | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/gallium/drivers/radeonsi/si_shader_nir.c b/src/gallium/drivers/radeonsi/si_shader_nir.c index db2ac4c..1b735d9 100644 --- a/src/gallium/drivers/radeonsi/si_shader_nir.c +++ b/src/gallium/drivers/radeonsi/si_shader_nir.c @@ -352,6 +352,61 @@ static void si_lower_nir(struct si_screen *sscreen, struct nir_shader *nir) NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL); } +static bool si_mark_divergent_texture_non_uniform(struct nir_shader *nir) +{ + assert(nir->info.divergence_analysis_run); + + /* sampler_non_uniform and texture_non_uniform are always false in GLSL, + * but this can lead to unexpected behavior if texture/sampler index come from + * a vertex attribute. + * + * For instance, 2 consecutive draws using 2 different index values, + * could be squashed together by the hw - producing a single draw with + * non-dynamically uniform index. + * + * To avoid this, detect divergent indexing, mark them as non-uniform, + * so that we can apply waterfall loop on these index later (either llvm + * backend or nir_lower_non_uniform_access). + * + * See https://gitlab.freedesktop.org/mesa/mesa/-/issues/2253 + */ + + bool divergence_changed = false; + + nir_function_impl *impl = nir_shader_get_entrypoint(nir); + nir_foreach_block_safe(block, impl) { + nir_foreach_instr_safe(instr, block) { + if (instr->type != nir_instr_type_tex) + continue; + + nir_tex_instr *tex = nir_instr_as_tex(instr); + for (int i = 0; i < tex->num_srcs; i++) { + bool divergent = tex->src[i].src.ssa->divergent; + + switch (tex->src[i].src_type) { + case nir_tex_src_texture_deref: + case nir_tex_src_texture_handle: + tex->texture_non_uniform |= divergent; + break; + case nir_tex_src_sampler_deref: + case nir_tex_src_sampler_handle: + tex->sampler_non_uniform |= divergent; + break; + default: + break; + } + } + + /* If dest is already divergent, divergence won't change. */ + divergence_changed |= !tex->dest.ssa.divergent && + (tex->texture_non_uniform || tex->sampler_non_uniform); + } + } + + nir_metadata_preserve(impl, nir_metadata_all); + return divergence_changed; +} + char *si_finalize_nir(struct pipe_screen *screen, void *nirptr) { struct si_screen *sscreen = (struct si_screen *)screen; -- 2.7.4