mirror of
https://github.com/stenzek/duckstation.git
synced 2026-10-11 22:49:58 +00:00
Core: Centralize the async task queue
Will be needed for multithreaded shader compilation, and it was duplicated code anyway.
This commit is contained in:
+22
-1
@@ -28,6 +28,7 @@
|
||||
#include "common/path.h"
|
||||
#include "common/ryml_helpers.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/task_queue.h"
|
||||
#include "common/threading.h"
|
||||
#include "common/timer.h"
|
||||
|
||||
@@ -49,6 +50,9 @@ LOG_CHANNEL(Core);
|
||||
|
||||
namespace Core {
|
||||
|
||||
/// Use two async worker threads, should be enough for most tasks.
|
||||
static constexpr u32 NUM_ASYNC_WORKER_THREADS = 2;
|
||||
|
||||
static bool SetAppRootAndResources(const char* resources_subdir, Error* error);
|
||||
static bool SetDataRoot(Error* error);
|
||||
static void SetDefaultSettings(SettingsInterface& si, bool host, bool system, bool controller);
|
||||
@@ -66,6 +70,8 @@ struct CoreLocals
|
||||
Threading::ThreadHandle core_thread_handle;
|
||||
|
||||
Timer::Value process_start_time = 0;
|
||||
|
||||
TaskQueue async_task_queue;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -695,7 +701,7 @@ void Core::ProcessShutdown()
|
||||
System::ReleasePersistentMemory();
|
||||
}
|
||||
|
||||
bool Core::CoreThreadInitialize(Error* error)
|
||||
bool Core::CoreThreadInitialize(bool disable_worker_threads, Error* error)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// On Win32, we have a bunch of things which use COM (e.g. SDL, Cubeb, etc).
|
||||
@@ -711,6 +717,9 @@ bool Core::CoreThreadInitialize(Error* error)
|
||||
|
||||
s_locals.core_thread_handle = Threading::ThreadHandle::GetForCallingThread();
|
||||
|
||||
if (!disable_worker_threads)
|
||||
s_locals.async_task_queue.SetWorkerCount(NUM_ASYNC_WORKER_THREADS);
|
||||
|
||||
System::LoadSettings(false);
|
||||
|
||||
LogStartupInformation();
|
||||
@@ -729,6 +738,8 @@ bool Core::CoreThreadInitialize(Error* error)
|
||||
|
||||
void Core::CoreThreadShutdown()
|
||||
{
|
||||
s_locals.async_task_queue.SetWorkerCount(0);
|
||||
|
||||
#ifdef ENABLE_DISCORD_PRESENCE
|
||||
DiscordPresence::Shutdown();
|
||||
#endif
|
||||
@@ -760,6 +771,16 @@ bool Host::IsOnCoreThread()
|
||||
return Core::s_locals.core_thread_handle.IsCallingThread();
|
||||
}
|
||||
|
||||
void Host::QueueAsyncTask(std::function<void()> function)
|
||||
{
|
||||
Core::s_locals.async_task_queue.SubmitTask(std::move(function));
|
||||
}
|
||||
|
||||
void Host::WaitForAllAsyncTasks()
|
||||
{
|
||||
Core::s_locals.async_task_queue.WaitForAll();
|
||||
}
|
||||
|
||||
float Core::GetProcessUptime()
|
||||
{
|
||||
return static_cast<float>(Timer::ConvertValueToSeconds(Timer::GetCurrentValue() - s_locals.process_start_time));
|
||||
|
||||
@@ -42,7 +42,7 @@ bool ProcessStartup(Error* error);
|
||||
void ProcessShutdown();
|
||||
|
||||
/// Called on CPU thread initialization.
|
||||
bool CoreThreadInitialize(Error* error);
|
||||
bool CoreThreadInitialize(bool disable_worker_threads, Error* error);
|
||||
|
||||
/// Called on CPU thread shutdown.
|
||||
void CoreThreadShutdown();
|
||||
|
||||
@@ -46,7 +46,6 @@
|
||||
#include "common/path.h"
|
||||
#include "common/scoped_guard.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/task_queue.h"
|
||||
#include "common/threading.h"
|
||||
|
||||
#include "util/audio_stream.h"
|
||||
@@ -106,9 +105,6 @@ QT_TRANSLATE_NOOP("MAC_APPLICATION_MENU", "About %1")
|
||||
|
||||
static constexpr u32 SETTINGS_SAVE_DELAY = 1000;
|
||||
|
||||
/// Use two async worker threads, should be enough for most tasks.
|
||||
static constexpr u32 NUM_ASYNC_WORKER_THREADS = 2;
|
||||
|
||||
/// Interval at which the controllers are polled when the system is not active.
|
||||
static constexpr int BACKGROUND_CONTROLLER_POLLING_INTERVAL_WITH_DEVICES = 100;
|
||||
static constexpr int BACKGROUND_CONTROLLER_POLLING_INTERVAL_WITHOUT_DEVICES = 1000;
|
||||
@@ -180,7 +176,6 @@ struct State
|
||||
} // namespace
|
||||
|
||||
ALIGN_TO_CACHE_LINE static State s_state;
|
||||
ALIGN_TO_CACHE_LINE static TaskQueue s_async_task_queue;
|
||||
|
||||
} // namespace QtHost
|
||||
|
||||
@@ -1712,16 +1707,6 @@ void Host::RunOnUIThread(std::function<void()> function, bool block /* = false*/
|
||||
block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, std::move(function));
|
||||
}
|
||||
|
||||
void Host::QueueAsyncTask(std::function<void()> function)
|
||||
{
|
||||
QtHost::s_async_task_queue.SubmitTask(std::move(function));
|
||||
}
|
||||
|
||||
void Host::WaitForAllAsyncTasks()
|
||||
{
|
||||
QtHost::s_async_task_queue.WaitForAll();
|
||||
}
|
||||
|
||||
QtAsyncTask::QtAsyncTask(WorkCallback callback)
|
||||
{
|
||||
m_callback = std::move(callback);
|
||||
@@ -2218,7 +2203,7 @@ void CoreThread::run()
|
||||
// input source setup must happen on emu thread
|
||||
{
|
||||
Error startup_error;
|
||||
if (!Core::CoreThreadInitialize(&startup_error))
|
||||
if (!Core::CoreThreadInitialize(false, &startup_error))
|
||||
{
|
||||
moveToThread(m_ui_thread);
|
||||
Host::ReportFatalError("Fatal Startup Error", startup_error.GetDescription());
|
||||
@@ -2226,10 +2211,6 @@ void CoreThread::run()
|
||||
}
|
||||
}
|
||||
|
||||
// start up worker threads
|
||||
// TODO: Replace this with QThreads
|
||||
QtHost::s_async_task_queue.SetWorkerCount(NUM_ASYNC_WORKER_THREADS);
|
||||
|
||||
// connections
|
||||
connect(qApp, &QGuiApplication::applicationStateChanged, this, &CoreThread::applicationStateChanged);
|
||||
|
||||
@@ -2266,9 +2247,6 @@ void CoreThread::run()
|
||||
|
||||
destroyBackgroundControllerPollTimer();
|
||||
|
||||
// join worker threads
|
||||
QtHost::s_async_task_queue.SetWorkerCount(0);
|
||||
|
||||
// and tidy up everything left
|
||||
Core::CoreThreadShutdown();
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "common/path.h"
|
||||
#include "common/sha256_digest.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/task_queue.h"
|
||||
#include "common/threading.h"
|
||||
#include "common/time_helpers.h"
|
||||
#include "common/timer.h"
|
||||
@@ -71,7 +70,6 @@ struct RegTestHostState
|
||||
};
|
||||
|
||||
static RegTestHostState s_state;
|
||||
ALIGN_TO_CACHE_LINE static TaskQueue s_async_task_queue;
|
||||
|
||||
} // namespace RegTestHost
|
||||
|
||||
@@ -365,16 +363,6 @@ void Host::RunOnUIThread(std::function<void()> function, bool block /* = false *
|
||||
RunOnCoreThread(std::move(function), block);
|
||||
}
|
||||
|
||||
void Host::QueueAsyncTask(std::function<void()> function)
|
||||
{
|
||||
RegTestHost::s_async_task_queue.SubmitTask(std::move(function));
|
||||
}
|
||||
|
||||
void Host::WaitForAllAsyncTasks()
|
||||
{
|
||||
RegTestHost::s_async_task_queue.WaitForAll();
|
||||
}
|
||||
|
||||
void Host::RequestResizeHostDisplay(s32 width, s32 height)
|
||||
{
|
||||
//
|
||||
@@ -989,15 +977,12 @@ int main(int argc, char* argv[])
|
||||
if (!RegTestHost::SetNewDataRoot(autoboot->path))
|
||||
return EXIT_FAILURE;
|
||||
|
||||
if (!Core::CoreThreadInitialize(&error))
|
||||
if (!Core::CoreThreadInitialize(true, &error))
|
||||
{
|
||||
ERROR_LOG("CoreThreadInitialize() failed: {}", error.GetDescription());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Only one async worker, keep the CPU usage down so we can parallelize execution of regtest itself.
|
||||
RegTestHost::s_async_task_queue.SetWorkerCount(1);
|
||||
|
||||
RegTestHost::HookSignals();
|
||||
|
||||
int result = -1;
|
||||
@@ -1045,8 +1030,6 @@ int main(int argc, char* argv[])
|
||||
result = 0;
|
||||
|
||||
cleanup:
|
||||
RegTestHost::s_async_task_queue.SetWorkerCount(0);
|
||||
|
||||
RegTestHost::ProcessCoreThreadEvents();
|
||||
Core::CoreThreadShutdown();
|
||||
Core::ProcessShutdown();
|
||||
|
||||
Reference in New Issue
Block a user