mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-15 04:21:01 +00:00
PPU/Progress Dialog: Improve remaining time calculation
This commit is contained in:
parent
0bb5974ab6
commit
44c08c3a73
@ -174,7 +174,7 @@ bool serialize<ppu_thread::cr_bits>(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<std::shared_ptr<lv2_overlay>, 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<std::string>& dir_queue, std::vector<ppu_
|
||||
|
||||
const std::string firmware_sprx_path = vfs::get("/dev_flash/sys/external/");
|
||||
|
||||
std::vector<std::pair<std::string, u64>> 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_info> file_queue;
|
||||
file_queue.reserve(2000);
|
||||
|
||||
// Find all .sprx files recursively
|
||||
@ -3629,6 +3645,12 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
continue;
|
||||
}
|
||||
|
||||
// SCE header size
|
||||
if (entry.size <= 0x20)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string upper = fmt::to_upper(entry.name);
|
||||
|
||||
// Skip already loaded modules or HLEd ones
|
||||
@ -3676,7 +3698,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
}
|
||||
|
||||
// Get full path
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, 0);
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, 0, entry.size);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3684,7 +3706,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
if ((upper.ends_with(".ELF") || upper.ends_with(".SELF")) && Emu.GetBoot() != dir_queue[i] + entry.name)
|
||||
{
|
||||
// Get full path
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, 0);
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, 0, entry.size);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -3710,14 +3732,14 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
if (upper.ends_with(".SPRX"))
|
||||
{
|
||||
// .sprx inside .mself found
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, rec.off);
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, rec.off, rec.size);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (upper.ends_with(".SELF"))
|
||||
{
|
||||
// .self inside .mself found
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, rec.off);
|
||||
file_queue.emplace_back(dir_queue[i] + entry.name, rec.off, rec.size);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -3734,11 +3756,21 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
}
|
||||
|
||||
g_progr_ftotal += file_queue.size();
|
||||
|
||||
u64 total_files_size = 0;
|
||||
|
||||
for (const file_info& info : file_queue)
|
||||
{
|
||||
total_files_size += info.file_size;
|
||||
}
|
||||
|
||||
g_progr_ftotal_bits += total_files_size;
|
||||
|
||||
scoped_progress_dialog progr = "Compiling PPU modules...";
|
||||
|
||||
atomic_t<usz> fnext = 0;
|
||||
|
||||
lf_queue<std::string> possible_exec_file_paths;
|
||||
lf_queue<file_info> possible_exec_file_paths;
|
||||
shared_mutex ovl_mtx;
|
||||
|
||||
named_thread_group workers("SPRX Worker ", std::min<u32>(utils::get_thread_count(), ::size32(file_queue)), [&]
|
||||
@ -3756,7 +3788,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
continue;
|
||||
}
|
||||
|
||||
auto& [path, offset] = file_queue[func_i];
|
||||
auto& [path, offset, file_size] = file_queue[func_i];
|
||||
|
||||
ppu_log.notice("Trying to load: %s", path);
|
||||
|
||||
@ -3794,7 +3826,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
if (auto prx = ppu_load_prx(obj, true, path, offset))
|
||||
{
|
||||
obj.clear(), src.close(); // Clear decrypted file and elf object memory
|
||||
ppu_initialize(*prx);
|
||||
ppu_initialize(*prx, false, file_size);
|
||||
ppu_finalize(*prx);
|
||||
continue;
|
||||
}
|
||||
@ -3828,7 +3860,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
// Does not really require this lock, this is done for performance reasons.
|
||||
// Seems like too many created threads is hard for Windows to manage efficiently with many CPU threads.
|
||||
std::lock_guard lock(ovl_mtx);
|
||||
ppu_initialize(*ovlm);
|
||||
ppu_initialize(*ovlm, false, file_size);
|
||||
}
|
||||
|
||||
ppu_finalize(*ovlm);
|
||||
@ -3842,7 +3874,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
}
|
||||
|
||||
ppu_log.notice("Failed to precompile '%s' (prx: %s, ovl: %s): Attempting tratment as executable file", path, prx_err, ovl_err);
|
||||
possible_exec_file_paths.push(path);
|
||||
possible_exec_file_paths.push(path, offset, file_size);
|
||||
inc_fdone = 0;
|
||||
}
|
||||
});
|
||||
@ -3874,7 +3906,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string path = *slice;
|
||||
const auto& [path, _, file_size] = *slice;
|
||||
|
||||
ppu_log.notice("Trying to load as executable: %s", path);
|
||||
|
||||
@ -3930,7 +3962,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
|
||||
|
||||
_main.name = ' '; // Make ppu_finalize work
|
||||
Emu.ConfigurePPUCache(!Emu.IsPathInsideDir(_main.path, g_cfg_vfs.get_dev_flash()));
|
||||
ppu_initialize(_main);
|
||||
ppu_initialize(_main, false, file_size);
|
||||
spu_cache::initialize(false);
|
||||
ppu_finalize(_main);
|
||||
_main = {};
|
||||
@ -4093,7 +4125,7 @@ extern void ppu_initialize()
|
||||
}
|
||||
}
|
||||
|
||||
bool ppu_initialize(const ppu_module& info, bool check_only)
|
||||
bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size)
|
||||
{
|
||||
if (g_cfg.core.ppu_decoder != ppu_decoder_type::llvm)
|
||||
{
|
||||
@ -4569,9 +4601,9 @@ bool ppu_initialize(const ppu_module& info, bool check_only)
|
||||
g_progr_ptotal += total_compile;
|
||||
}
|
||||
|
||||
if (g_progr_ftotal)
|
||||
if (g_progr_ftotal_bits && file_size)
|
||||
{
|
||||
g_progr_fknown++;
|
||||
g_progr_fknown_bits += file_size;
|
||||
}
|
||||
|
||||
if (!workload.empty())
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
extern std::pair<std::shared_ptr<lv2_overlay>, 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);
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
extern std::shared_ptr<lv2_prx> 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<bool>& loaded_flags);
|
||||
|
||||
|
@ -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<std::string>& dir_queue, std::vector<ppu_module*>* 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<lv2_prx> ppu_load_prx(const ppu_prx_object&, bool virtual_load, const std::string&, s64 = 0, utils::serial* = nullptr);
|
||||
|
@ -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<progress_dialog_string_t> g_progr{};
|
||||
atomic_t<u32> g_progr_ftotal{0};
|
||||
atomic_t<u32> g_progr_fknown{0};
|
||||
atomic_t<u32> g_progr_fdone{0};
|
||||
atomic_t<u64> g_progr_ftotal_bits{0};
|
||||
atomic_t<u64> g_progr_fknown_bits{0};
|
||||
atomic_t<u32> g_progr_ptotal{0};
|
||||
atomic_t<u32> 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();
|
||||
@ -156,7 +160,8 @@ void progress_dialog_server::operator()()
|
||||
|
||||
u32 ftotal = 0;
|
||||
u32 fdone = 0;
|
||||
u32 fknown = 0;
|
||||
u32 fknown_bits = 0;
|
||||
u32 ftotal_bits = 0;
|
||||
u32 ptotal = 0;
|
||||
u32 pdone = 0;
|
||||
const char* text1 = nullptr;
|
||||
@ -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<u64>(ptotal, 1) * std::max<u64>(ftotal, 1) / std::max<u64>(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<u64>(std::max<u64>(ptotal, 1), std::max<u64>(use_bits ? ftotal_bits : ftotal, 1), std::max<u64>(known_files, 1));
|
||||
const u64 done = pdone;
|
||||
const u32 value = static_cast<u32>(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{});
|
||||
|
@ -17,8 +17,9 @@ struct alignas(16) progress_dialog_string_t
|
||||
|
||||
extern atomic_t<progress_dialog_string_t> g_progr;
|
||||
extern atomic_t<u32> g_progr_ftotal;
|
||||
extern atomic_t<u32> g_progr_fknown;
|
||||
extern atomic_t<u32> g_progr_fdone;
|
||||
extern atomic_t<u64> g_progr_ftotal_bits;
|
||||
extern atomic_t<u64> g_progr_fknown_bits;
|
||||
extern atomic_t<u32> g_progr_ptotal;
|
||||
extern atomic_t<u32> g_progr_pdone;
|
||||
extern atomic_t<bool> g_system_progress_canceled;
|
||||
|
@ -392,6 +392,23 @@ namespace utils
|
||||
return static_cast<T>(value / align + (value > 0 ? T{(value % align) > (align / 2)} : 0 - T{(value % align) < (align / 2)}));
|
||||
}
|
||||
|
||||
// Multiplying by ratio, semi-resistant to overflows
|
||||
template <UnsignedInt T>
|
||||
constexpr T rational_mul(T value, std::type_identity_t<T> numerator, std::type_identity_t<T> denominator)
|
||||
{
|
||||
if constexpr (sizeof(T) <= sizeof(u64) / 2)
|
||||
{
|
||||
return static_cast<T>(value * u64{numerator} / u64{denominator});
|
||||
}
|
||||
|
||||
if constexpr (sizeof(T) <= sizeof(u128) / 2)
|
||||
{
|
||||
return static_cast<T>(value * u128{numerator} / u128{denominator});
|
||||
}
|
||||
|
||||
return static_cast<T>(value / denominator * numerator + (value % denominator) * numerator / denominator);
|
||||
}
|
||||
|
||||
template <UnsignedInt T>
|
||||
constexpr T add_saturate(T addend1, T addend2)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user