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;