diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index 5ede03b59b..315f0cbf1e 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2155,7 +2155,7 @@ namespace rsx * 3. Surface is swapped back in. Surface cache resets layout to optimal rasterization layout * 4. During bind, the surface is converted to shader layout because it is not in GENERAL layout */ - if (!g_cfg.video.strict_rendering_mode) + if (!texture_cache_helpers::force_strict_fbo_sampling(result.second->samples())) { insert_texture_barrier(cmd, result.second, false); } diff --git a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h index 629f40888a..e70eed7401 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h @@ -96,6 +96,24 @@ namespace rsx namespace texture_cache_helpers { + static inline bool force_strict_fbo_sampling(u8 samples) + { + if (g_cfg.video.strict_rendering_mode) + { + // Strict mode. All access is strict. + return true; + } + + if (g_cfg.video.antialiasing_level == msaa_level::none) + { + // MSAA disabled. All access is fast. + return false; + } + + // Strict access if MSAA only. + return samples > 1 && !!g_cfg.video.force_hw_MSAA_resolve; + } + static inline bool is_gcm_depth_format(u32 format) { switch (format) @@ -665,7 +683,7 @@ namespace rsx } } - if (surface_is_rop_target && g_cfg.video.strict_rendering_mode) + if (surface_is_rop_target && texture_cache_helpers::force_strict_fbo_sampling(texptr->samples())) { // Framebuffer feedback avoidance. For MSAA, we do not need to make copies; just use the resolve target if (texptr->samples() == 1) diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index f39962e3a6..d03b776ced 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -161,6 +161,7 @@ struct cfg_root : cfg::node cfg::_bool strict_texture_flushing{ this, "Strict Texture Flushing", false }; cfg::_bool multithreaded_rsx{ this, "Multithreaded RSX", false }; cfg::_bool relaxed_zcull_sync{ this, "Relaxed ZCULL Sync", false }; + cfg::_bool force_hw_MSAA_resolve{ this, "Force Hardware MSAA Resolve", false, true }; cfg::_enum stereo_render_mode{ this, "3D Display Mode", stereo_render_mode_options::disabled }; cfg::_bool debug_program_analyser{ this, "Debug Program Analyser", false }; cfg::_bool precise_zpass_count{ this, "Accurate ZCULL stats", true }; diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index ca55d53ee7..9316014fd3 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -102,6 +102,7 @@ enum class emu_settings_type AllowHostGPULabels, DisableMSLFastMath, OutputScalingMode, + ForceHwMSAAResolve, // Performance Overlay PerfOverlayEnabled, @@ -282,6 +283,7 @@ inline static const QMap settings_location = { emu_settings_type::AllowHostGPULabels, { "Video", "Allow Host GPU Labels"}}, { emu_settings_type::DisableMSLFastMath, { "Video", "Disable MSL Fast Math"}}, { emu_settings_type::OutputScalingMode, { "Video", "Output Scaling Mode"}}, + { emu_settings_type::ForceHwMSAAResolve, { "Video", "Force Hardware MSAA Resolve"}}, // Vulkan { emu_settings_type::VulkanAsyncTextureUploads, { "Video", "Vulkan", "Asynchronous Texture Streaming 2"}}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index b56792b509..6e1a1d1b13 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -2308,6 +2308,9 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceCheckBox(ui->disableVertexCache, emu_settings_type::DisableVertexCache); SubscribeTooltip(ui->disableVertexCache, tooltips.settings.disable_vertex_cache); + m_emu_settings->EnhanceCheckBox(ui->forceHwMSAAResolve, emu_settings_type::ForceHwMSAAResolve); + SubscribeTooltip(ui->forceHwMSAAResolve, tooltips.settings.force_hw_MSAA); + // Checkboxes: core debug options m_emu_settings->EnhanceCheckBox(ui->alwaysStart, emu_settings_type::StartOnBoot); SubscribeTooltip(ui->alwaysStart, tooltips.settings.start_on_boot); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 8cdab09b03..50646de24a 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -2657,6 +2657,13 @@ + + + + Force Hardware MSAA Resolve + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index f70461400b..cb89ba1e30 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -39,6 +39,7 @@ public: const QString handle_tiled_memory = tr("Obey RSX memory tiling configuration when writing GPU data to vm memory.\nThis can fix graphics corruption observed when Read Color or Read Depth options are enabled."); const QString disable_on_disk_shader_cache = tr("Disables the loading and saving of shaders from and to the shader cache in the data directory."); const QString allow_host_labels = tr("Allows the host GPU to synchronize with CELL directly. This incurs a performance penalty, but exposes the true state of GPU objects to the guest CPU. Can help eliminate visual noise and glitching at the cost of performance. Use with caution."); + const QString force_hw_MSAA = tr("Forces MSAA to use the host GPU's resolve capabilities for all sampling operations.\nThis option incurs a performance penalty as well as the risk of visual artifacts but can yield crisper visuals when MSAA is enabled."); const QString disable_vertex_cache = tr("Disables the vertex cache.\nMight resolve missing or flickering graphics output.\nMay degrade performance."); const QString zcull_operation_mode = tr("Changes ZCULL report synchronization behaviour. Experiment to find the best option for your game. Approximate mode is recommended for most games.\n· Precise is the most accurate to PS3 behaviour. Required for accurate visuals in some titles such as Demon's Souls and The Darkness.\n· Approximate is a much faster way to generate occlusion data which may not always match what the PS3 would generate. Works well with most PS3 games.\n· Relaxed changes the synchronization method completely and can greatly improve performance in some games or completely break others."); const QString max_spurs_threads = tr("Limits the maximum number of SPURS threads in each thread group.\nMay improve performance in some cases, especially on systems with limited number of hardware threads.\nLimiting the number of threads is likely to cause crashes; it's recommended to keep this at the default value.");