From 6e0b5a874d35edd60d918b759931b4a7642a3f77 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Sun, 14 Dec 2025 21:40:14 +0300 Subject: [PATCH] rxs: Improve alpha-to-coverage emulation --- rpcs3/Emu/RSX/NV47/HW/nv4097.cpp | 28 +++++++++++++++++++ rpcs3/Emu/RSX/NV47/HW/nv4097.h | 2 ++ .../GLSLSnippets/RSXProg/RSXROPEpilogue.glsl | 2 +- rpcs3/Emu/RSX/rsx_methods.cpp | 2 +- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp index 8db588da60..929925bcb1 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp +++ b/rpcs3/Emu/RSX/NV47/HW/nv4097.cpp @@ -306,6 +306,34 @@ namespace rsx REGS(ctx)->decode(reg, REGS(ctx)->latch); } + void set_aa_control(context* ctx, u32 reg, u32 arg) + { + const auto latch = REGS(ctx)->latch; + if (arg == latch) + { + return; + } + + // Reconfigure pipeline. + RSX(ctx)->m_graphics_state |= rsx::pipeline_config_dirty; + + // If we support A2C in hardware, leave the rest upto the hardware. The pipeline config should take care of it. + const auto& backend_config = RSX(ctx)->get_backend_config(); + if (backend_config.supports_hw_a2c && + backend_config.supports_hw_a2c_1spp) + { + return; + } + + // No A2C hardware support or partial hardware support. Invalidate the current program if A2C state changed. + const auto a2c_old = REGS(ctx)->decode(latch).msaa_alpha_to_coverage(); + const auto a2c_new = REGS(ctx)->decode(arg).msaa_alpha_to_coverage(); + if (a2c_old != a2c_new) + { + RSX(ctx)->m_graphics_state |= rsx::fragment_program_state_dirty; + } + } + ///// Draw call setup (vertex, etc) void set_array_element16(context* ctx, u32, u32 arg) diff --git a/rpcs3/Emu/RSX/NV47/HW/nv4097.h b/rpcs3/Emu/RSX/NV47/HW/nv4097.h index db736396b9..a5a434e47d 100644 --- a/rpcs3/Emu/RSX/NV47/HW/nv4097.h +++ b/rpcs3/Emu/RSX/NV47/HW/nv4097.h @@ -87,6 +87,8 @@ namespace rsx void set_transform_constant_load(context* ctx, u32 reg, u32 arg); + void set_aa_control(context* ctx, u32 reg, u32 arg); + #define RSX(ctx) ctx->rsxthr #define REGS(ctx) (&rsx::method_registers) diff --git a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPEpilogue.glsl b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPEpilogue.glsl index 283371d0ed..240186cd29 100644 --- a/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPEpilogue.glsl +++ b/rpcs3/Emu/RSX/Program/GLSLSnippets/RSXProg/RSXROPEpilogue.glsl @@ -32,7 +32,7 @@ R"( #endif #ifdef _ENABLE_ALPHA_TO_COVERAGE_TEST - if (!_test_bit(rop_control, MSAA_WRITE_ENABLE_BIT) || !coverage_test_passes(col0)) + if (!coverage_test_passes(col0)) { discard; } diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 3d12440882..03bbd1e52a 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -717,7 +717,6 @@ namespace rsx state_signals[NV4097_SET_ALPHA_FUNC] = rsx::fragment_state_dirty; state_signals[NV4097_SET_ALPHA_REF] = rsx::fragment_state_dirty; state_signals[NV4097_SET_ALPHA_TEST_ENABLE] = rsx::fragment_program_state_dirty; - state_signals[NV4097_SET_ANTI_ALIASING_CONTROL] = rsx::fragment_program_state_dirty; state_signals[NV4097_SET_SHADER_PACKER] = rsx::fragment_program_state_dirty; state_signals[NV4097_SET_SHADER_WINDOW] = rsx::fragment_state_dirty; state_signals[NV4097_SET_FOG_MODE] = rsx::fragment_state_dirty; @@ -1714,6 +1713,7 @@ namespace rsx bind(NV4097_SET_BLEND_EQUATION, nv4097::set_blend_equation); bind(NV4097_SET_BLEND_FUNC_SFACTOR, nv4097::set_blend_factor); bind(NV4097_SET_BLEND_FUNC_DFACTOR, nv4097::set_blend_factor); + bind(NV4097_SET_ANTI_ALIASING_CONTROL, nv4097::set_aa_control); //NV308A (0xa400..0xbffc!) bind_array(NV308A_COLOR, 1, 256 * 7, nv308a::color::impl);