From 2a7ebf2ae093644c083c4e0002b332922526a4f2 Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Thu, 28 Aug 2025 17:14:20 +0100 Subject: [PATCH] nir/lower_alpha: extend to support dynamic a2c Signed-off-by: Simon Perretta Reviewed-by: Erik Faye-Lund Part-of: --- src/asahi/lib/agx_nir_prolog_epilog.c | 2 +- src/broadcom/compiler/vir.c | 2 +- src/compiler/nir/nir.h | 3 ++- src/compiler/nir/nir_lower_alpha.c | 4 +++- src/imagination/pco/pco_internal.h | 2 +- src/imagination/pco/pco_nir.c | 5 +---- src/imagination/pco/pco_nir_pvfio.c | 26 +++++++++++++++++++------ src/imagination/vulkan/pvr_cmd_buffer.c | 4 ++++ src/imagination/vulkan/pvr_device.c | 2 +- 9 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/asahi/lib/agx_nir_prolog_epilog.c b/src/asahi/lib/agx_nir_prolog_epilog.c index e66685df963..fe9d5cd506f 100644 --- a/src/asahi/lib/agx_nir_prolog_epilog.c +++ b/src/asahi/lib/agx_nir_prolog_epilog.c @@ -473,7 +473,7 @@ agx_nir_fs_epilog(nir_builder *b, const void *key_) /* Alpha-to-coverage must be lowered before alpha-to-one */ if (key->blend.alpha_to_coverage) NIR_PASS(_, b->shader, nir_lower_alpha_to_coverage, tib.nr_samples, - false); + false, NULL); /* Depth/stencil writes must be deferred until after all discards, * particularly alpha-to-coverage. diff --git a/src/broadcom/compiler/vir.c b/src/broadcom/compiler/vir.c index b2a75cedda5..24045aef46a 100644 --- a/src/broadcom/compiler/vir.c +++ b/src/broadcom/compiler/vir.c @@ -1103,7 +1103,7 @@ v3d_nir_lower_fs_early(struct v3d_compile *c) assert(c->fs_key->msaa); NIR_PASS(_, c->s, nir_lower_alpha_to_coverage, - V3D_MAX_SAMPLES, true); + V3D_MAX_SAMPLES, true, NULL); } if (c->fs_key->sample_alpha_to_one) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index d3a120086ec..3b2898f6f1b 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5455,7 +5455,8 @@ bool nir_lower_vec_to_regs(nir_shader *shader, nir_instr_writemask_filter_cb cb, bool nir_lower_alpha_to_coverage(nir_shader *shader, uint8_t nr_samples, - bool has_intrinsic); + bool has_intrinsic, + nir_def *dyn_enable); bool nir_lower_alpha_to_one(nir_shader *shader); diff --git a/src/compiler/nir/nir_lower_alpha.c b/src/compiler/nir/nir_lower_alpha.c index 62dac29910a..4a5d3231a2d 100644 --- a/src/compiler/nir/nir_lower_alpha.c +++ b/src/compiler/nir/nir_lower_alpha.c @@ -28,7 +28,7 @@ alpha_to_coverage(nir_builder *b, nir_def *alpha, uint8_t nr_samples, bool has_i * monolithic pixel shader or a fragment epilogue. */ bool -nir_lower_alpha_to_coverage(nir_shader *shader, uint8_t nr_samples, bool has_intrinsic) +nir_lower_alpha_to_coverage(nir_shader *shader, uint8_t nr_samples, bool has_intrinsic, nir_def *dyn_enable) { /* If we are not using the intrinsic we need to know the sample count. */ assert(has_intrinsic || nr_samples); @@ -72,6 +72,8 @@ nir_lower_alpha_to_coverage(nir_shader *shader, uint8_t nr_samples, bool has_int nir_builder *b = &_b; nir_def *alpha = nir_channel(b, rgba, 3); + if (dyn_enable) + alpha = nir_bcsel(b, dyn_enable, alpha, nir_imm_floatN_t(b, 1.0f, alpha->bit_size)); nir_def *mask = alpha_to_coverage(b, alpha, nr_samples, has_intrinsic); /* Discard samples that aren't covered */ diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index 6051f7363b5..62e7b7d6457 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -1761,10 +1761,10 @@ bool pco_nir_link_multiview(nir_shader *producer, pco_data *consumer_data); bool pco_nir_lower_algebraic(nir_shader *shader); bool pco_nir_lower_algebraic_late(nir_shader *shader); +bool pco_nir_lower_alpha_to_coverage(nir_shader *shader); bool pco_nir_lower_atomics(nir_shader *shader, pco_data *data); bool pco_nir_lower_barriers(nir_shader *shader, pco_data *data); bool pco_nir_lower_clip_cull_vars(nir_shader *shader); -bool pco_nir_lower_demote_samples(nir_shader *shader); bool pco_nir_lower_fs_intrinsics(nir_shader *shader); bool pco_nir_lower_vs_intrinsics(nir_shader *shader); bool pco_nir_lower_images(nir_shader *shader, pco_data *data); diff --git a/src/imagination/pco/pco_nir.c b/src/imagination/pco/pco_nir.c index 76388e9351f..bcaf6fc0c81 100644 --- a/src/imagination/pco/pco_nir.c +++ b/src/imagination/pco/pco_nir.c @@ -886,10 +886,7 @@ void pco_lower_nir(pco_ctx *ctx, nir_shader *nir, pco_data *data) NIR_PASS(_, nir, pco_nir_lower_tex, data, ctx); if (nir->info.stage == MESA_SHADER_FRAGMENT) { - if (data->fs.uses.alpha_to_coverage) { - NIR_PASS(_, nir, nir_lower_alpha_to_coverage, 0, true); - NIR_PASS(_, nir, pco_nir_lower_demote_samples); - } + NIR_PASS(_, nir, pco_nir_lower_alpha_to_coverage); NIR_PASS(_, nir, nir_lower_blend, &data->fs.blend_opts); diff --git a/src/imagination/pco/pco_nir_pvfio.c b/src/imagination/pco/pco_nir_pvfio.c index 3598d4871c8..33e9855fa89 100644 --- a/src/imagination/pco/pco_nir_pvfio.c +++ b/src/imagination/pco/pco_nir_pvfio.c @@ -702,13 +702,27 @@ static bool lower_demote_samples(nir_builder *b, return true; } -bool pco_nir_lower_demote_samples(nir_shader *s) +bool pco_nir_lower_alpha_to_coverage(nir_shader *shader) { - assert(s->info.stage == MESA_SHADER_FRAGMENT); - return nir_shader_intrinsics_pass(s, - lower_demote_samples, - nir_metadata_control_flow, - NULL); + if (shader->info.internal) + return false; + + nir_builder b = nir_builder_create(nir_shader_get_entrypoint(shader)); + b.cursor = + nir_before_block(nir_start_block(nir_shader_get_entrypoint(shader))); + nir_def *a2c_enabled = nir_ine_imm( + &b, + nir_ubitfield_extract_imm(&b, nir_load_fs_meta_pco(&b), 25, 1), + 0); + + nir_lower_alpha_to_coverage(shader, 0, true, a2c_enabled); + + nir_shader_intrinsics_pass(shader, + lower_demote_samples, + nir_metadata_control_flow, + NULL); + + return true; } static nir_def * diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 8b674255e29..2befd3449ae 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -4233,6 +4233,10 @@ static VkResult pvr_setup_descriptor_mappings( cmd_buffer->vk.dynamic_graphics_state.cb.color_write_enables << 1; + if (cmd_buffer->vk.dynamic_graphics_state.ms + .alpha_to_coverage_enable) + fs_meta |= (1 << 25); + struct pvr_suballoc_bo *fs_meta_bo; result = pvr_cmd_buffer_upload_general(cmd_buffer, &fs_meta, diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 07b2019d496..ab48ea3e8ec 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -391,7 +391,7 @@ static void pvr_physical_device_get_supported_features( .extendedDynamicState3PolygonMode = false, .extendedDynamicState3RasterizationSamples = true, .extendedDynamicState3SampleMask = true, - .extendedDynamicState3AlphaToCoverageEnable = false, + .extendedDynamicState3AlphaToCoverageEnable = true, .extendedDynamicState3AlphaToOneEnable = true, .extendedDynamicState3LogicOpEnable = false, .extendedDynamicState3ColorBlendEnable = false,