From d449420a45a7ddde6fab8e7b2a44ef5b89538328 Mon Sep 17 00:00:00 2001 From: Eladash <18193363+elad335@users.noreply.github.com> Date: Tue, 28 Nov 2023 19:41:14 +0200 Subject: [PATCH] PPU Progress Dialog: Add "Applying PPU Code" stage --- rpcs3/Emu/Cell/PPUThread.cpp | 129 +++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 45 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 259c5fa11d..b364de5cac 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -3652,6 +3652,8 @@ extern void ppu_precompile(std::vector& dir_queue, std::vector progr(std::in_place, "Scanning PPU Executable..."); + // Make sure we only have one '/' at the end and remove duplicates. for (std::string& dir : dir_queue) { @@ -3659,6 +3661,7 @@ extern void ppu_precompile(std::vector& dir_queue, std::vector& dir_queue, std::vector fnext = 0; @@ -4081,7 +4084,7 @@ extern void ppu_initialize() auto& _main = g_fxo->get(); - scoped_progress_dialog progr = "Analyzing PPU Executable..."; + std::optional progr(std::in_place, "Analyzing PPU Executable..."); // Analyse executable if (!_main.analyse(0, _main.elf_entry, _main.seg0_code_end, _main.applied_patches, [](){ return Emu.IsStopped(); })) @@ -4092,7 +4095,7 @@ extern void ppu_initialize() // Validate analyser results (not required) _main.validate(0); - progr = "Scanning PPU Modules..."; + *progr = "Scanning PPU Modules..."; bool compile_main = false; @@ -4180,6 +4183,8 @@ extern void ppu_initialize() dir_queue.insert(std::end(dir_queue), std::begin(dirs), std::end(dirs)); } + progr.reset(); + ppu_precompile(dir_queue, &module_list); if (Emu.IsStopped()) @@ -4315,7 +4320,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size) if (!check_only) { // Initialize progress dialog - progr.emplace("Loading PPU modules..."); + progr.emplace("Loading PPU Modules..."); } // Permanently loaded compiled PPU modules (name -> data) @@ -4678,7 +4683,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size) // Create worker threads for compilation if (!workload.empty()) { - *progr = "Compiling PPU modules..."; + *progr = "Compiling PPU Modules..."; u32 thread_count = rpcs3::utils::get_max_threads(); @@ -4787,7 +4792,7 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size) if (workload.size() < link_workload.size()) { // Only show this message if this task is relevant - *progr = "Linking PPU modules..."; + *progr = "Linking PPU Modules..."; } for (const auto& [obj_name, is_compiled] : link_workload) @@ -4807,6 +4812,8 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size) } } + progr.reset(); + if (!is_being_used_in_emulation || (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped())) { return compiled_new; @@ -4819,55 +4826,87 @@ bool ppu_initialize(const ppu_module& info, bool check_only, u64 file_size) // Try to patch all single and unregistered BLRs with the same function (TODO: Maybe generalize it into PIC code detection and patching) ppu_intrp_func_t BLR_func = nullptr; - if (jit && !jit_mod.init) + const bool is_first = jit && !jit_mod.init; + + if (is_first) { jit->fin(); - - // Get and install function addresses - for (const auto& func : info.funcs) - { - if (!func.size) continue; - - const auto name = fmt::format("__0x%x", func.addr - reloc); - const auto addr = ensure(reinterpret_cast(jit->get(name))); - jit_mod.funcs.emplace_back(addr); - - if (func.size == 4 && !BLR_func && *info.get_ptr(func.addr) == ppu_instructions::BLR()) - { - BLR_func = addr; - } - - ppu_register_function_at(func.addr, 4, addr); - - if (g_cfg.core.ppu_debug) - ppu_log.trace("Installing function %s at 0x%x: %p (reloc = 0x%x)", name, func.addr, ppu_ref(func.addr), reloc); - } - - jit_mod.init = true; } - else + + usz index = 0; + usz max_count = 0; + + for (const auto& func : info.funcs) { - usz index = 0; - - // Locate existing functions - for (const auto& func : info.funcs) + if (func.size) { - if (!func.size) continue; + max_count++; + } + } - const u64 addr = reinterpret_cast(ensure(jit_mod.funcs[index++])); + usz pending_progress = umax; - if (func.size == 4 && !BLR_func && *info.get_ptr(func.addr) == ppu_instructions::BLR()) - { - BLR_func = reinterpret_cast(addr); - } + bool early_exit = false; - ppu_register_function_at(func.addr, 4, addr); - - if (g_cfg.core.ppu_debug) - ppu_log.trace("Reinstalling function at 0x%x: %p (reloc=0x%x)", func.addr, ppu_ref(func.addr), reloc); + // Get and install function addresses + for (const auto& func : info.funcs) + { + if (!func.size) + { + continue; } - index = 0; + if (cpu ? cpu->state.all_of(cpu_flag::exit) : Emu.IsStopped()) + { + // Revert partially commited changes + jit_mod.funcs.clear(); + BLR_func = nullptr; + early_exit = true; + break; + } + + const auto name = fmt::format("__0x%x", func.addr - reloc); + + // Try to locate existing function if it is not the first time + const auto addr = is_first ? ensure(reinterpret_cast(jit->get(name))) + : reinterpret_cast(ensure(jit_mod.funcs[index])); + + jit_mod.funcs.emplace_back(addr); + + if (func.size == 4 && !BLR_func && *info.get_ptr(func.addr) == ppu_instructions::BLR()) + { + BLR_func = addr; + } + + ppu_register_function_at(func.addr, 4, addr); + + if (g_cfg.core.ppu_debug) + ppu_log.trace("Installing function %s at 0x%x: %p (reloc = 0x%x)", name, func.addr, ppu_ref(func.addr), reloc); + + index++; + + if (pending_progress != umax) + { + pending_progress++; + + if (pending_progress == 1024) + { + pending_progress = 0; + g_progr_pdone++; + } + } + else if (!g_progr.load() && !g_progr_ptotal && !g_progr_ftotal) + { + g_progr_pdone += index / 1024; + g_progr_ptotal += max_count / 1024; + pending_progress = index % 1024; + progr.emplace("Applying PPU Code..."); + } + } + + if (is_first && !early_exit) + { + jit_mod.init = true; } if (BLR_func)