From ea2f4d57fa16ad0719d1218d837b3944af6e0921 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 16 Jul 2019 22:23:13 +0300 Subject: [PATCH] rsx: Fixups --- rpcs3/Emu/RSX/Common/surface_store.h | 17 +-------------- rpcs3/Emu/RSX/Common/surface_utils.h | 31 ++++++++++++++++++++++++++++ rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 9 +++++--- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 13 +++++++----- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 6ed07f9f5b..d3d6a9778b 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -196,7 +196,7 @@ namespace rsx { auto surface = Traits::get(e.second); - if (new_surface->last_use_tag > surface->last_use_tag || + if (new_surface->last_use_tag >= surface->last_use_tag || new_surface == surface || address == e.first) { @@ -274,15 +274,6 @@ namespace rsx for (const auto& e : list2) surface_info.push_back(e); } - if (UNLIKELY(surface_info.size() > 1)) - { - // Sort with oldest first for early exit - std::sort(surface_info.begin(), surface_info.end(), [](const auto& a, const auto& b) - { - return (a.second->last_use_tag < b.second->last_use_tag); - }); - } - // TODO: Modify deferred_clip_region::direct_copy() to take a few more things into account! const areau child_region = new_surface->get_normalized_memory_area(); const auto child_w = child_region.width(); @@ -343,12 +334,6 @@ namespace rsx continue; } - if (child_w == size.width && child_h == size.height && surface_info.size() > 1) - { - // If the write covers the whole area, discard anything older - new_surface->clear_rw_barrier(); - } - // TODO: Eventually need to stack all the overlapping regions, but for now just do the latest rect in the space deferred_clipped_region region; region.src_x = src_offset.x; diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h index b12ee0c0ec..7960a6155e 100644 --- a/rpcs3/Emu/RSX/Common/surface_utils.h +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -318,6 +318,37 @@ namespace rsx old_contents.clear(); } + template + u32 prepare_rw_barrier_for_transfer(T *target) + { + if (old_contents.size() <= 1) + return 0; + + // Sort here before doing transfers since surfaces may have been updated in the meantime + std::sort(old_contents.begin(), old_contents.end(), [](auto& a, auto &b) + { + auto _a = static_cast(a.source); + auto _b = static_cast(b.source); + return (_a->last_use_tag < _b->last_use_tag); + }); + + // Try and optimize by omitting possible overlapped transfers + for (size_t i = old_contents.size() - 1; i > 0 /* Intentional */; i--) + { + old_contents[i].init_transfer(target); + + const auto dst_area = old_contents[i].dst_rect(); + if (unsigned(dst_area.x2) == target->width() && unsigned(dst_area.y2) == target->height() && + !dst_area.x1 && !dst_area.y1) + { + // This transfer will overwrite everything older + return u32(i); + } + } + + return 0; + } + template void set_old_contents(T* other) { diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index 9867cf650c..3e2b94d989 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -623,11 +623,15 @@ void gl::render_target::memory_barrier(gl::command_context& cmd, bool force_init return; } - for (auto §ion : old_contents) + const bool dst_is_depth = !!(aspect() & gl::image_aspect::depth); + const auto dst_bpp = get_bpp(); + unsigned first = prepare_rw_barrier_for_transfer(this); + + for (auto i = first; i < old_contents.size(); ++i) { + auto §ion = old_contents[i]; auto src_texture = gl::as_rtt(section.source); const auto src_bpp = src_texture->get_bpp(); - const auto dst_bpp = get_bpp(); rsx::typeless_xfer typeless_info{}; if (get_internal_format() == src_texture->get_internal_format()) @@ -649,7 +653,6 @@ void gl::render_target::memory_barrier(gl::command_context& cmd, bool force_init } } - const bool dst_is_depth = !!(aspect() & gl::image_aspect::depth); section.init_transfer(this); if (state_flags & rsx::surface_state_flags::erase_bkgnd) diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 96398ee0c3..c5b18d65ca 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -315,14 +315,20 @@ namespace vk return; } + // Memory transfers + vk::image *target_image = (samples() > 1) ? get_resolve_target() : this; + vk::blitter hw_blitter; bool optimize_copy = true; - for (auto §ion : old_contents) + const auto dst_bpp = get_bpp(); + unsigned first = prepare_rw_barrier_for_transfer(this); + + for (auto i = first; i < old_contents.size(); ++i) { + auto §ion = old_contents[i]; auto src_texture = static_cast(section.source); src_texture->read_barrier(cmd); const auto src_bpp = src_texture->get_bpp(); - const auto dst_bpp = get_bpp(); rsx::typeless_xfer typeless_info{}; if (src_texture->info.format == info.format) @@ -342,9 +348,7 @@ namespace vk } } - vk::blitter hw_blitter; section.init_transfer(this); - auto src_area = section.src_rect(); auto dst_area = section.dst_rect(); @@ -354,7 +358,6 @@ namespace vk this->transform_pixels_to_samples(dst_area); } - vk::image *target_image = (samples() > 1) ? get_resolve_target() : this; bool memory_load = true; if (dst_area.x1 == 0 && dst_area.y1 == 0 && unsigned(dst_area.x2) == target_image->width() && unsigned(dst_area.y2) == target_image->height())