From bca5f94b3f9208bf8fb99a8344c083721ea6cac0 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Thu, 6 Jun 2019 13:25:32 +0300 Subject: [PATCH] rsx: Add option to toggle MSAA --- rpcs3/Emu/RSX/Common/surface_utils.h | 21 ++++++++++- rpcs3/Emu/RSX/Common/texture_cache.h | 10 ++--- rpcs3/Emu/RSX/RSXThread.cpp | 6 +-- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 56 +++++++++++++++++++++------- rpcs3/Emu/RSX/VK/VKResolveHelper.h | 4 +- rpcs3/Emu/System.cpp | 15 ++++++++ rpcs3/Emu/System.h | 7 ++++ rpcs3/Json/tooltips.json | 1 + rpcs3/rpcs3qt/emu_settings.h | 2 + rpcs3/rpcs3qt/settings_dialog.cpp | 3 ++ rpcs3/rpcs3qt/settings_dialog.ui | 3 -- 11 files changed, 99 insertions(+), 29 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h index 6ebf116bf9..6dc68f6c49 100644 --- a/rpcs3/Emu/RSX/Common/surface_utils.h +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -16,6 +16,12 @@ namespace rsx require_unresolve = 4 }; + enum surface_sample_layout : u32 + { + null = 0, + ps3 = 1 + }; + template struct surface_overlap_info_t { @@ -137,6 +143,7 @@ namespace rsx u8 samples_y = 1; std::unique_ptr::type> resolve_surface; + surface_sample_layout sample_layout = surface_sample_layout::null; flags32_t memory_usage_flags = surface_usage_flags::unknown; flags32_t state_flags = surface_state_flags::ready; @@ -444,7 +451,7 @@ namespace rsx // HACK!! This should be cleared through memory barriers only state_flags = rsx::surface_state_flags::ready; - if (spp > 1) + if (spp > 1 && sample_layout != surface_sample_layout::null) { msaa_flags = resolve_flags; } @@ -518,5 +525,15 @@ namespace rsx y1 *= samples_y; y2 *= samples_y; } + + template + void transform_blit_coordinates(rsx::surface_access access_type, area_base& region) + { + if (spp == 1 || sample_layout == rsx::surface_sample_layout::ps3) + return; + + verify(HERE), access_type != rsx::surface_access::write; + transform_samples_to_pixels(region); + } }; -} +} \ No newline at end of file diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index ea77f35312..fe1d0823ba 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2889,18 +2889,16 @@ namespace rsx } } - if (src_is_render_target && - dynamic_cast(vram_texture) != nullptr) + if (src_is_render_target) { // The resource is of surface type; possibly disabled AA emulation - src_subres.surface->transform_samples_to_pixels(src_area); + src_subres.surface->transform_blit_coordinates(rsx::surface_access::transfer, src_area); } - if (dst_is_render_target && - dynamic_cast(dest_texture) != nullptr) + if (dst_is_render_target) { // The resource is of surface type; possibly disabled AA emulation - dst_subres.surface->transform_samples_to_pixels(dst_area); + dst_subres.surface->transform_blit_coordinates(rsx::surface_access::transfer, dst_area); } typeless_info.analyse(); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index fb18801480..6448b45128 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -658,9 +658,9 @@ namespace rsx auto alpha_ref = rsx::method_registers.alpha_ref() / 255.f; auto rop_control = rsx::method_registers.alpha_test_enabled()? 1u : 0u; - if (0 && - rsx::method_registers.msaa_alpha_to_coverage_enabled() && - rsx::method_registers.surface_antialias() != rsx::surface_antialiasing::center_1_sample) + if (rsx::method_registers.msaa_alpha_to_coverage_enabled() && + rsx::method_registers.surface_antialias() != rsx::surface_antialiasing::center_1_sample && + g_cfg.video.antialiasing_level == msaa_level::none) { // Alpha values generate a coverage mask for order independent blending // Requires hardware AA to work properly (or just fragment sample stage in fragment shaders) diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index c7465aef5c..082485ab92 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -22,7 +22,7 @@ namespace vk vk::viewable_image* get_surface(rsx::surface_access access_type) override { - if (spp == 1 || access_type == rsx::surface_access::write) + if (samples() == 1 || access_type == rsx::surface_access::write) { return this; } @@ -277,7 +277,7 @@ namespace vk }; const bool read_access = (access != rsx::surface_access::write); - if (spp > 1 && read_access) + if (samples() > 1 && read_access) { get_resolve_target(); } @@ -352,10 +352,13 @@ namespace vk auto src_area = old_contents.src_rect(); auto dst_area = old_contents.dst_rect(); - src_texture->transform_pixels_to_samples(src_area); - this->transform_pixels_to_samples(dst_area); + if (g_cfg.video.antialiasing_level != msaa_level::none) + { + src_texture->transform_pixels_to_samples(src_area); + this->transform_pixels_to_samples(dst_area); + } - vk::image *target_image = (spp > 1) ? get_resolve_target() : this; + vk::image *target_image = (samples() > 1) ? get_resolve_target() : this; if (dst_area.x1 == 0 && dst_area.y1 == 0 && unsigned(dst_area.x2) == target_image->width() && unsigned(dst_area.y2) == target_image->height()) { @@ -386,7 +389,7 @@ namespace vk on_write_copy(); - if (!read_access && spp > 1) + if (!read_access && samples() > 1) { // Write barrier, must initialize unresolve(cmd); @@ -421,11 +424,23 @@ namespace rsx vk::render_device &device, vk::command_buffer& cmd) { const auto fmt = vk::get_compatible_surface_format(format); - const auto spp = get_format_sample_count(antialias); VkFormat requested_format = fmt.first; - VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; - if (antialias == rsx::surface_antialiasing::center_1_sample) + u8 samples; + surface_sample_layout sample_layout; + if (g_cfg.video.antialiasing_level == msaa_level::_auto) + { + samples = get_format_sample_count(antialias); + sample_layout = surface_sample_layout::ps3; + } + else + { + samples = 1; + sample_layout = surface_sample_layout::null; + } + + VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + if (LIKELY(samples == 1)) { usage_flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; } @@ -440,7 +455,7 @@ namespace rsx VK_IMAGE_TYPE_2D, requested_format, static_cast(rsx::apply_resolution_scale((u16)width, true)), static_cast(rsx::apply_resolution_scale((u16)height, true)), 1, 1, 1, - static_cast(spp), + static_cast(samples), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, usage_flags, @@ -450,6 +465,7 @@ namespace rsx rtt->set_format(format); rtt->set_aa_mode(antialias); + rtt->sample_layout = sample_layout; rtt->memory_usage_flags = rsx::surface_usage_flags::attachment; rtt->state_flags = rsx::surface_state_flags::erase_bkgnd; rtt->native_component_map = fmt.second; @@ -471,10 +487,22 @@ namespace rsx vk::render_device &device, vk::command_buffer& cmd) { const VkFormat requested_format = vk::get_compatible_depth_surface_format(device.get_formats_support(), format); - const auto spp = get_format_sample_count(antialias); VkImageUsageFlags usage_flags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - if (antialias == rsx::surface_antialiasing::center_1_sample) + u8 samples; + surface_sample_layout sample_layout; + if (g_cfg.video.antialiasing_level == msaa_level::_auto) + { + samples = get_format_sample_count(antialias); + sample_layout = surface_sample_layout::ps3; + } + else + { + samples = 1; + sample_layout = surface_sample_layout::null; + } + + if (LIKELY(samples == 1)) { usage_flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; } @@ -485,7 +513,7 @@ namespace rsx VK_IMAGE_TYPE_2D, requested_format, static_cast(rsx::apply_resolution_scale((u16)width, true)), static_cast(rsx::apply_resolution_scale((u16)height, true)), 1, 1, 1, - static_cast(spp), + static_cast(samples), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_TILING_OPTIMAL, usage_flags, @@ -495,6 +523,7 @@ namespace rsx ds->set_format(format); ds->set_aa_mode(antialias); + ds->sample_layout = sample_layout; ds->memory_usage_flags= rsx::surface_usage_flags::attachment; ds->state_flags = rsx::surface_state_flags::erase_bkgnd; ds->native_component_map = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R }; @@ -540,6 +569,7 @@ namespace rsx sink->memory_usage_flags = rsx::surface_usage_flags::storage; sink->state_flags = rsx::surface_state_flags::erase_bkgnd; sink->native_component_map = ref->native_component_map; + sink->sample_layout = ref->sample_layout; sink->native_pitch = u16(prev.width * ref->get_bpp() * ref->samples_x); sink->surface_width = prev.width; sink->surface_height = prev.height; diff --git a/rpcs3/Emu/RSX/VK/VKResolveHelper.h b/rpcs3/Emu/RSX/VK/VKResolveHelper.h index 8839e43e89..389c8d493f 100644 --- a/rpcs3/Emu/RSX/VK/VKResolveHelper.h +++ b/rpcs3/Emu/RSX/VK/VKResolveHelper.h @@ -256,7 +256,7 @@ namespace vk depthonly_resolve() { build( - " ivec2 out_coord = ivec2(gl_FragCoord.xy);\n" + " ivec2 out_coord = ivec2(gl_FragCoord.xy);\n" " ivec2 in_coord = (out_coord / regs[0].xy);\n" " ivec2 sample_loc = out_coord % ivec2(regs[0].xy);\n" " int sample_index = sample_loc.x + (sample_loc.y * regs[0].y);\n" @@ -325,7 +325,7 @@ namespace vk m_num_usable_samplers = 2; build( - " ivec2 out_coord = ivec2(gl_FragCoord.xy);\n" + " ivec2 out_coord = ivec2(gl_FragCoord.xy);\n" " ivec2 in_coord = (out_coord / regs[0].xy);\n" " ivec2 sample_loc = out_coord % ivec2(regs[0].xy);\n" " int sample_index = sample_loc.x + (sample_loc.y * regs[0].y);\n" diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index ba48fecf1b..71d0d66f77 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -171,6 +171,21 @@ void fmt_class_string::format(std::string& out, u64 arg) }); } +template <> +void fmt_class_string::format(std::string& out, u64 arg) +{ + format_enum(out, arg, [](msaa_level value) + { + switch (value) + { + case msaa_level::none: return "Disabled"; + case msaa_level::_auto: return "Auto"; + } + + return unknown; + }); +} + template <> void fmt_class_string::format(std::string& out, u64 arg) { diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 8ae7c33f05..a0933775ba 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -148,6 +148,12 @@ enum class frame_limit_type _auto, }; +enum class msaa_level +{ + none, + _auto +}; + enum class detail_level { minimal, @@ -430,6 +436,7 @@ struct cfg_root : cfg::node cfg::_enum resolution{this, "Resolution", video_resolution::_720}; cfg::_enum aspect_ratio{this, "Aspect ratio", video_aspect::_16_9}; cfg::_enum frame_limit{this, "Frame limit", frame_limit_type::none}; + cfg::_enum antialiasing_level{this, "MSAA", msaa_level::none}; cfg::_bool write_color_buffers{this, "Write Color Buffers"}; cfg::_bool write_depth_buffer{this, "Write Depth Buffer"}; diff --git a/rpcs3/Json/tooltips.json b/rpcs3/Json/tooltips.json index 24c115dedc..3c94bd901a 100644 --- a/rpcs3/Json/tooltips.json +++ b/rpcs3/Json/tooltips.json @@ -107,6 +107,7 @@ "graphicsAdapterBox_Linux": "On multi GPU systems select which GPU to use in RPCS3 when using Vulkan.\nThis is not needed when using OpenGL.", "aspectBox": "Leave this on 16:9 unless you have a 4:3 monitor.\nAuto also works well, especially if you use a resolution that is not 720p.", "frameLimitBox": "Off is the best option as it performs faster.\nUsing the frame limiter will add extra overhead and slow down the game.\nHowever, some games will crash if the frame rate is too high.\nIf that happens, set value to anything other than Off.", + "antiAliasing": "Emulate PS3 multisampling layout.\nCan fix some otherwise difficult to solve graphics glitches.\nLow to moderate performance hit depending on your GPU hardware.", "anisotropicFilterOverride": "Higher values increase sharpness of textures on sloped surfaces at the cost of GPU resources.\nModern GPUs can handle this setting just fine even at 16x.\nKeep this on Automatic if you want to use the original setting used by a real PS3." }, "sliders": { diff --git a/rpcs3/rpcs3qt/emu_settings.h b/rpcs3/rpcs3qt/emu_settings.h index 5954068453..dc869134ba 100644 --- a/rpcs3/rpcs3qt/emu_settings.h +++ b/rpcs3/rpcs3qt/emu_settings.h @@ -53,6 +53,7 @@ public: Resolution, AspectRatio, FrameLimit, + MSAA, LogShaderPrograms, WriteDepthBuffer, WriteColorBuffers, @@ -262,6 +263,7 @@ private: { Resolution, { "Video", "Resolution"}}, { AspectRatio, { "Video", "Aspect ratio"}}, { FrameLimit, { "Video", "Frame limit"}}, + { MSAA, { "Video", "MSAA"}}, { LogShaderPrograms, { "Video", "Log shader programs"}}, { WriteDepthBuffer, { "Video", "Write Depth Buffer"}}, { WriteColorBuffers, { "Video", "Write Color Buffers"}}, diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 93127a3dd0..0505716812 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -525,6 +525,9 @@ settings_dialog::settings_dialog(std::shared_ptr guiSettings, std: xemu_settings->EnhanceComboBox(ui->frameLimitBox, emu_settings::FrameLimit); SubscribeTooltip(ui->frameLimitBox, json_gpu_cbo["frameLimitBox"].toString()); + xemu_settings->EnhanceComboBox(ui->antiAliasing, emu_settings::MSAA); + SubscribeTooltip(ui->antiAliasing, json_gpu_cbo["antiAliasing"].toString()); + xemu_settings->EnhanceComboBox(ui->anisotropicFilterOverride, emu_settings::AnisotropicFilterOverride, true); SubscribeTooltip(ui->anisotropicFilterOverride, json_gpu_cbo["anisotropicFilterOverride"].toString()); // only allow values 0,2,4,8,16 diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 4884edfe8b..b7e5415ea5 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -468,9 +468,6 @@ - - false - Anti-Aliasing