|
|
@ -46,30 +46,28 @@ |
|
|
|
|
|
|
|
|
static Core::Frontend::WindowSystemType GetWindowSystemType(); |
|
|
static Core::Frontend::WindowSystemType GetWindowSystemType(); |
|
|
|
|
|
|
|
|
EmuThread::EmuThread(Core::System& system_) : system{system_} {} |
|
|
|
|
|
|
|
|
EmuThread::EmuThread(Core::System& system) : m_system{system} {} |
|
|
|
|
|
|
|
|
EmuThread::~EmuThread() = default; |
|
|
EmuThread::~EmuThread() = default; |
|
|
|
|
|
|
|
|
void EmuThread::run() { |
|
|
void EmuThread::run() { |
|
|
std::string name = "EmuControlThread"; |
|
|
|
|
|
MicroProfileOnThreadCreate(name.c_str()); |
|
|
|
|
|
Common::SetCurrentThreadName(name.c_str()); |
|
|
|
|
|
|
|
|
const char* name = "EmuControlThread"; |
|
|
|
|
|
MicroProfileOnThreadCreate(name); |
|
|
|
|
|
Common::SetCurrentThreadName(name); |
|
|
|
|
|
|
|
|
auto& gpu = system.GPU(); |
|
|
|
|
|
auto stop_token = stop_source.get_token(); |
|
|
|
|
|
bool debugger_should_start = system.DebuggerEnabled(); |
|
|
|
|
|
|
|
|
auto& gpu = m_system.GPU(); |
|
|
|
|
|
auto stop_token = m_stop_source.get_token(); |
|
|
|
|
|
|
|
|
system.RegisterHostThread(); |
|
|
|
|
|
|
|
|
m_system.RegisterHostThread(); |
|
|
|
|
|
|
|
|
// Main process has been loaded. Make the context current to this thread and begin GPU and CPU
|
|
|
// Main process has been loaded. Make the context current to this thread and begin GPU and CPU
|
|
|
// execution.
|
|
|
// execution.
|
|
|
gpu.ObtainContext(); |
|
|
gpu.ObtainContext(); |
|
|
|
|
|
|
|
|
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); |
|
|
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); |
|
|
|
|
|
|
|
|
if (Settings::values.use_disk_shader_cache.GetValue()) { |
|
|
if (Settings::values.use_disk_shader_cache.GetValue()) { |
|
|
system.Renderer().ReadRasterizer()->LoadDiskResources( |
|
|
|
|
|
system.GetCurrentProcessProgramID(), stop_token, |
|
|
|
|
|
|
|
|
m_system.Renderer().ReadRasterizer()->LoadDiskResources( |
|
|
|
|
|
m_system.GetCurrentProcessProgramID(), stop_token, |
|
|
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { |
|
|
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { |
|
|
emit LoadProgress(stage, value, total); |
|
|
emit LoadProgress(stage, value, total); |
|
|
}); |
|
|
}); |
|
|
@ -79,57 +77,35 @@ void EmuThread::run() { |
|
|
gpu.ReleaseContext(); |
|
|
gpu.ReleaseContext(); |
|
|
gpu.Start(); |
|
|
gpu.Start(); |
|
|
|
|
|
|
|
|
system.GetCpuManager().OnGpuReady(); |
|
|
|
|
|
|
|
|
m_system.GetCpuManager().OnGpuReady(); |
|
|
|
|
|
m_system.RegisterExitCallback([this] { m_stop_source.request_stop(); }); |
|
|
|
|
|
|
|
|
system.RegisterExitCallback([this]() { |
|
|
|
|
|
stop_source.request_stop(); |
|
|
|
|
|
SetRunning(false); |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
if (m_system.DebuggerEnabled()) { |
|
|
|
|
|
m_system.InitializeDebugger(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Holds whether the cpu was running during the last iteration,
|
|
|
|
|
|
// so that the DebugModeLeft signal can be emitted before the
|
|
|
|
|
|
// next execution step
|
|
|
|
|
|
bool was_active = false; |
|
|
|
|
|
while (!stop_token.stop_requested()) { |
|
|
while (!stop_token.stop_requested()) { |
|
|
if (running) { |
|
|
|
|
|
if (was_active) { |
|
|
|
|
|
emit DebugModeLeft(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
std::unique_lock lk{m_should_run_mutex}; |
|
|
|
|
|
if (m_should_run) { |
|
|
|
|
|
m_system.Run(); |
|
|
|
|
|
m_is_running.store(true); |
|
|
|
|
|
m_is_running.notify_all(); |
|
|
|
|
|
|
|
|
running_guard = true; |
|
|
|
|
|
Core::SystemResultStatus result = system.Run(); |
|
|
|
|
|
if (result != Core::SystemResultStatus::Success) { |
|
|
|
|
|
running_guard = false; |
|
|
|
|
|
this->SetRunning(false); |
|
|
|
|
|
emit ErrorThrown(result, system.GetStatusDetails()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (debugger_should_start) { |
|
|
|
|
|
system.InitializeDebugger(); |
|
|
|
|
|
debugger_should_start = false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
running_wait.Wait(); |
|
|
|
|
|
result = system.Pause(); |
|
|
|
|
|
if (result != Core::SystemResultStatus::Success) { |
|
|
|
|
|
running_guard = false; |
|
|
|
|
|
this->SetRunning(false); |
|
|
|
|
|
emit ErrorThrown(result, system.GetStatusDetails()); |
|
|
|
|
|
} |
|
|
|
|
|
running_guard = false; |
|
|
|
|
|
|
|
|
|
|
|
if (!stop_token.stop_requested()) { |
|
|
|
|
|
was_active = true; |
|
|
|
|
|
emit DebugModeEntered(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; }); |
|
|
} else { |
|
|
} else { |
|
|
std::unique_lock lock{running_mutex}; |
|
|
|
|
|
Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); }); |
|
|
|
|
|
|
|
|
m_system.Pause(); |
|
|
|
|
|
m_is_running.store(false); |
|
|
|
|
|
m_is_running.notify_all(); |
|
|
|
|
|
|
|
|
|
|
|
emit DebugModeEntered(); |
|
|
|
|
|
Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; }); |
|
|
|
|
|
emit DebugModeLeft(); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Shutdown the main emulated process
|
|
|
// Shutdown the main emulated process
|
|
|
system.ShutdownMainProcess(); |
|
|
|
|
|
|
|
|
m_system.DetachDebugger(); |
|
|
|
|
|
m_system.ShutdownMainProcess(); |
|
|
|
|
|
|
|
|
#if MICROPROFILE_ENABLED
|
|
|
#if MICROPROFILE_ENABLED
|
|
|
MicroProfileOnThreadExit(); |
|
|
MicroProfileOnThreadExit(); |
|
|
|