From 44c08c3a738cfac91d802625e2491754626b2174 Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 5 Sep 2023 21:15:52 +0300 Subject: [PATCH] PPU/Progress Dialog: Improve remaining time calculation --- rpcs3/Emu/Cell/PPUThread.cpp | 64 ++++++++++++++++++++++-------- rpcs3/Emu/Cell/lv2/sys_overlay.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_prx.cpp | 2 +- rpcs3/Emu/System.cpp | 2 +- rpcs3/Emu/system_progress.cpp | 41 +++++++++++-------- rpcs3/Emu/system_progress.hpp | 3 +- rpcs3/util/asm.hpp | 17 ++++++++ 7 files changed, 95 insertions(+), 36 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index f60e2b040b..5f726cfc89 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -174,7 +174,7 @@ bool serialize(utils::serial& ar, typename ppu_thread::cr_b extern void ppu_initialize(); extern void ppu_finalize(const ppu_module& info); -extern bool ppu_initialize(const ppu_module& info, bool = false); +extern bool ppu_initialize(const ppu_module& info, bool check_only = false, u64 file_size = 0); static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name); extern bool ppu_load_exec(const ppu_exec_object&, bool virtual_load, const std::string&, utils::serial* = nullptr); extern std::pair, CellError> ppu_load_overlay(const ppu_exec_object&, bool virtual_load, const std::string& path, s64 file_offset, utils::serial* = nullptr); @@ -3597,7 +3597,23 @@ extern void ppu_precompile(std::vector& dir_queue, std::vector> file_queue; + struct file_info + { + std::string path; + u64 offset; + u64 file_size; + + file_info() noexcept = default; + + file_info(std::string _path, u64 offs, u64 size) noexcept + : path(std::move(_path)) + , offset(offs) + , file_size(size) + { + } + }; + + std::vector file_queue; file_queue.reserve(2000); // Find all .sprx files recursively @@ -3629,6 +3645,12 @@ extern void ppu_precompile(std::vector& dir_queue, std::vector& dir_queue, std::vector& dir_queue, std::vector& dir_queue, std::vector& dir_queue, std::vector fnext = 0; - lf_queue possible_exec_file_paths; + lf_queue possible_exec_file_paths; shared_mutex ovl_mtx; named_thread_group workers("SPRX Worker ", std::min(utils::get_thread_count(), ::size32(file_queue)), [&] @@ -3756,7 +3788,7 @@ extern void ppu_precompile(std::vector& dir_queue, std::vector& dir_queue, std::vector& dir_queue, std::vector& dir_queue, std::vector& dir_queue, std::vector& dir_queue, std::vector, CellError> ppu_load_overlay(const ppu_exec_object&, bool virtual_load, const std::string& path, s64 file_offset, utils::serial* ar = nullptr); -extern bool ppu_initialize(const ppu_module&, bool = false); +extern bool ppu_initialize(const ppu_module&, bool check_only = false, u64 file_size = 0); extern void ppu_finalize(const ppu_module&); LOG_CHANNEL(sys_overlay); diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index 4a9b7d4ee5..a63ea9fbc3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -19,7 +19,7 @@ extern std::shared_ptr ppu_load_prx(const ppu_prx_object&, bool virtual_load, const std::string&, s64, utils::serial* = nullptr); extern void ppu_unload_prx(const lv2_prx& prx); -extern bool ppu_initialize(const ppu_module&, bool = false); +extern bool ppu_initialize(const ppu_module&, bool check_only = false, u64 file_size = 0); extern void ppu_finalize(const ppu_module&); extern void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size, std::basic_string& loaded_flags); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 7b0aa144d6..07cdfa5ebe 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -75,7 +75,7 @@ extern bool ppu_load_exec(const ppu_exec_object&, bool virtual_load, const std:: extern void spu_load_exec(const spu_exec_object&); extern void spu_load_rel_exec(const spu_rel_object&); extern void ppu_precompile(std::vector& dir_queue, std::vector* loaded_prx); -extern bool ppu_initialize(const ppu_module&, bool = false); +extern bool ppu_initialize(const ppu_module&, bool check_only = false, u64 file_size = 0); extern void ppu_finalize(const ppu_module&); extern void ppu_unload_prx(const lv2_prx&); extern std::shared_ptr ppu_load_prx(const ppu_prx_object&, bool virtual_load, const std::string&, s64 = 0, utils::serial* = nullptr); diff --git a/rpcs3/Emu/system_progress.cpp b/rpcs3/Emu/system_progress.cpp index afb9bbe13b..e02537e3b8 100644 --- a/rpcs3/Emu/system_progress.cpp +++ b/rpcs3/Emu/system_progress.cpp @@ -8,13 +8,16 @@ #include "Emu/RSX/Overlays/overlay_compile_notification.h" #include "Emu/System.h" +#include "util/asm.hpp" + LOG_CHANNEL(sys_log, "SYS"); // Progress display server synchronization variables atomic_t g_progr{}; atomic_t g_progr_ftotal{0}; -atomic_t g_progr_fknown{0}; atomic_t g_progr_fdone{0}; +atomic_t g_progr_ftotal_bits{0}; +atomic_t g_progr_fknown_bits{0}; atomic_t g_progr_ptotal{0}; atomic_t g_progr_pdone{0}; @@ -40,11 +43,11 @@ void progress_dialog_server::operator()() const auto get_state = []() { - auto whole_state = std::make_tuple(+g_progr.load(), +g_progr_ftotal, +g_progr_fknown, +g_progr_fdone, +g_progr_ptotal, +g_progr_pdone); + auto whole_state = std::make_tuple(+g_progr.load(), +g_progr_ftotal, +g_progr_fdone, +g_progr_ftotal_bits, +g_progr_fknown_bits, +g_progr_ptotal, +g_progr_pdone); while (true) { - auto new_state = std::make_tuple(+g_progr.load(), +g_progr_ftotal, +g_progr_fknown, +g_progr_fdone, +g_progr_ptotal, +g_progr_pdone); + auto new_state = std::make_tuple(+g_progr.load(), +g_progr_ftotal, +g_progr_fdone, +g_progr_ftotal_bits, +g_progr_fknown_bits, +g_progr_ptotal, +g_progr_pdone); if (new_state == whole_state) { @@ -72,7 +75,7 @@ void progress_dialog_server::operator()() if (g_progr_ftotal || g_progr_fdone || g_progr_ptotal || g_progr_pdone) { - const auto& [text_new, ftotal, fknown, fdone, ptotal, pdone] = get_state(); + const auto& [text_new, ftotal, fdone, ftotal_bits, fknown_bits, ptotal, pdone] = get_state(); if (text_new) { @@ -84,8 +87,9 @@ void progress_dialog_server::operator()() { // Cleanup (missed message but do not cry over spilt milk) g_progr_fdone -= fdone; - g_progr_fknown -= fknown; g_progr_pdone -= pdone; + g_progr_ftotal_bits -= ftotal_bits; + g_progr_fknown_bits -= fknown_bits; g_progr_ftotal -= ftotal; g_progr_ptotal -= ptotal; g_progr_ptotal.notify_all(); @@ -155,10 +159,11 @@ void progress_dialog_server::operator()() } u32 ftotal = 0; - u32 fdone = 0; - u32 fknown = 0; + u32 fdone = 0; + u32 fknown_bits = 0; + u32 ftotal_bits = 0; u32 ptotal = 0; - u32 pdone = 0; + u32 pdone = 0; const char* text1 = nullptr; const u64 start_time = get_system_time(); @@ -166,13 +171,14 @@ void progress_dialog_server::operator()() // Update progress while (!g_system_progress_stopping && thread_ctrl::state() != thread_state::aborting) { - const auto& [text_new, ftotal_new, fknown_new, fdone_new, ptotal_new, pdone_new] = get_state(); + const auto& [text_new, ftotal_new, fdone_new, ftotal_bits_new, fknown_bits_new, ptotal_new, pdone_new] = get_state(); - if (ftotal != ftotal_new || fknown != fknown_new || fdone != fdone_new || ptotal != ptotal_new || pdone != pdone_new || text_new != text1) + if (ftotal != ftotal_new || fdone != fdone_new || fknown_bits != fknown_bits_new || ftotal_bits != ftotal_bits_new || ptotal != ptotal_new || pdone != pdone_new || text_new != text1) { ftotal = ftotal_new; - fknown = fknown_new; fdone = fdone_new; + ftotal_bits = ftotal_bits_new; + fknown_bits = fknown_bits_new; ptotal = ptotal_new; pdone = pdone_new; @@ -210,8 +216,9 @@ void progress_dialog_server::operator()() // Compute new progress in percents // Assume not all programs were found if files were not compiled (as it may contain more) - const u64 known_files = ftotal && fknown ? fknown : ftotal; - const u64 total = std::max(ptotal, 1) * std::max(ftotal, 1) / std::max(known_files, 1); + const bool use_bits = fknown_bits && ftotal_bits; + const u64 known_files = use_bits ? fknown_bits : ftotal; + const u64 total = utils::rational_mul(std::max(ptotal, 1), std::max(use_bits ? ftotal_bits : ftotal, 1), std::max(known_files, 1)); const u64 done = pdone; const u32 value = static_cast(done >= total ? 100 : done * 100 / total); @@ -224,7 +231,7 @@ void progress_dialog_server::operator()() if (ptotal) fmt::append(progr, " module %u of %u", pdone, ptotal); - if (value >= 3) + if (value) { const u64 passed = (get_system_time() - start_time); const u64 seconds_passed = passed / 1'000'000; @@ -321,8 +328,9 @@ void progress_dialog_server::operator()() // Cleanup g_progr_fdone -= fdone; - g_progr_fknown -= fknown; g_progr_pdone -= pdone; + g_progr_ftotal_bits -= ftotal_bits; + g_progr_fknown_bits -= fknown_bits; g_progr_ftotal -= ftotal; g_progr_ptotal -= ptotal; g_progr_ptotal.notify_all(); @@ -343,8 +351,9 @@ void progress_dialog_server::operator()() progress_dialog_server::~progress_dialog_server() { g_progr_ftotal.release(0); - g_progr_fknown.release(0); g_progr_fdone.release(0); + g_progr_ftotal_bits.release(0); + g_progr_fknown_bits.release(0); g_progr_ptotal.release(0); g_progr_pdone.release(0); g_progr.release(progress_dialog_string_t{}); diff --git a/rpcs3/Emu/system_progress.hpp b/rpcs3/Emu/system_progress.hpp index 976366f864..f50ba890ca 100644 --- a/rpcs3/Emu/system_progress.hpp +++ b/rpcs3/Emu/system_progress.hpp @@ -17,8 +17,9 @@ struct alignas(16) progress_dialog_string_t extern atomic_t g_progr; extern atomic_t g_progr_ftotal; -extern atomic_t g_progr_fknown; extern atomic_t g_progr_fdone; +extern atomic_t g_progr_ftotal_bits; +extern atomic_t g_progr_fknown_bits; extern atomic_t g_progr_ptotal; extern atomic_t g_progr_pdone; extern atomic_t g_system_progress_canceled; diff --git a/rpcs3/util/asm.hpp b/rpcs3/util/asm.hpp index da0be9f1f6..789f01d880 100644 --- a/rpcs3/util/asm.hpp +++ b/rpcs3/util/asm.hpp @@ -392,6 +392,23 @@ namespace utils return static_cast(value / align + (value > 0 ? T{(value % align) > (align / 2)} : 0 - T{(value % align) < (align / 2)})); } + // Multiplying by ratio, semi-resistant to overflows + template + constexpr T rational_mul(T value, std::type_identity_t numerator, std::type_identity_t denominator) + { + if constexpr (sizeof(T) <= sizeof(u64) / 2) + { + return static_cast(value * u64{numerator} / u64{denominator}); + } + + if constexpr (sizeof(T) <= sizeof(u128) / 2) + { + return static_cast(value * u128{numerator} / u128{denominator}); + } + + return static_cast(value / denominator * numerator + (value % denominator) * numerator / denominator); + } + template constexpr T add_saturate(T addend1, T addend2) {