diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index a64f59ca88..2602afdfcd 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -2112,7 +2112,14 @@ void ppu_thread::cpu_task() #endif cmd_pop(); - ppu_initialize(), spu_cache::initialize(); + ppu_initialize(); + + if (Emu.IsStopped()) + { + return; + } + + spu_cache::initialize(); #ifdef __APPLE__ pthread_jit_write_protect_np(true); diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 3b863dd589..45e08df319 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -661,7 +661,7 @@ void spu_cache::add(const spu_program& func) m_file.write_gather(gather, 3); } -void spu_cache::initialize() +void spu_cache::initialize(bool build_existing_cache) { spu_runtime::g_interpreter = spu_runtime::g_gateway; @@ -699,13 +699,24 @@ void spu_cache::initialize() auto data_list = std::move(g_fxo->get().data); g_fxo->get().had_been_used = true; - const bool spu_precompilation_enabled = func_list.empty() && g_cfg.core.spu_cache && g_cfg.core.llvm_precompilation; + u32 total_precompile = 0; + + for (auto& sec : data_list) + { + total_precompile += sec.funcs.size(); + } + + const bool spu_precompilation_enabled = (build_existing_cache ? func_list.empty() : func_list.size() < total_precompile) && g_cfg.core.spu_cache && g_cfg.core.llvm_precompilation; if (spu_precompilation_enabled) { // What compiles in this case goes straight to disk g_fxo->get() = std::move(cache); } + else if (!build_existing_cache) + { + return; + } else { data_list.clear(); @@ -752,17 +763,14 @@ void spu_cache::initialize() thread_ctrl::wait_on(g_progr_ptotal, v); } - u32 add_count = ::size32(func_list); + const u32 add_count = ::size32(func_list) + total_precompile; - for (auto& sec : data_list) + if (add_count) { - add_count += sec.funcs.size(); + g_progr_ptotal += add_count; + progr.emplace("Building SPU cache..."); } - g_progr_ptotal += add_count; - - progr.emplace("Building SPU cache..."); - worker_count = rpcs3::utils::get_max_threads(); } diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 551e73a13a..5dd68184b1 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -34,7 +34,7 @@ public: void add(const struct spu_program& func); - static void initialize(); + static void initialize(bool build_existing_cache = true); }; struct spu_program diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e85cc6a6cf..cba2644511 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -15,6 +15,7 @@ #include "Emu/Cell/PPUDisAsm.h" #include "Emu/Cell/PPUAnalyser.h" #include "Emu/Cell/SPUThread.h" +#include "Emu/Cell/SPURecompiler.h" #include "Emu/RSX/RSXThread.h" #include "Emu/Cell/lv2/sys_process.h" #include "Emu/Cell/lv2/sys_sync.h" @@ -1385,6 +1386,10 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, // Force LLVM recompiler g_cfg.core.ppu_decoder.from_default(); + // Force SPU cache and precompilation + g_cfg.core.llvm_precompilation.set(true); + g_cfg.core.spu_cache.set(true); + // Disable incompatible settings fixup_ppu_settings(); @@ -1490,6 +1495,13 @@ game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, ppu_precompile(dir_queue, nullptr); + if (Emu.IsStopped()) + { + return; + } + + spu_cache::initialize(false); + // Exit "process" CallFromMainThread([this] { diff --git a/rpcs3/rpcs3qt/game_list_frame.cpp b/rpcs3/rpcs3qt/game_list_frame.cpp index b8e66edadb..28181afba4 100644 --- a/rpcs3/rpcs3qt/game_list_frame.cpp +++ b/rpcs3/rpcs3qt/game_list_frame.cpp @@ -1101,7 +1101,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos) ? tr("&Change Custom Gamepad Configuration") : tr("&Create Custom Gamepad Configuration")); QAction* configure_patches = menu.addAction(tr("&Manage Game Patches")); - QAction* create_ppu_cache = menu.addAction(tr("&Create PPU Cache")); + QAction* create_ppu_cache = menu.addAction(tr("&Create PPU/SPU Cache")); menu.addSeparator(); @@ -1440,7 +1440,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos) { if (m_gui_settings->GetBootConfirmation(this)) { - CreatePPUCache(gameinfo); + CreateCPUCaches(gameinfo); } }); connect(remove_game, &QAction::triggered, this, [this, current_game, gameinfo, cache_base_dir, name] @@ -1612,23 +1612,24 @@ void game_list_frame::ShowContextMenu(const QPoint &pos) menu.exec(global_pos); } -bool game_list_frame::CreatePPUCache(const std::string& path, const std::string& serial) +bool game_list_frame::CreateCPUCaches(const std::string& path, const std::string& serial) { Emu.GracefulShutdown(false); Emu.SetForceBoot(true); if (const auto error = Emu.BootGame(fs::is_file(path) ? fs::get_parent_dir(path) : path, serial, true); error != game_boot_result::no_errors) { - game_list_log.error("Could not create PPU Cache for %s, error: %s", path, error); + game_list_log.error("Could not create PPU and SPU caches for %s, error: %s", path, error); return false; } - game_list_log.warning("Creating PPU Cache for %s", path); + + game_list_log.warning("Creating PPU/SPU Caches for %s", path); return true; } -bool game_list_frame::CreatePPUCache(const game_info& game) +bool game_list_frame::CreateCPUCaches(const game_info& game) { - return game && CreatePPUCache(game->info.path, game->info.serial); + return game && CreateCPUCaches(game->info.path, game->info.serial); } bool game_list_frame::RemoveCustomConfiguration(const std::string& title_id, const game_info& game, bool is_interactive) @@ -1907,7 +1908,7 @@ void game_list_frame::RemoveHDD1Cache(const std::string& base_dir, const std::st game_list_log.fatal("Only %d/%d HDD1 cache directories could be removed in %s (%s)", dirs_removed, dirs_total, base_dir, title_id); } -void game_list_frame::BatchCreatePPUCaches() +void game_list_frame::BatchCreateCPUCaches() { const std::string vsh_path = g_cfg_vfs.get_dev_flash() + "vsh/module/"; const bool vsh_exists = fs::is_file(vsh_path + "vsh.self"); @@ -1952,7 +1953,7 @@ void game_list_frame::BatchCreatePPUCaches() pdlg->setLabelText(tr("%0\nProgress: %1/%2. Compiling caches for VSH...", "Second line after main label").arg(main_label).arg(created).arg(total)); QApplication::processEvents(); - if (CreatePPUCache(vsh_path) && wait_until_compiled()) + if (CreateCPUCaches(vsh_path) && wait_until_compiled()) { pdlg->SetValue(++created); } @@ -1968,7 +1969,7 @@ void game_list_frame::BatchCreatePPUCaches() pdlg->setLabelText(tr("%0\nProgress: %1/%2. Compiling caches for %3...", "Second line after main label").arg(main_label).arg(created).arg(total).arg(qstr(game->info.serial))); QApplication::processEvents(); - if (CreatePPUCache(game) && wait_until_compiled()) + if (CreateCPUCaches(game) && wait_until_compiled()) { pdlg->SetValue(++created); } diff --git a/rpcs3/rpcs3qt/game_list_frame.h b/rpcs3/rpcs3qt/game_list_frame.h index 582d407a52..ecc7e106c7 100644 --- a/rpcs3/rpcs3qt/game_list_frame.h +++ b/rpcs3/rpcs3qt/game_list_frame.h @@ -63,7 +63,7 @@ public: bool IsEntryVisible(const game_info& game, bool search_fallback = false) const; public Q_SLOTS: - void BatchCreatePPUCaches(); + void BatchCreateCPUCaches(); void BatchRemovePPUCaches(); void BatchRemoveSPUCaches(); void BatchRemoveCustomConfigurations(); @@ -108,8 +108,8 @@ private: bool RemovePPUCache(const std::string& base_dir, bool is_interactive = false); bool RemoveSPUCache(const std::string& base_dir, bool is_interactive = false); void RemoveHDD1Cache(const std::string& base_dir, const std::string& title_id, bool is_interactive = false); - static bool CreatePPUCache(const std::string& path, const std::string& serial = {}); - static bool CreatePPUCache(const game_info& game); + static bool CreateCPUCaches(const std::string& path, const std::string& serial = {}); + static bool CreateCPUCaches(const game_info& game); static std::string GetCacheDirBySerial(const std::string& serial); static std::string GetDataDirBySerial(const std::string& serial); diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp index a99fec89f8..2313e9f9b6 100644 --- a/rpcs3/rpcs3qt/main_window.cpp +++ b/rpcs3/rpcs3qt/main_window.cpp @@ -2506,7 +2506,7 @@ void main_window::CreateConnects() }); connect(ui->exitAct, &QAction::triggered, this, &QWidget::close); - connect(ui->batchCreatePPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchCreatePPUCaches); + connect(ui->batchCreateCPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchCreateCPUCaches); connect(ui->batchRemovePPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemovePPUCaches); connect(ui->batchRemoveSPUCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveSPUCaches); connect(ui->batchRemoveShaderCachesAct, &QAction::triggered, m_game_list_frame, &game_list_frame::BatchRemoveShaderCaches); diff --git a/rpcs3/rpcs3qt/main_window.ui b/rpcs3/rpcs3qt/main_window.ui index 9c93bf5c79..35422d94fc 100644 --- a/rpcs3/rpcs3qt/main_window.ui +++ b/rpcs3/rpcs3qt/main_window.ui @@ -182,7 +182,7 @@ All Titles - + @@ -1094,9 +1094,9 @@ Show Title Bars - + - Create PPU Caches + Create PPU/SPU Caches