diff --git a/Utilities/lockless.h b/Utilities/lockless.h index 87e726ee3c..f49544ea3d 100644 --- a/Utilities/lockless.h +++ b/Utilities/lockless.h @@ -270,6 +270,30 @@ public: return {}; } + const T& operator[](usz index) const noexcept + { + lf_queue_iterator result = begin(); + + while (--index != umax) + { + result++; + } + + return *result; + } + + T& operator[](usz index) noexcept + { + lf_queue_iterator result = begin(); + + while (--index != umax) + { + result++; + } + + return *result; + } + lf_queue_slice& pop_front() { delete std::exchange(m_head, std::exchange(m_head->m_link, nullptr)); @@ -315,6 +339,23 @@ class lf_queue final public: constexpr lf_queue() = default; + lf_queue(lf_queue&& other) noexcept + { + m_head.release(other.m_head.exchange(0)); + } + + lf_queue& operator=(lf_queue&& other) noexcept + { + if (this == std::addressof(other)) + { + return *this; + } + + delete load(m_head); + m_head.release(other.m_head.exchange(0)); + return *this; + } + ~lf_queue() { delete load(m_head); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 8b53f4ca33..0878feb511 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -3907,6 +3907,8 @@ extern void ppu_precompile(std::vector& dir_queue, std::vectorget(); _main = {}; + auto current_cache = std::move(g_fxo->get()); + if (!ppu_load_exec(obj, true, path)) { // Abort @@ -3916,11 +3918,13 @@ extern void ppu_precompile(std::vector& dir_queue, std::vectorget() = std::move(current_cache); break; } if (!_main.analyse(0, _main.elf_entry, _main.seg0_code_end, _main.applied_pathes, [](){ return Emu.IsStopped(); })) { + g_fxo->get() = std::move(current_cache); break; } @@ -3929,8 +3933,10 @@ extern void ppu_precompile(std::vector& dir_queue, std::vectorget() = std::move(current_cache); break; } @@ -3945,6 +3951,7 @@ extern void ppu_precompile(std::vector& dir_queue, std::vectorget() = std::move(main_module); + g_fxo->get().collect_funcs_to_precompile = true; Emu.ConfigurePPUCache(); }); diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 46eda7110e..28e2f330c5 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -516,20 +516,6 @@ spu_cache::~spu_cache() { } -struct spu_section_data -{ - struct data_t - { - u32 vaddr; - std::basic_string inst_data; - std::vector funcs; - }; - - shared_mutex mtx; - atomic_t had_been_used = false; - std::vector data; -}; - extern void utilize_spu_data_segment(u32 vaddr, const void* ls_data_vaddr, u32 size) { if (vaddr % 4) @@ -549,9 +535,9 @@ extern void utilize_spu_data_segment(u32 vaddr, const void* ls_data_vaddr, u32 s return; } - g_fxo->need(); + g_fxo->need(); - if (g_fxo->get().had_been_used) + if (!g_fxo->get().collect_funcs_to_precompile) { return; } @@ -559,7 +545,7 @@ extern void utilize_spu_data_segment(u32 vaddr, const void* ls_data_vaddr, u32 s std::basic_string data(size / 4, 0); std::memcpy(data.data(), ls_data_vaddr, size); - spu_section_data::data_t obj{vaddr, std::move(data)}; + spu_cache::precompile_data_t obj{vaddr, std::move(data)}; obj.funcs = spu_thread::discover_functions(vaddr, { reinterpret_cast(ls_data_vaddr), size }, vaddr != 0, umax); @@ -576,19 +562,7 @@ extern void utilize_spu_data_segment(u32 vaddr, const void* ls_data_vaddr, u32 s spu_log.notice("Found %u SPU functions", obj.funcs.size()); - std::lock_guard lock(g_fxo->get().mtx); - - for (const auto& data : g_fxo->get().data) - { - // TODO: More robust duplicates filtering - if (data.vaddr == vaddr && data.inst_data.starts_with(obj.inst_data)) - { - spu_log.notice("Avoided duplicate SPU segment"); - return; - } - } - - g_fxo->get().data.emplace_back(std::move(obj)); + g_fxo->get().precompile_funcs.push(std::move(obj)); } std::deque spu_cache::get() @@ -693,8 +667,8 @@ void spu_cache::initialize(bool build_existing_cache) atomic_t fnext{}; atomic_t fail_flag{0}; - auto data_list = std::move(g_fxo->get().data); - g_fxo->get().had_been_used = true; + auto data_list = g_fxo->get().precompile_funcs.pop_all(); + g_fxo->get().collect_funcs_to_precompile = false; u32 total_precompile = 0; @@ -717,7 +691,7 @@ void spu_cache::initialize(bool build_existing_cache) else { total_precompile = 0; - data_list.clear(); + data_list = {}; } atomic_t data_indexer = 0; diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 5dd68184b1..dbe56e9ff1 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -35,6 +35,17 @@ public: void add(const struct spu_program& func); static void initialize(bool build_existing_cache = true); + + struct precompile_data_t + { + u32 vaddr; + std::basic_string inst_data; + std::vector funcs; + }; + + bool collect_funcs_to_precompile = true; + + lf_queue precompile_funcs; }; struct spu_program