From 9776c1cff204ff3a38b7dd6e8c6a171d2719f556 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Wed, 25 May 2022 15:57:53 +0200 Subject: [PATCH] ac/llvm: add use_waterfall_for_divergent_tex_samplers option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GLSL says that indexing in a samplers array should be done with a dynamically uniform value. If the app doesn't obey this constraint, it'll get incorrect results. But there's one case where the app might be correct and yet get incorrect result: if 2 consecutive draws are used, with no state changes in between, the hardware might run them in the same wave and the app will get incorrect result as-if it was using non-dynamically uniform index. To prevent this, this commit takes advantage of the divergence analysis pass - if the index is marked as divergent, then it will have the same effect as using ACCESS_NON_UNIFORM in SPIR-V. Reviewed-by: Marek Olšák Part-of: --- src/amd/llvm/ac_nir_to_llvm.c | 16 ++++++++++++++-- src/amd/llvm/ac_shader_abi.h | 4 ++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/amd/llvm/ac_nir_to_llvm.c b/src/amd/llvm/ac_nir_to_llvm.c index 9f61aa29484..3b740cf9431 100644 --- a/src/amd/llvm/ac_nir_to_llvm.c +++ b/src/amd/llvm/ac_nir_to_llvm.c @@ -4583,10 +4583,22 @@ static void tex_fetch_ptrs(struct ac_nir_context *ctx, nir_tex_instr *instr, LLVMValueRef sampler_dynamic_index = get_sampler_desc_index(ctx, sampler_deref_instr, &instr->instr, false); - if (instr->texture_non_uniform) + + /* instr->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, and use enter_waterfall. + * See https://gitlab.freedesktop.org/mesa/mesa/-/issues/2253. + */ + if (instr->texture_non_uniform || + (ctx->abi->use_waterfall_for_divergent_tex_samplers && texture_deref_instr->dest.ssa.divergent)) texture_dynamic_index = enter_waterfall(ctx, wctx + 0, texture_dynamic_index, true); - if (instr->sampler_non_uniform) + if (instr->sampler_non_uniform || + (ctx->abi->use_waterfall_for_divergent_tex_samplers && sampler_deref_instr->dest.ssa.divergent)) sampler_dynamic_index = enter_waterfall(ctx, wctx + 1, sampler_dynamic_index, true); *res_ptr = get_sampler_desc(ctx, texture_deref_instr, main_descriptor, &instr->instr, diff --git a/src/amd/llvm/ac_shader_abi.h b/src/amd/llvm/ac_shader_abi.h index 0c370ffbc9b..2d2697b2e71 100644 --- a/src/amd/llvm/ac_shader_abi.h +++ b/src/amd/llvm/ac_shader_abi.h @@ -129,6 +129,10 @@ struct ac_shader_abi { /* Whether to inline the compute dispatch size in user sgprs. */ bool load_grid_size_from_user_sgpr; + + /* Whether to detect divergent textures/samplers index and apply + * waterfall to avoid incorrect rendering. */ + bool use_waterfall_for_divergent_tex_samplers; }; #endif /* AC_SHADER_ABI_H */