kk: Track fragment helper status since Metal does not correctly demote them

When discarding a fragment in Metal, it will not be demoted to helper. At
least for Apple Silicon M1 and M2. Call nir_lower_is_helper_invocation to
work around this.

Reviewed-by: Arcady Goldmints-Orlov <arcady@lunarg.com>
Signed-off-by: Aitor Camacho <aitor@lunarg.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38590>
This commit is contained in:
Aitor Camacho 2025-11-22 21:10:55 +09:00 committed by Marge Bot
parent a015397c52
commit 67d05f71e9
2 changed files with 23 additions and 9 deletions

View file

@ -49,6 +49,22 @@ info on what was updated.
Workarounds
===========
KK_WORKAROUND_4
---------------
| macOS version: 26.0.1
| Metal ticket: FB21124215 (@aitor)
| Metal ticket status: Waiting resolution
| CTS test failure: ``dEQP-VK.draw.renderpass.shader_invocation.helper_invocation*`` and few others
| Comments:
``simd_is_helper_thread()`` will always return true if the shader was started
as a non-helper thread, even after ``discard_fragment()`` is called. The
workaround is to have a variable tracking this state and update it when the
fragment is discarded. This issue is present in M1 and M2 chips.
| Log:
| 2025-11-22: Workaround implemented and reported to Apple
KK_WORKAROUND_3
---------------
| macOS version: 15.4.x

View file

@ -118,10 +118,6 @@ emit_local_vars(struct nir_to_msl_ctx *ctx, nir_shader *shader)
P_IND(ctx, "uchar scratch[%d] = {0};\n", shader->scratch_size);
}
}
if (BITSET_TEST(shader->info.system_values_read,
SYSTEM_VALUE_HELPER_INVOCATION)) {
P_IND(ctx, "bool gl_HelperInvocation = simd_is_helper_thread();\n");
}
}
static bool
@ -969,9 +965,6 @@ intrinsic_to_msl(struct nir_to_msl_ctx *ctx, nir_intrinsic_instr *instr)
P(ctx, "gl_BaseInstance;\n");
break;
case nir_intrinsic_load_helper_invocation:
P(ctx, "gl_HelperInvocation;\n");
break;
case nir_intrinsic_is_helper_invocation:
P(ctx, "simd_is_helper_thread();\n");
break;
case nir_intrinsic_ddx:
@ -1860,12 +1853,19 @@ msl_preprocess_nir(struct nir_shader *nir)
NIR_PASS(_, nir, nir_lower_vars_to_ssa);
NIR_PASS(_, nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
/* lower_system_values needs to go before is_helper_invocation since it will
* generate discards. */
NIR_PASS(_, nir, nir_lower_system_values);
if (nir->info.stage == MESA_SHADER_FRAGMENT) {
nir_input_attachment_options input_attachment_options = {
.use_fragcoord_sysval = true,
.use_layer_id_sysval = true,
};
NIR_PASS(_, nir, nir_lower_input_attachments, &input_attachment_options);
/* KK_WORKAROUND_4 */
NIR_PASS(_, nir, nir_lower_is_helper_invocation);
}
NIR_PASS(_, nir, nir_opt_combine_barriers, NULL, NULL);
NIR_PASS(_, nir, nir_lower_var_copies);
@ -1881,8 +1881,6 @@ msl_preprocess_nir(struct nir_shader *nir)
glsl_get_natural_size_align_bytes,
glsl_get_natural_size_align_bytes);
NIR_PASS(_, nir, nir_lower_system_values);
nir_lower_compute_system_values_options csv_options = {
.has_base_global_invocation_id = 0,
.has_base_workgroup_id = true,