ac/llvm: add use_waterfall_for_divergent_tex_samplers option

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 <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16709>
This commit is contained in:
Pierre-Eric Pelloux-Prayer
2022-05-25 15:57:53 +02:00
committed by Marge Bot
parent 9ff04985b9
commit 9776c1cff2
2 changed files with 18 additions and 2 deletions

View File

@@ -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,

View File

@@ -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 */