From af1d3c2aa69d5144735dd8df05a4fb655d72a473 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 31 Oct 2017 21:01:24 +0300 Subject: [PATCH] rsx: Improve surface store resource management - vk: Use frame testing to determine invalidated resources that can be safely deleted --- rpcs3/Emu/RSX/Common/surface_store.h | 16 ++++++++++++++++ rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h | 3 +++ rpcs3/Emu/RSX/GL/GLRenderTargets.h | 4 ++++ rpcs3/Emu/RSX/VK/VKRenderTargets.h | 17 +++++++++++++++-- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index dbaa8aed0e..f3400f2b9e 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -165,8 +165,11 @@ namespace rsx new_surface_storage = std::move(rtt); if (old_surface) + { //Exchange this surface with the invalidated one + Traits::notify_surface_invalidated(old_surface_storage); rtt = std::move(old_surface_storage); + } else //rtt is now empty - erase it invalidated_resources.erase(It); @@ -179,8 +182,11 @@ namespace rsx } if (old_surface != nullptr && new_surface == nullptr) + { //This was already determined to be invalid and is excluded from testing above + Traits::notify_surface_invalidated(old_surface_storage); invalidated_resources.push_back(std::move(old_surface_storage)); + } if (new_surface != nullptr) { @@ -229,8 +235,11 @@ namespace rsx new_surface_storage = std::move(ds); if (old_surface) + { //Exchange this surface with the invalidated one + Traits::notify_surface_invalidated(old_surface_storage); ds = std::move(old_surface_storage); + } else invalidated_resources.erase(It); @@ -242,8 +251,11 @@ namespace rsx } if (old_surface != nullptr && new_surface == nullptr) + { //This was already determined to be invalid and is excluded from testing above + Traits::notify_surface_invalidated(old_surface_storage); invalidated_resources.push_back(std::move(old_surface_storage)); + } if (new_surface != nullptr) { @@ -498,6 +510,7 @@ namespace rsx if (surface == ref) { + Traits::notify_surface_invalidated(It->second); invalidated_resources.push_back(std::move(It->second)); m_render_targets_storage.erase(It); @@ -515,6 +528,7 @@ namespace rsx if (surface == ref) { + Traits::notify_surface_invalidated(It->second); invalidated_resources.push_back(std::move(It->second)); m_depth_stencil_storage.erase(It); @@ -541,6 +555,7 @@ namespace rsx auto It = m_render_targets_storage.find(addr); if (It != m_render_targets_storage.end()) { + Traits::notify_surface_invalidated(It->second); invalidated_resources.push_back(std::move(It->second)); m_render_targets_storage.erase(It); @@ -553,6 +568,7 @@ namespace rsx auto It = m_depth_stencil_storage.find(addr); if (It != m_depth_stencil_storage.end()) { + Traits::notify_surface_invalidated(It->second); invalidated_resources.push_back(std::move(It->second)); m_depth_stencil_storage.erase(It); diff --git a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h index 6b1da86704..ef45073680 100644 --- a/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h +++ b/rpcs3/Emu/RSX/D3D12/D3D12RenderTargetSets.h @@ -142,6 +142,9 @@ struct render_target_traits //TODO } + static + void notify_surface_invalidated(const ComPtr&) + {} static bool rtt_has_format_width_height(const ComPtr &rtt, surface_color_format surface_color_format, size_t width, size_t height, bool=false) diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index ee3c16cb08..250fc11293 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -253,6 +253,10 @@ struct gl_render_target_traits static void invalidate_rtt_surface_contents(void *, gl::render_target *rtt, gl::render_target* /*old*/, bool forced) { if (forced) rtt->set_cleared(false); } static void invalidate_depth_surface_contents(void *, gl::render_target *ds, gl::render_target* /*old*/, bool) { ds->set_cleared(false); } + static + void notify_surface_invalidated(const std::unique_ptr&) + {} + static bool rtt_has_format_width_height(const std::unique_ptr &rtt, rsx::surface_color_format format, size_t width, size_t height, bool check_refs=false) { diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 8fd7052cb9..c971245c89 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -26,6 +26,7 @@ namespace vk std::unique_ptr view; render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing + u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid render_target(vk::render_device &dev, uint32_t memory_type_index, @@ -223,6 +224,7 @@ namespace rsx //Reset deref count surface->deref_count = 0; + surface->frame_tag = 0; } static void prepare_rtt_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface) @@ -238,6 +240,7 @@ namespace rsx //Reset deref count surface->deref_count = 0; + surface->frame_tag = 0; } static void prepare_ds_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface) @@ -261,6 +264,12 @@ namespace rsx ds->old_contents = old_surface; } + static + void notify_surface_invalidated(const std::unique_ptr &surface) + { + surface->frame_tag = vk::get_current_frame_id(); + } + static bool rtt_has_format_width_height(const std::unique_ptr &rtt, surface_color_format format, size_t width, size_t height, bool check_refs=false) { if (check_refs && rtt->deref_count == 0) //Surface may still have read refs from data 'copy' @@ -337,9 +346,13 @@ namespace rsx void free_invalidated() { - invalidated_resources.remove_if([](std::unique_ptr &rtt) + const u64 last_finished_frame = vk::get_last_completed_frame_id(); + invalidated_resources.remove_if([&](std::unique_ptr &rtt) { - if (rtt->deref_count >= 2) return true; + verify(HERE), rtt->frame_tag != 0; + + if (rtt->deref_count >= 2 && rtt->frame_tag < last_finished_frame) + return true; rtt->deref_count++; return false;