From 7a3d95bbe2fc939c5e7aedc87751150c1f011f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timur=20Krist=C3=B3f?= Date: Wed, 29 Jan 2025 17:35:06 +0100 Subject: [PATCH] ac/nir/ngg: Mitigate attribute ring wait bug when primitive ID is per-primitive. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a possibility that some waves in an NGG workgroup don't have any input vertices, only primitives. When these waves store the primitive ID as a per-primitive attribute, they will need to wait for those stores before the primitive export, because the other waves can't wait for them. Cc: mesa-stable Reviewed-by: Marek Olšák Part-of: --- src/amd/common/nir/ac_nir_lower_ngg.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/amd/common/nir/ac_nir_lower_ngg.c b/src/amd/common/nir/ac_nir_lower_ngg.c index 86acb7defe6..ffd32bacbce 100644 --- a/src/amd/common/nir/ac_nir_lower_ngg.c +++ b/src/amd/common/nir/ac_nir_lower_ngg.c @@ -2468,6 +2468,7 @@ ac_nir_lower_ngg_nogs(nir_shader *shader, const ac_nir_lower_ngg_options *option options->can_cull ? nir_local_variable_create(impl, glsl_bool_type(), "gs_accepted") : NULL; nir_variable *gs_exported_var = nir_local_variable_create(impl, glsl_bool_type(), "gs_exported"); + const bool wait_attr_ring = must_wait_attr_ring(options->gfx_level, options->has_param_exports); bool streamout_enabled = shader->xfb_info && !options->disable_streamout; bool has_user_edgeflags = options->use_edgeflags && (shader->info.outputs_written & VARYING_BIT_EDGE); @@ -2478,9 +2479,14 @@ ac_nir_lower_ngg_nogs(nir_shader *shader, const ac_nir_lower_ngg_options *option * Always use late prim export when user edge flags are enabled. * This is because edge flags are written by ES threads but they * are exported by GS threads as part of th primitive export. + * + * When the primitive ID output is configured as a per-primitive, + * and the shader must wait for attribute ring waits before exports, + * we must always use late primitive export. */ - bool early_prim_export = - options->early_prim_export && !(streamout_enabled || has_user_edgeflags); + const bool early_prim_export = + options->early_prim_export && !(streamout_enabled || has_user_edgeflags) && + !(wait_attr_ring && options->export_primitive_id_per_prim); lower_ngg_nogs_state state = { .options = options, @@ -2654,6 +2660,15 @@ ac_nir_lower_ngg_nogs(nir_shader *shader, const ac_nir_lower_ngg_options *option /* Take care of late primitive export */ if (!state.early_prim_export) { b->cursor = nir_after_impl(impl); + + if (wait_attr_ring && options->export_primitive_id_per_prim) { + /* Wait for the per-primitive primitive ID store to finish. */ + nir_barrier(b, .execution_scope = SCOPE_SUBGROUP, + .memory_scope = SCOPE_DEVICE, + .memory_semantics = NIR_MEMORY_RELEASE, + .memory_modes = nir_var_mem_ssbo | nir_var_shader_out | nir_var_mem_global | nir_var_image); + } + emit_ngg_nogs_prim_export(b, &state, nir_load_var(b, prim_exp_arg_var)); } @@ -2662,8 +2677,6 @@ ac_nir_lower_ngg_nogs(nir_shader *shader, const ac_nir_lower_ngg_options *option export_outputs &= ~VARYING_BIT_PSIZ; if (options->kill_layer) export_outputs &= ~VARYING_BIT_LAYER; - - const bool wait_attr_ring = must_wait_attr_ring(options->gfx_level, options->has_param_exports); if (wait_attr_ring) export_outputs &= ~VARYING_BIT_POS;