mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-15 19:28:43 +12:00
Rewrite LLVM compilation progress dialog
Use a single dialog
This commit is contained in:
parent
a2253e840f
commit
b0ee369135
2 changed files with 169 additions and 89 deletions
|
@ -48,7 +48,6 @@
|
||||||
#include "define_new_memleakdetect.h"
|
#include "define_new_memleakdetect.h"
|
||||||
|
|
||||||
#include "PPUTranslator.h"
|
#include "PPUTranslator.h"
|
||||||
#include "Modules/cellMsgDialog.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -67,7 +66,9 @@ const bool s_use_ssse3 =
|
||||||
|
|
||||||
extern u64 get_system_time();
|
extern u64 get_system_time();
|
||||||
|
|
||||||
|
extern atomic_t<const char*> g_progr;
|
||||||
|
extern atomic_t<u64> g_progr_ptotal;
|
||||||
|
extern atomic_t<u64> g_progr_pdone;
|
||||||
|
|
||||||
enum class join_status : u32
|
enum class join_status : u32
|
||||||
{
|
{
|
||||||
|
@ -164,7 +165,7 @@ extern const ppu_decoder<ppu_interpreter_fast> g_ppu_interpreter_fast([](auto& t
|
||||||
|
|
||||||
extern void ppu_initialize();
|
extern void ppu_initialize();
|
||||||
extern void ppu_initialize(const ppu_module& info);
|
extern void ppu_initialize(const ppu_module& info);
|
||||||
static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name, u32 fragment_index, const std::shared_ptr<atomic_t<u32>>&);
|
static void ppu_initialize2(class jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name);
|
||||||
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code);
|
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code);
|
||||||
|
|
||||||
// Get pointer to executable cache
|
// Get pointer to executable cache
|
||||||
|
@ -1337,6 +1338,9 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LLVM_AVAILABLE
|
#ifdef LLVM_AVAILABLE
|
||||||
|
// Initialize progress dialog
|
||||||
|
g_progr = "Compiling PPU modules...";
|
||||||
|
|
||||||
// Compiled PPU module info
|
// Compiled PPU module info
|
||||||
struct jit_module
|
struct jit_module
|
||||||
{
|
{
|
||||||
|
@ -1380,10 +1384,6 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
// Difference between function name and current location
|
// Difference between function name and current location
|
||||||
const u32 reloc = info.name.empty() ? 0 : info.segs.at(0).addr;
|
const u32 reloc = info.name.empty() ? 0 : info.segs.at(0).addr;
|
||||||
|
|
||||||
std::shared_ptr<atomic_t<u32>> fragment_sync = std::make_shared<atomic_t<u32>>(0);
|
|
||||||
|
|
||||||
u32 fragment_count{0};
|
|
||||||
|
|
||||||
while (jit_mod.vars.empty() && fpos < info.funcs.size())
|
while (jit_mod.vars.empty() && fpos < info.funcs.size())
|
||||||
{
|
{
|
||||||
// Initialize compiler instance
|
// Initialize compiler instance
|
||||||
|
@ -1546,8 +1546,11 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update progress dialog
|
||||||
|
g_progr_ptotal++;
|
||||||
|
|
||||||
// Create worker thread for compilation
|
// Create worker thread for compilation
|
||||||
jthreads.emplace_back([&jit, obj_name = obj_name, part = std::move(part), &cache_path, fragment_sync, jcores, findex = ::size32(jthreads)]()
|
jthreads.emplace_back([&jit, obj_name = obj_name, part = std::move(part), &cache_path, jcores]()
|
||||||
{
|
{
|
||||||
// Set low priority
|
// Set low priority
|
||||||
thread_ctrl::set_native_priority(-1);
|
thread_ctrl::set_native_priority(-1);
|
||||||
|
@ -1556,14 +1559,14 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
{
|
{
|
||||||
semaphore_lock jlock(jcores->sem);
|
semaphore_lock jlock(jcores->sem);
|
||||||
|
|
||||||
if (Emu.IsStopped())
|
if (!Emu.IsStopped())
|
||||||
{
|
{
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use another JIT instance
|
// Use another JIT instance
|
||||||
jit_compiler jit2({}, g_cfg.core.llvm_cpu);
|
jit_compiler jit2({}, g_cfg.core.llvm_cpu);
|
||||||
ppu_initialize2(jit2, part, cache_path, obj_name, findex, fragment_sync);
|
ppu_initialize2(jit2, part, cache_path, obj_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_progr_pdone++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Emu.IsStopped() || !jit || !fs::is_file(cache_path + obj_name))
|
if (Emu.IsStopped() || !jit || !fs::is_file(cache_path + obj_name))
|
||||||
|
@ -1577,9 +1580,6 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize fragment count sync var
|
|
||||||
fragment_sync->exchange(::size32(jthreads));
|
|
||||||
|
|
||||||
// Join worker threads
|
// Join worker threads
|
||||||
for (auto& thread : jthreads)
|
for (auto& thread : jthreads)
|
||||||
{
|
{
|
||||||
|
@ -1663,7 +1663,7 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name, u32 fragment_index, const std::shared_ptr<atomic_t<u32>>& fragment_sync)
|
static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, const std::string& cache_path, const std::string& obj_name)
|
||||||
{
|
{
|
||||||
#ifdef LLVM_AVAILABLE
|
#ifdef LLVM_AVAILABLE
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
@ -1691,8 +1691,6 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MsgDialogBase> dlg;
|
|
||||||
|
|
||||||
{
|
{
|
||||||
legacy::FunctionPassManager pm(module.get());
|
legacy::FunctionPassManager pm(module.get());
|
||||||
|
|
||||||
|
@ -1716,25 +1714,6 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||||
//pm.add(createCFGSimplificationPass());
|
//pm.add(createCFGSimplificationPass());
|
||||||
//pm.add(createLintPass()); // Check
|
//pm.add(createLintPass()); // Check
|
||||||
|
|
||||||
// Initialize message dialog
|
|
||||||
dlg = Emu.GetCallbacks().get_msg_dialog();
|
|
||||||
dlg->type.se_normal = true;
|
|
||||||
dlg->type.bg_invisible = true;
|
|
||||||
dlg->type.progress_bar_count = 1;
|
|
||||||
dlg->on_close = [](s32 status)
|
|
||||||
{
|
|
||||||
Emu.CallAfter([]()
|
|
||||||
{
|
|
||||||
// Abort everything
|
|
||||||
Emu.Stop();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
Emu.CallAfter([=]()
|
|
||||||
{
|
|
||||||
dlg->Create("Compiling PPU module:\n" + obj_name + "\nPlease wait...");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Translate functions
|
// Translate functions
|
||||||
for (size_t fi = 0, fmax = module_part.funcs.size(); fi < fmax; fi++)
|
for (size_t fi = 0, fmax = module_part.funcs.size(); fi < fmax; fi++)
|
||||||
{
|
{
|
||||||
|
@ -1746,18 +1725,6 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||||
|
|
||||||
if (module_part.funcs[fi].size)
|
if (module_part.funcs[fi].size)
|
||||||
{
|
{
|
||||||
// Update dialog
|
|
||||||
Emu.CallAfter([=, max = module_part.funcs.size()]()
|
|
||||||
{
|
|
||||||
dlg->ProgressBarSetMsg(0, fmt::format("Compiling %u of %u", fi + 1, fmax));
|
|
||||||
|
|
||||||
if (fi * 100 / fmax != (fi + 1) * 100 / fmax)
|
|
||||||
dlg->ProgressBarInc(0, 1);
|
|
||||||
|
|
||||||
if (u32 fragment_count = fragment_sync->load())
|
|
||||||
dlg->SetMsg(fmt::format("Compiling PPU module (%u of %u):\n%s\nPlease wait...", fragment_index + 1, fragment_count, obj_name));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Translate
|
// Translate
|
||||||
if (const auto func = translator.Translate(module_part.funcs[fi]))
|
if (const auto func = translator.Translate(module_part.funcs[fi]))
|
||||||
{
|
{
|
||||||
|
@ -1780,16 +1747,6 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
||||||
//mpm.add(createDeadInstEliminationPass());
|
//mpm.add(createDeadInstEliminationPass());
|
||||||
//mpm.run(*module);
|
//mpm.run(*module);
|
||||||
|
|
||||||
// Update dialog
|
|
||||||
Emu.CallAfter([=]()
|
|
||||||
{
|
|
||||||
dlg->ProgressBarSetMsg(0, "Generating code, this may take a long time...");
|
|
||||||
dlg->ProgressBarInc(0, 100);
|
|
||||||
|
|
||||||
if (u32 fragment_count = fragment_sync->load())
|
|
||||||
dlg->SetMsg(fmt::format("Compiling PPU module (%u of %u):\n%s\nPlease wait...", fragment_index + 1, fragment_count, obj_name));
|
|
||||||
});
|
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
raw_string_ostream out(result);
|
raw_string_ostream out(result);
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,13 @@ extern void network_thread_init();
|
||||||
fs::file g_tty;
|
fs::file g_tty;
|
||||||
atomic_t<s64> g_tty_size{0};
|
atomic_t<s64> g_tty_size{0};
|
||||||
|
|
||||||
|
// Progress display server synchronization variables
|
||||||
|
atomic_t<const char*> g_progr{nullptr};
|
||||||
|
atomic_t<u64> g_progr_ftotal{0};
|
||||||
|
atomic_t<u64> g_progr_fdone{0};
|
||||||
|
atomic_t<u64> g_progr_ptotal{0};
|
||||||
|
atomic_t<u64> g_progr_pdone{0};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void fmt_class_string<mouse_handler>::format(std::string& out, u64 arg)
|
void fmt_class_string<mouse_handler>::format(std::string& out, u64 arg)
|
||||||
{
|
{
|
||||||
|
@ -260,6 +267,100 @@ void Emulator::Init()
|
||||||
#endif
|
#endif
|
||||||
// Initialize patch engine
|
// Initialize patch engine
|
||||||
fxm::make_always<patch_engine>()->append(fs::get_config_dir() + "/patch.yml");
|
fxm::make_always<patch_engine>()->append(fs::get_config_dir() + "/patch.yml");
|
||||||
|
|
||||||
|
// Initialize progress dialog server (TODO)
|
||||||
|
if (g_progr.exchange("") == nullptr)
|
||||||
|
{
|
||||||
|
std::thread server([]()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::shared_ptr<MsgDialogBase> dlg;
|
||||||
|
|
||||||
|
// Wait for the start condition
|
||||||
|
while (!g_progr_ftotal && !g_progr_ptotal)
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(5ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize message dialog
|
||||||
|
dlg = Emu.GetCallbacks().get_msg_dialog();
|
||||||
|
dlg->type.se_normal = true;
|
||||||
|
dlg->type.bg_invisible = true;
|
||||||
|
dlg->type.progress_bar_count = 1;
|
||||||
|
dlg->on_close = [](s32 status)
|
||||||
|
{
|
||||||
|
Emu.CallAfter([]()
|
||||||
|
{
|
||||||
|
// Abort everything
|
||||||
|
Emu.Stop();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Emu.CallAfter([=]()
|
||||||
|
{
|
||||||
|
dlg->Create(+g_progr);
|
||||||
|
});
|
||||||
|
|
||||||
|
u64 ftotal = 0;
|
||||||
|
u64 fdone = 0;
|
||||||
|
u64 ptotal = 0;
|
||||||
|
u64 pdone = 0;
|
||||||
|
u32 value = 0;
|
||||||
|
|
||||||
|
// Update progress
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (ftotal != g_progr_ftotal || fdone != g_progr_fdone || ptotal != g_progr_ptotal || pdone != g_progr_pdone)
|
||||||
|
{
|
||||||
|
ftotal = g_progr_ftotal;
|
||||||
|
fdone = g_progr_fdone;
|
||||||
|
ptotal = g_progr_ptotal;
|
||||||
|
pdone = g_progr_pdone;
|
||||||
|
|
||||||
|
// Compute new progress in percents
|
||||||
|
const u32 new_value = ((ptotal ? pdone * 1. / ptotal : 0.) + fdone) * 100. / (ftotal ? ftotal : 1);
|
||||||
|
|
||||||
|
// Compute the difference
|
||||||
|
const u32 delta = new_value > value ? new_value - value : 0;
|
||||||
|
|
||||||
|
value += delta;
|
||||||
|
|
||||||
|
// Changes detected, send update
|
||||||
|
Emu.CallAfter([=]()
|
||||||
|
{
|
||||||
|
std::string progr = "Progress:";
|
||||||
|
|
||||||
|
if (ftotal)
|
||||||
|
fmt::append(progr, " file %u of %u%s", fdone, ftotal, ptotal ? "," : "");
|
||||||
|
if (ptotal)
|
||||||
|
fmt::append(progr, " module %u of %u", pdone, ptotal);
|
||||||
|
|
||||||
|
dlg->SetMsg(+g_progr);
|
||||||
|
dlg->ProgressBarSetMsg(0, progr);
|
||||||
|
dlg->ProgressBarInc(0, delta);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fdone >= ftotal && pdone >= ptotal)
|
||||||
|
{
|
||||||
|
// Close dialog
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(10ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
g_progr_ftotal -= fdone;
|
||||||
|
g_progr_fdone -= fdone;
|
||||||
|
g_progr_ptotal -= pdone;
|
||||||
|
g_progr_pdone -= pdone;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Emulator::BootRsxCapture(const std::string& path)
|
bool Emulator::BootRsxCapture(const std::string& path)
|
||||||
|
@ -565,9 +666,15 @@ void Emulator::Load(bool add_only)
|
||||||
std::vector<std::string> dir_queue;
|
std::vector<std::string> dir_queue;
|
||||||
dir_queue.emplace_back(m_path + '/');
|
dir_queue.emplace_back(m_path + '/');
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, u64>> file_queue;
|
||||||
|
file_queue.reserve(2000);
|
||||||
|
|
||||||
std::queue<std::shared_ptr<thread_ctrl>> thread_queue;
|
std::queue<std::shared_ptr<thread_ctrl>> thread_queue;
|
||||||
const uint max_threads = std::thread::hardware_concurrency();
|
const uint max_threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
|
// Initialize progress dialog
|
||||||
|
g_progr = "Scanning directories for SPRX libraries...";
|
||||||
|
|
||||||
// Find all .sprx files recursively (TODO: process .mself files)
|
// Find all .sprx files recursively (TODO: process .mself files)
|
||||||
for (std::size_t i = 0; i < dir_queue.size(); i++)
|
for (std::size_t i = 0; i < dir_queue.size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -604,12 +711,28 @@ void Emulator::Load(bool add_only)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get full path
|
// Get full path
|
||||||
const std::string path = dir_queue[i] + entry.name;
|
file_queue.emplace_back(dir_queue[i] + entry.name, 0);
|
||||||
|
g_progr_ftotal++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < file_queue.size(); i++)
|
||||||
|
{
|
||||||
|
const auto& path = file_queue[i].first;
|
||||||
|
|
||||||
LOG_NOTICE(LOADER, "Trying to load SPRX: %s", path);
|
LOG_NOTICE(LOADER, "Trying to load SPRX: %s", path);
|
||||||
|
|
||||||
|
// Load MSELF or SPRX
|
||||||
|
fs::file src{path};
|
||||||
|
|
||||||
|
if (file_queue[i].second == 0)
|
||||||
|
{
|
||||||
// Some files may fail to decrypt due to the lack of klic
|
// Some files may fail to decrypt due to the lack of klic
|
||||||
const ppu_prx_object obj = decrypt_self(fs::file(path));
|
src = decrypt_self(std::move(src));
|
||||||
|
}
|
||||||
|
|
||||||
|
const ppu_prx_object obj = src;
|
||||||
|
|
||||||
if (obj == elf_error::ok)
|
if (obj == elf_error::ok)
|
||||||
{
|
{
|
||||||
|
@ -626,15 +749,15 @@ void Emulator::Load(bool add_only)
|
||||||
{
|
{
|
||||||
ppu_initialize(*_prx);
|
ppu_initialize(*_prx);
|
||||||
ppu_unload_prx(*_prx);
|
ppu_unload_prx(*_prx);
|
||||||
|
g_progr_fdone++;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_ERROR(LOADER, "Failed to load SPRX '%s' (%s)", path, obj.get_error());
|
LOG_ERROR(LOADER, "Failed to load SPRX '%s' (%s)", path, obj.get_error());
|
||||||
}
|
g_progr_fdone++;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Join every thread and print exceptions
|
// Join every thread and print exceptions
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue