ac/nir/ngg: Mitigate attribute ring wait bug when primitive ID is per-primitive.

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 <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33218>
This commit is contained in:
Timur Kristóf
2025-01-29 17:35:06 +01:00
committed by Marge Bot
parent 397d45d055
commit 7a3d95bbe2
+17 -4
View File
@@ -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;