From e179adc4a0fdabeec4131f95b9894e5d38bfe585 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Mon, 8 Aug 2022 19:27:53 +0300 Subject: [PATCH] rsx: Refactor surface cache storage --- rpcs3/Emu/RSX/Common/ranged_map.hpp | 6 + .../Emu/RSX/Common/surface_cache_storage.hpp | 113 ++++++++++++++++++ rpcs3/Emu/RSX/Common/surface_store.h | 6 +- rpcs3/Emu/RSX/GL/GLRenderTargets.h | 24 +++- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 23 +++- rpcs3/emucore.vcxproj | 1 + rpcs3/emucore.vcxproj.filters | 3 + 7 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 rpcs3/Emu/RSX/Common/surface_cache_storage.hpp diff --git a/rpcs3/Emu/RSX/Common/ranged_map.hpp b/rpcs3/Emu/RSX/Common/ranged_map.hpp index ddd8c76761..44cacc7be9 100644 --- a/rpcs3/Emu/RSX/Common/ranged_map.hpp +++ b/rpcs3/Emu/RSX/Common/ranged_map.hpp @@ -10,6 +10,7 @@ namespace rsx template class ranged_map { + protected: struct block_metadata_t { u32 id = umax; // ID of the matadata blob @@ -30,6 +31,11 @@ namespace rsx return address / BlockSize; } + static inline u32 block_address(u32 block_id) + { + return block_id * BlockSize; + } + void broadcast_insert(const utils::address_range& range) { const auto head_block = block_for(range.start); diff --git a/rpcs3/Emu/RSX/Common/surface_cache_storage.hpp b/rpcs3/Emu/RSX/Common/surface_cache_storage.hpp new file mode 100644 index 0000000000..4f0e0b7db8 --- /dev/null +++ b/rpcs3/Emu/RSX/Common/surface_cache_storage.hpp @@ -0,0 +1,113 @@ +#pragma once +#include "ranged_map.hpp" + +namespace rsx +{ + template + class surface_cache_data_map : public ranged_map + { + using super = class ranged_map; + using metadata_t = typename super::block_metadata_t; + + const metadata_t& find_head_block(u32 address) + { + auto& meta = super::m_metadata[address]; + if (meta.head_block != umax) + { + return find_head_block(meta.head_block * BlockSize); + } + + return meta; + } + + public: + using buffer_object_storage_type = typename Traits::buffer_object_storage_type; + using buffer_object_type = typename Traits::buffer_object_type; + + struct buffer_object_t + { + buffer_object_storage_type bo; + u64 memory_tag = 0; + + inline buffer_object_type get() + { + return Traits::get(bo); + } + + inline void release() + { + bo.release(); + } + + inline void acquire(buffer_object_type obj) + { + ensure(!get()); + bo = obj; + } + }; + + protected: + using buffer_block_array = typename std::array; + buffer_block_array m_buffer_list; + + public: + surface_cache_data_map() + : super::ranged_map() + {} + + surface_cache_data_map& with_range(const utils::address_range& range) + { + // Prepare underlying memory so that the range specified is provisioned and contiguous + const auto& head_block = find_head_block(range.start); + const auto start_address = block_address(head_block.id); + + const auto& current = m_buffer_list[head_block.id]; + if (auto bo = current.get()) + { + if (::size32(*bo) >= (range.end - start_address)) + { + return *this; + } + } + + // Data does not exist or is not contiguous. Merge the layer + std::vector bo_list; + for (u32 address = start_address; address <= range.end;) + { + auto& bo_storage = m_buffer_list[super::block_for(address)]; + if (auto bo = bo_storage.get()) + { + bo_list.push_back(bo); + bo_storage.release(); + address += ::size32(*bo); + continue; + } + + bo_list.push_back(nullptr); + address += BlockSize; + } + + auto unified = Traits::merge_bo_list(bo_list); + ensure(unified); + + current.acquire(unified); + return *this; + } + + void spill(const utils::address_range& range) + { + // Move VRAM to system RAM + const auto& meta = with_range(range).find_head_block(range.start); + auto& storage = m_buffer_list[meta.id]; + Traits::spill_buffer(storage.bo); + } + + void unspill(const utils::address_range& range) + { + // Move system RAM to VRAM + const auto& meta = with_range(range).find_head_block(range.start); + auto& storage = m_buffer_list[meta.id]; + Traits::unspill_buffer(storage.bo); + } + }; +} diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index a1e5154d00..4d5005fd64 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -2,7 +2,7 @@ #include "surface_utils.h" #include "simple_array.hpp" -#include "ranged_map.hpp" +#include "surface_cache_storage.hpp" #include "../gcm_enums.h" #include "../rsx_utils.h" #include @@ -20,7 +20,7 @@ namespace rsx usz get_packed_pitch(surface_color_format format, u32 width); } - template + template struct surface_store { static constexpr u32 get_aa_factor_u(surface_antialiasing aa_mode) @@ -45,7 +45,7 @@ namespace rsx using surface_type = typename Traits::surface_type; using command_list_type = typename Traits::command_list_type; using surface_overlap_info = surface_overlap_info_t; - using surface_ranged_map = typename rsx::ranged_map; + using surface_ranged_map = surface_cache_data_map; protected: surface_ranged_map m_render_targets_storage = {}; diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index 77e32f34b6..e837ed84af 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -124,6 +124,8 @@ struct gl_render_target_traits { using surface_storage_type = std::unique_ptr; using surface_type = gl::render_target*; + using buffer_object_storage_type = std::unique_ptr; + using buffer_object_type = gl::buffer*; using command_list_type = gl::command_context&; using download_buffer_object = std::vector; using barrier_descriptor_t = rsx::deferred_clipped_region; @@ -346,7 +348,27 @@ struct gl_render_target_traits } static - gl::render_target* get(const std::unique_ptr &in) + void spill_buffer(std::unique_ptr& bo) + { + // TODO + } + + static + void unspill_buffer(std::unique_ptr& bo) + { + // TODO + } + + static + gl::buffer* merge_bo_list(const std::vector& list) + { + // TODO + return nullptr; + } + + template + static + T* get(const std::unique_ptr &in) { return in.get(); } diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index f966830a43..5902125eb5 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -85,6 +85,8 @@ namespace vk { using surface_storage_type = std::unique_ptr; using surface_type = vk::render_target*; + using buffer_object_storage_type = std::unique_ptr; + using buffer_object_type = vk::buffer*; using command_list_type = vk::command_buffer&; using download_buffer_object = void*; using barrier_descriptor_t = rsx::deferred_clipped_region; @@ -451,9 +453,26 @@ namespace vk return int_surface_matches_properties(surface, vk_format, width, height, antialias, check_refs); } - static vk::render_target* get(const std::unique_ptr& tex) + static void spill_buffer(std::unique_ptr& bo) { - return tex.get(); + // TODO + } + + static void unspill_buffer(std::unique_ptr& bo) + { + // TODO + } + + static vk::buffer* merge_bo_list(const std::vector& list) + { + // TODO + return nullptr; + } + + template + static T* get(const std::unique_ptr& obj) + { + return obj.get(); } }; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 65cd5e1c54..ef8abee7e4 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -514,6 +514,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index e7a4f5e2a6..d1f86e949b 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -2140,6 +2140,9 @@ Emu\GPU\RSX\Common + + Emu\GPU\RSX\Common + Emu\CPU