From f00d9a7c7fa014b41ec335844d992ca58aed1fe8 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 7 Mar 2018 23:09:38 +0300 Subject: [PATCH] rssx" Halfplement alpha-to-coverage AA transparency --- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 38 ++++++++++++++++++++++++-------- rpcs3/Emu/RSX/RSXThread.cpp | 28 +++++++++++++++++++---- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 39 ++++++++++++++++++++++++++------- 3 files changed, 84 insertions(+), 21 deletions(-) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index ed6990976e..7302d2c4a6 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -1187,7 +1187,7 @@ void GLGSRender::update_draw_state() } } - const bool mrt_blend_enabled[] = + bool mrt_blend_enabled[] = { rsx::method_registers.blend_enabled(), rsx::method_registers.blend_enabled_surface_1(), @@ -1195,18 +1195,38 @@ void GLGSRender::update_draw_state() rsx::method_registers.blend_enabled_surface_3() }; + bool blend_equation_override = false; + if (rsx::method_registers.msaa_alpha_to_coverage_enabled() && + !rsx::method_registers.alpha_test_enabled()) + { + if (rsx::method_registers.msaa_enabled() && + rsx::method_registers.msaa_sample_mask() && + rsx::method_registers.surface_antialias() != rsx::surface_antialiasing::center_1_sample) + { + //fake alpha-to-coverage + //blend used in conjunction with alpha test to fake order-independent edge transparency + mrt_blend_enabled[0] = mrt_blend_enabled[1] = mrt_blend_enabled[2] = mrt_blend_enabled[3] = true; + blend_equation_override = true; + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBlendEquation(GL_FUNC_ADD); + } + } + if (mrt_blend_enabled[0] || mrt_blend_enabled[1] || mrt_blend_enabled[2] || mrt_blend_enabled[3]) { - glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()), - blend_factor(rsx::method_registers.blend_func_dfactor_rgb()), - blend_factor(rsx::method_registers.blend_func_sfactor_a()), - blend_factor(rsx::method_registers.blend_func_dfactor_a())); + if (!blend_equation_override) + { + glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()), + blend_factor(rsx::method_registers.blend_func_dfactor_rgb()), + blend_factor(rsx::method_registers.blend_func_sfactor_a()), + blend_factor(rsx::method_registers.blend_func_dfactor_a())); - auto blend_colors = rsx::get_constant_blend_colors(); - glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]); + auto blend_colors = rsx::get_constant_blend_colors(); + glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]); - glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()), - blend_equation(rsx::method_registers.blend_equation_a())); + glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()), + blend_equation(rsx::method_registers.blend_equation_a())); + } } gl_state.enablei(mrt_blend_enabled[0], GL_BLEND, 0); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ae44525774..32c0ce7e17 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -543,8 +543,11 @@ namespace rsx performance_counters.FIFO_idle_timestamp = get_system_time(); performance_counters.FIFO_is_idle = true; } + else + { + do_internal_task(); + } - do_internal_task(); continue; } @@ -950,11 +953,28 @@ namespace rsx void thread::fill_fragment_state_buffer(void *buffer, const RSXFragmentProgram &fragment_program) { - const u32 is_alpha_tested = rsx::method_registers.alpha_test_enabled(); - const f32 alpha_ref = rsx::method_registers.alpha_ref() / 255.f; + //TODO: Properly support alpha-to-coverage and alpha-to-one behavior in shaders + auto fragment_alpha_func = rsx::method_registers.alpha_func(); + auto alpha_ref = rsx::method_registers.alpha_ref() / 255.f; + auto is_alpha_tested = (u32)rsx::method_registers.alpha_test_enabled(); + + if (rsx::method_registers.msaa_alpha_to_coverage_enabled() && !is_alpha_tested) + { + if (rsx::method_registers.msaa_enabled() && + rsx::method_registers.surface_antialias() != rsx::surface_antialiasing::center_1_sample) + { + //alpha values generate a coverage mask for order independent blending + //requires hardware AA to work properly (or just fragment sample stage in fragment shaders) + //simulated using combined alpha blend and alpha test + fragment_alpha_func = rsx::comparison_function::greater; + alpha_ref = rsx::method_registers.msaa_sample_mask()? 0.25f : 0.f; + is_alpha_tested |= (1 << 4); + } + } + const f32 fog0 = rsx::method_registers.fog_params_0(); const f32 fog1 = rsx::method_registers.fog_params_1(); - const u32 alpha_func = static_cast(rsx::method_registers.alpha_func()); + const u32 alpha_func = static_cast(fragment_alpha_func); const u32 fog_mode = static_cast(rsx::method_registers.fog_equation()); // Generate wpos coeffecients diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index acc3466a32..b87aac0ea6 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -2165,7 +2165,7 @@ void VKGSRender::load_program(const vk::vertex_upload_info& vertex_info) properties.att_state[idx].colorWriteMask = mask; } - const bool mrt_blend_enabled[] = + bool mrt_blend_enabled[] = { rsx::method_registers.blend_enabled(), rsx::method_registers.blend_enabled_surface_1(), @@ -2173,15 +2173,38 @@ void VKGSRender::load_program(const vk::vertex_upload_info& vertex_info) rsx::method_registers.blend_enabled_surface_3() }; + bool blend_equation_override = false; + VkBlendFactor sfactor_rgb, sfactor_a, dfactor_rgb, dfactor_a; + VkBlendOp equation_rgb, equation_a; + + if (rsx::method_registers.msaa_alpha_to_coverage_enabled() && + !rsx::method_registers.alpha_test_enabled()) + { + if (rsx::method_registers.msaa_enabled() && + rsx::method_registers.msaa_sample_mask() && + rsx::method_registers.surface_antialias() != rsx::surface_antialiasing::center_1_sample) + { + //fake alpha-to-coverage + //blend used in conjunction with alpha test to fake order-independent edge transparency + mrt_blend_enabled[0] = mrt_blend_enabled[1] = mrt_blend_enabled[2] = mrt_blend_enabled[3] = true; + blend_equation_override = true; + sfactor_rgb = sfactor_a = VK_BLEND_FACTOR_SRC_ALPHA; + dfactor_rgb = dfactor_a = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + equation_rgb = equation_a = VK_BLEND_OP_ADD; + } + } + if (mrt_blend_enabled[0] || mrt_blend_enabled[1] || mrt_blend_enabled[2] || mrt_blend_enabled[3]) { - VkBlendFactor sfactor_rgb = vk::get_blend_factor(rsx::method_registers.blend_func_sfactor_rgb()); - VkBlendFactor sfactor_a = vk::get_blend_factor(rsx::method_registers.blend_func_sfactor_a()); - VkBlendFactor dfactor_rgb = vk::get_blend_factor(rsx::method_registers.blend_func_dfactor_rgb()); - VkBlendFactor dfactor_a = vk::get_blend_factor(rsx::method_registers.blend_func_dfactor_a()); - - VkBlendOp equation_rgb = vk::get_blend_op(rsx::method_registers.blend_equation_rgb()); - VkBlendOp equation_a = vk::get_blend_op(rsx::method_registers.blend_equation_a()); + if (!blend_equation_override) + { + sfactor_rgb = vk::get_blend_factor(rsx::method_registers.blend_func_sfactor_rgb()); + sfactor_a = vk::get_blend_factor(rsx::method_registers.blend_func_sfactor_a()); + dfactor_rgb = vk::get_blend_factor(rsx::method_registers.blend_func_dfactor_rgb()); + dfactor_a = vk::get_blend_factor(rsx::method_registers.blend_func_dfactor_a()); + equation_rgb = vk::get_blend_op(rsx::method_registers.blend_equation_rgb()); + equation_a = vk::get_blend_op(rsx::method_registers.blend_equation_a()); + } for (u8 idx = 0; idx < m_draw_buffers_count; ++idx) {