diff --git a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp index 389efe0a2e..9d218edb89 100644 --- a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp +++ b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp @@ -667,7 +667,23 @@ namespace rsx rop_control.enable_polygon_stipple(); } - if (REGS(m_ctx)->msaa_alpha_to_coverage_enabled() && !RSX(m_ctx)->get_backend_config().supports_hw_a2c) + auto can_use_hw_a2c = [&]() -> bool + { + const auto& config = RSX(m_ctx)->get_backend_config(); + if (!config.supports_hw_a2c) + { + return false; + } + + if (config.supports_hw_a2c_1spp) + { + return true; + } + + return REGS(m_ctx)->surface_antialias() != rsx::surface_antialiasing::center_1_sample; + }; + + if (REGS(m_ctx)->msaa_alpha_to_coverage_enabled() && !can_use_hw_a2c()) { // TODO: Properly support alpha-to-coverage and alpha-to-one behavior in shaders // Alpha values generate a coverage mask for order independent blending diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 3dcac04f09..b2de00e3b7 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -3,6 +3,8 @@ #include "../rsx_methods.h" #include "../Common/BufferUtils.h" +#include "Emu/RSX/NV47/HW/context_accessors.define.h" + namespace gl { GLenum comparison_op(rsx::comparison_function op) @@ -256,6 +258,32 @@ void GLGSRender::update_draw_state() gl_state.enablei(mrt_blend_enabled[2], GL_BLEND, 2); gl_state.enablei(mrt_blend_enabled[3], GL_BLEND, 3); } + + // Antialias control + if (backend_config.supports_hw_msaa) + { + gl_state.enable(/*REGS(m_ctx)->msaa_enabled()*/GL_MULTISAMPLE); + + gl_state.enable(GL_SAMPLE_MASK); + gl_state.sample_mask(REGS(m_ctx)->msaa_sample_mask()); + + gl_state.enable(GL_SAMPLE_SHADING); + gl_state.min_sample_shading_rate(1.f); + + gl_state.enable(GL_SAMPLE_COVERAGE); + gl_state.sample_coverage(1.f); + } + + if (backend_config.supports_hw_a2c) + { + const bool hw_enable = backend_config.supports_hw_a2c_1spp || REGS(m_ctx)->surface_antialias() != rsx::surface_antialiasing::center_1_sample; + gl_state.enable(hw_enable && REGS(m_ctx)->msaa_alpha_to_coverage_enabled(), GL_SAMPLE_ALPHA_TO_COVERAGE); + } + + if (backend_config.supports_hw_a2one) + { + gl_state.enable(REGS(m_ctx)->msaa_alpha_to_one_enabled(), GL_SAMPLE_ALPHA_TO_ONE); + } } switch (rsx::method_registers.current_draw_clause.primitive) @@ -307,12 +335,6 @@ void GLGSRender::update_draw_state() // Clip planes gl_state.clip_planes((current_vertex_program.output_mask >> CELL_GCM_ATTRIB_OUTPUT_UC0) & 0x3F); - // Sample control - // TODO: MinSampleShading - //gl_state.enable(rsx::method_registers.msaa_enabled(), GL_MULTISAMPLE); - //gl_state.enable(rsx::method_registers.msaa_alpha_to_coverage_enabled(), GL_SAMPLE_ALPHA_TO_COVERAGE); - //gl_state.enable(rsx::method_registers.msaa_alpha_to_one_enabled(), GL_SAMPLE_ALPHA_TO_ONE); - //TODO //NV4097_SET_ANISO_SPREAD //NV4097_SET_SPECULAR_ENABLE diff --git a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp index af51240c88..f6d5d2f3b4 100644 --- a/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp +++ b/rpcs3/Emu/RSX/GL/GLFragmentProgram.cpp @@ -5,6 +5,7 @@ #include "GLCommonDecompiler.h" #include "../GCM.h" #include "../Program/GLSLCommon.h" +#include "../RSXThread.h" std::string GLFragmentDecompilerThread::getFloatTypeName(usz elementCount) { @@ -218,7 +219,7 @@ void GLFragmentDecompilerThread::insertGlobalFunctions(std::stringstream &OS) m_shader_props.require_srgb_to_linear = properties.has_upg; m_shader_props.require_linear_to_srgb = properties.has_pkg; m_shader_props.require_fog_read = properties.in_register_mask & in_fogc; - m_shader_props.emulate_coverage_tests = true; // g_cfg.video.antialiasing_level == msaa_level::none; + m_shader_props.emulate_coverage_tests = !rsx::get_renderer_backend_config().supports_hw_a2c_1spp; m_shader_props.emulate_shadow_compare = device_props.emulate_depth_compare; m_shader_props.low_precision_tests = ::gl::get_driver_caps().vendor_NVIDIA && !(m_prog.ctrl & RSX_SHADER_CONTROL_ATTRIBUTE_INTERPOLATION); m_shader_props.disable_early_discard = !::gl::get_driver_caps().vendor_NVIDIA; diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 8e24cecf4f..6dbd7f919c 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -47,8 +47,6 @@ GLGSRender::GLGSRender(utils::serial* ar) noexcept : GSRender(ar) else m_vertex_cache = std::make_unique(); - backend_config.supports_hw_a2c = false; - backend_config.supports_hw_a2one = false; backend_config.supports_multidraw = true; backend_config.supports_normalized_barycentrics = true; @@ -56,6 +54,8 @@ GLGSRender::GLGSRender(utils::serial* ar) noexcept : GSRender(ar) { backend_config.supports_hw_msaa = true; backend_config.supports_hw_a2c = true; + backend_config.supports_hw_a2c_1spp = false; // In OGL A2C is implicitly disabled at 1spp + backend_config.supports_hw_a2one = true; } } diff --git a/rpcs3/Emu/RSX/GL/GLProcTable.h b/rpcs3/Emu/RSX/GL/GLProcTable.h index e36b47ab8b..783701e4dd 100644 --- a/rpcs3/Emu/RSX/GL/GLProcTable.h +++ b/rpcs3/Emu/RSX/GL/GLProcTable.h @@ -262,6 +262,9 @@ OPENGL_PROC(PFNGLTEXSTORAGE3DPROC, TexStorage3D); // ARB_texture_multisample OPENGL_PROC(PFNGLTEXSTORAGE2DMULTISAMPLEPROC, TexStorage2DMultisample); OPENGL_PROC(PFNGLTEXSTORAGE3DMULTISAMPLEPROC, TexStorage3DMultisample); +OPENGL_PROC(PFNGLSAMPLEMASKIPROC, SampleMaski); +OPENGL_PROC(PFNGLMINSAMPLESHADINGPROC, MinSampleShading); +OPENGL_PROC(PFNGLSAMPLECOVERAGEPROC, SampleCoverage); // Texture_View OPENGL_PROC(PFNGLTEXTUREVIEWPROC, TextureView); diff --git a/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp b/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp index 8020b45936..ffc4fe38f1 100644 --- a/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp +++ b/rpcs3/Emu/RSX/GL/glutils/state_tracker.hpp @@ -309,6 +309,32 @@ namespace gl } } + void sample_mask(GLbitfield mask) + { + if (!test_and_set_property(GL_SAMPLE_MASK_VALUE, mask)) + { + glSampleMaski(0, mask); + } + } + + void sample_coverage(GLclampf coverage) + { + const u32 value = std::bit_cast(coverage); + if (!test_and_set_property(GL_SAMPLE_COVERAGE_VALUE, value)) + { + glSampleCoverage(coverage, GL_FALSE); + } + } + + void min_sample_shading_rate(GLclampf rate) + { + const u32 value = std::bit_cast(rate); + if (!test_and_set_property(GL_MIN_SAMPLE_SHADING_VALUE, value)) + { + glMinSampleShading(rate); + } + } + void clip_planes(GLuint mask) { if (!test_and_set_property(CLIP_PLANES, mask)) diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 257c70e4a5..4da43908c0 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -87,6 +87,7 @@ namespace rsx { bool supports_multidraw; // Draw call batching bool supports_hw_a2c; // Alpha to coverage + bool supports_hw_a2c_1spp; // Alpha to coverage at 1 sample per pixel bool supports_hw_renormalization; // Should be true on NV hardware which matches PS3 texture renormalization behaviour bool supports_hw_msaa; // MSAA support bool supports_hw_a2one; // Alpha to one @@ -466,4 +467,9 @@ namespace rsx { return g_fxo->try_get(); } + + inline const backend_configuration& get_renderer_backend_config() + { + return g_fxo->get().get_backend_config(); + } } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 573f837707..2305e515e4 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -630,6 +630,7 @@ VKGSRender::VKGSRender(utils::serial* ar) noexcept : GSRender(ar) { backend_config.supports_hw_msaa = true; backend_config.supports_hw_a2c = true; + backend_config.supports_hw_a2c_1spp = true; backend_config.supports_hw_a2one = m_device->get_alpha_to_one_support(); }