System: Move more core functionality out of file

This file got way too large and has too much unrelated stuff.
pull/3732/head
Stenzek 2 months ago
parent cc1775f0be
commit 678b6101e7
No known key found for this signature in database

@ -2,10 +2,18 @@
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
#include "core.h"
#include "achievements.h"
#include "core_private.h"
#include "discord_presence.h"
#include "gdb_server.h"
#include "host.h"
#include "settings.h"
#include "system.h"
#include "system_private.h"
#include "video_thread.h"
#include "util/gpu_device.h"
#include "util/http_cache.h"
#include "util/ini_settings_interface.h"
#include "util/input_manager.h"
@ -15,9 +23,16 @@
#include "common/file_system.h"
#include "common/layered_settings_interface.h"
#include "common/log.h"
#include "common/memmap.h"
#include "common/path.h"
#include "common/ryml_helpers.h"
#include "common/string_util.h"
#include "common/threading.h"
#include "common/timer.h"
#include "scmversion/scmversion.h"
#include "cpuinfo.h"
#include "fmt/format.h"
#include <cstdarg>
@ -37,12 +52,19 @@ 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);
static void CheckCacheLineSize();
static void LogStartupInformation();
namespace {
struct CoreLocals
{
std::mutex settings_mutex;
LayeredSettingsInterface layered_settings_interface;
INISettingsInterface base_settings_interface;
Threading::ThreadHandle core_thread_handle;
Timer::Value process_start_time = 0;
};
} // namespace
@ -528,3 +550,233 @@ void Core::SetInputSettingsLayer(SettingsInterface* sif, std::unique_lock<std::m
{
s_locals.layered_settings_interface.SetLayer(LayeredSettingsInterface::LAYER_INPUT, sif);
}
bool Core::PerformEarlyHardwareChecks(Error* error)
{
// This shouldn't fail... if it does, just hope for the best.
cpuinfo_initialize();
#ifdef CPU_ARCH_X64
#ifdef CPU_ARCH_SSE41
if (!cpuinfo_has_x86_sse4_1())
{
Error::SetStringFmt(
error, "<h3>Your CPU does not support the SSE4.1 instruction set.</h3><p>SSE4.1 is required for this version of "
"DuckStation. Please download and switch to the legacy SSE2 version.</p><p>You can download this from <a "
"href=\"https://www.duckstation.org/\">www.duckstation.org</a> under \"Other Platforms\".");
return false;
}
#else
if (cpuinfo_has_x86_sse4_1())
{
Error::SetStringFmt(
error, "You are running the <strong>legacy SSE2 DuckStation executable</strong> on a CPU that supports the "
"SSE4.1 instruction set.\nPlease download and switch to the regular, non-SSE2 version.\nYou can download "
"this from <a href=\"https://www.duckstation.org/\">www.duckstation.org</a>.");
}
#endif
#endif
#ifndef DYNAMIC_HOST_PAGE_SIZE
// Check page size. If it doesn't match, it is a fatal error.
const size_t runtime_host_page_size = MemMap::GetRuntimePageSize();
if (runtime_host_page_size == 0)
{
Error::SetStringFmt(error, "Cannot determine size of page. Continuing with expectation of {} byte pages.",
HOST_PAGE_SIZE);
}
else if (HOST_PAGE_SIZE != runtime_host_page_size)
{
Error::SetStringFmt(
error, "Page size mismatch. This build was compiled with {} byte pages, but the system has {} byte pages.",
HOST_PAGE_SIZE, runtime_host_page_size);
return false;
}
#else
if (HOST_PAGE_SIZE == 0 || HOST_PAGE_SIZE < MIN_HOST_PAGE_SIZE || HOST_PAGE_SIZE > MAX_HOST_PAGE_SIZE)
{
Error::SetStringFmt(error, "Page size of {} bytes is out of the range supported by this build: {}-{}.",
HOST_PAGE_SIZE, MIN_HOST_PAGE_SIZE, MAX_HOST_PAGE_SIZE);
return false;
}
#endif
return true;
}
void Core::CheckCacheLineSize()
{
u32 max_line_size = 0;
if (cpuinfo_initialize())
{
const u32 num_l1is = cpuinfo_get_l1i_caches_count();
const u32 num_l1ds = cpuinfo_get_l1d_caches_count();
const u32 num_l2s = cpuinfo_get_l2_caches_count();
for (u32 i = 0; i < num_l1is; i++)
{
const cpuinfo_cache* cache = cpuinfo_get_l1i_cache(i);
if (cache)
max_line_size = std::max(max_line_size, cache->line_size);
}
for (u32 i = 0; i < num_l1ds; i++)
{
const cpuinfo_cache* cache = cpuinfo_get_l1d_cache(i);
if (cache)
max_line_size = std::max(max_line_size, cache->line_size);
}
for (u32 i = 0; i < num_l2s; i++)
{
const cpuinfo_cache* cache = cpuinfo_get_l2_cache(i);
if (cache)
max_line_size = std::max(max_line_size, cache->line_size);
}
}
if (max_line_size == 0)
{
ERROR_LOG("Cannot determine size of cache line. Continuing with expectation of {} byte lines.",
HOST_CACHE_LINE_SIZE);
}
else if (HOST_CACHE_LINE_SIZE != max_line_size)
{
// Not fatal, but does have performance implications.
WARNING_LOG(
"Cache line size mismatch. This build was compiled with {} byte lines, but the system has {} byte lines.",
HOST_CACHE_LINE_SIZE, max_line_size);
}
}
void Core::LogStartupInformation()
{
#if !defined(CPU_ARCH_X64) || defined(CPU_ARCH_SSE41)
const std::string_view suffix = {};
#else
const std::string_view suffix = " [Legacy SSE2]";
#endif
INFO_LOG("DuckStation for {} ({}){}", TARGET_OS_STR, CPU_ARCH_STR, suffix);
INFO_LOG("Version: {} [{}]", g_scm_tag_str, g_scm_branch_str);
INFO_LOG("SCM Timestamp: {}", g_scm_date_str);
if (const cpuinfo_package* package = cpuinfo_initialize() ? cpuinfo_get_package(0) : nullptr) [[likely]]
{
INFO_LOG("Host CPU: {}", package->name);
INFO_LOG("CPU has {} logical processor(s) and {} core(s) across {} cluster(s).", package->processor_count,
package->core_count, package->cluster_count);
}
#ifdef DYNAMIC_HOST_PAGE_SIZE
INFO_LOG("Host Page Size: {} bytes", HOST_PAGE_SIZE);
#endif
}
bool Core::ProcessStartup(Error* error)
{
s_locals.process_start_time = Timer::GetCurrentValue();
if (!System::AllocatePersistentMemory(error))
return false;
CheckCacheLineSize();
// Initialize rapidyaml before anything can use it.
SetRymlCallbacks();
#ifdef __linux__
// Running DuckStation out of /usr is not supported and makes no sense.
if (std::memcmp(EmuFolders::AppRoot.data(), "/usr/", 5) == 0)
return false;
#endif
return true;
}
void Core::ProcessShutdown()
{
System::ReleasePersistentMemory();
}
bool Core::CoreThreadInitialize(Error* error)
{
#ifdef _WIN32
// On Win32, we have a bunch of things which use COM (e.g. SDL, Cubeb, etc).
// We need to initialize COM first, before anything else does, because otherwise they might
// initialize it in single-threaded/apartment mode, which can't be changed to multithreaded.
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
Error::SetHResult(error, "CoInitializeEx() failed: ", hr);
return false;
}
#endif
s_locals.core_thread_handle = Threading::ThreadHandle::GetForCallingThread();
System::LoadSettings(false);
LogStartupInformation();
VideoThread::Internal::ProcessStartup();
Achievements::Initialize();
#ifdef ENABLE_DISCORD_PRESENCE
if (g_settings.enable_discord_presence)
DiscordPresence::Initialize();
#endif
return true;
}
void Core::CoreThreadShutdown()
{
#ifdef ENABLE_DISCORD_PRESENCE
DiscordPresence::Shutdown();
#endif
Achievements::Shutdown();
GPUDevice::UnloadDynamicLibraries();
InputManager::CloseSources();
HTTPCache::Shutdown();
VideoThread::Internal::ProcessShutdown();
s_locals.core_thread_handle = {};
#ifdef _WIN32
CoUninitialize();
#endif
}
const Threading::ThreadHandle& Host::GetCoreThreadHandle()
{
return Core::s_locals.core_thread_handle;
}
bool Host::IsOnCoreThread()
{
return Core::s_locals.core_thread_handle.IsCallingThread();
}
float Core::GetProcessUptime()
{
return static_cast<float>(Timer::ConvertValueToSeconds(Timer::GetCurrentValue() - s_locals.process_start_time));
}
void Core::IdleUpdate()
{
InputManager::PollSources();
#ifdef ENABLE_DISCORD_PRESENCE
DiscordPresence::Poll();
#endif
HTTPCache::PollRequests();
Achievements::IdleUpdate();
#ifdef ENABLE_GDB_SERVER
GDBServer::Poll(0);
#endif
}

@ -3,8 +3,9 @@
#pragma once
#include "types.h"
#include "common/small_string.h"
#include "common/types.h"
#include <mutex>
#include <string>
@ -64,4 +65,7 @@ SettingsInterface* GetGameSettingsLayer();
/// Retrieves the input settings layer, if present. Must call with lock held.
SettingsInterface* GetInputSettingsLayer();
/// Returns the number of seconds since the process started.
float GetProcessUptime();
} // namespace Core

@ -32,6 +32,24 @@ void SetGameSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>&
/// Sets the input profile settings layer. Called by System when the game changes.
void SetInputSettingsLayer(SettingsInterface* sif, std::unique_lock<std::mutex>& lock);
/// Performs mandatory hardware checks.
bool PerformEarlyHardwareChecks(Error* error);
/// Called on process startup, as early as possible.
bool ProcessStartup(Error* error);
/// Called on process shutdown.
void ProcessShutdown();
/// Called on CPU thread initialization.
bool CoreThreadInitialize(Error* error);
/// Called on CPU thread shutdown.
void CoreThreadShutdown();
/// Called to poll input when the session is not running.
void IdleUpdate();
} // namespace Core
namespace Host {

@ -13,6 +13,10 @@
class Error;
namespace Threading {
class ThreadHandle;
}
namespace Host {
/// Returns true if the specified resource file exists.
@ -64,6 +68,9 @@ const char* GetLanguageName(std::string_view language_code);
/// Refreshes the UI when the language is changed.
bool ChangeLanguage(const char* new_language);
/// Gets a handle to the core thread.
const Threading::ThreadHandle& GetCoreThreadHandle();
/// Returns true if the currently executing thread is the core thread.
bool IsOnCoreThread();

@ -5,7 +5,7 @@
#include "gpu.h"
#include "gpu_backend.h"
#include "system.h"
#include "system_private.h"
#include "host.h"
#include "video_thread.h"
#include "util/media_capture.h"
@ -139,13 +139,13 @@ u32 PerformanceCounters::GetFrameTimeHistoryPos()
void PerformanceCounters::Clear()
{
DebugAssert(System::GetCoreThreadHandle().IsCallingThread());
DebugAssert(Host::IsOnCoreThread());
VideoThread::RunOnThread([]() { s_state = {}; });
}
void PerformanceCounters::Reset()
{
DebugAssert(System::GetCoreThreadHandle().IsCallingThread());
DebugAssert(Host::IsOnCoreThread());
VideoThread::RunOnThread(
[frame_number = System::GetFrameNumber(), internal_frame_number = System::GetInternalFrameNumber()]() {
const Timer::Value now_ticks = Timer::GetCurrentValue();
@ -155,7 +155,7 @@ void PerformanceCounters::Reset()
s_state.last_frame_number = frame_number;
s_state.last_internal_frame_number = internal_frame_number;
s_state.last_core_thread_time = System::GetCoreThreadHandle().GetCPUTime();
s_state.last_core_thread_time = Host::GetCoreThreadHandle().GetCPUTime();
s_state.last_video_thread_time = VideoThread::Internal::GetThreadHandle().GetCPUTime();
s_state.average_frame_time_accumulator = 0.0f;
@ -206,7 +206,7 @@ void PerformanceCounters::Update(GPUBackend* gpu, u32 frame_number, u32 internal
s_state.fps = static_cast<float>(internal_frames_run) / time;
s_state.speed = (s_state.vps / System::GetVideoFrameRate()) * 100.0f;
const u64 core_thread_time = System::GetCoreThreadHandle().GetCPUTime();
const u64 core_thread_time = Host::GetCoreThreadHandle().GetCPUTime();
const u64 video_thread_time = VideoThread::Internal::GetThreadHandle().GetCPUTime();
const u64 core_thread_delta = core_thread_time - s_state.last_core_thread_time;
const u64 video_thread_delta = video_thread_time - s_state.last_video_thread_time;

@ -33,3 +33,10 @@ void Update(GPUBackend* gpu, u32 frame_number, u32 internal_frame_number);
void AccumulateGPUTime();
} // namespace PerformanceCounters
namespace Host {
/// Called when performance metrics are updated, approximately once a second.
void OnPerformanceCountersUpdated(const GPUBackend* gpu_backend);
} // namespace Host

@ -44,8 +44,6 @@
#include "video_presenter.h"
#include "video_thread.h"
#include "scmversion/scmversion.h"
#include "util/audio_stream.h"
#include "util/cd_image.h"
#include "util/compress_helpers.h"
@ -68,7 +66,6 @@
#include "common/log.h"
#include "common/memmap.h"
#include "common/path.h"
#include "common/ryml_helpers.h"
#include "common/string_util.h"
#include "common/threading.h"
#include "common/time_helpers.h"
@ -78,7 +75,6 @@
#include "IconsFontAwesome.h"
#include "IconsPromptFont.h"
#include "cpuinfo.h"
#include "fmt/chrono.h"
#include "fmt/format.h"
#include "imgui.h"
@ -94,11 +90,6 @@
LOG_CHANNEL(System);
#ifdef _WIN32
#include "common/windows_headers.h"
#include <Objbase.h>
#endif
// #define PROFILE_MEMORY_SAVE_STATES 1
SystemBootParameters::SystemBootParameters() = default;
@ -142,9 +133,6 @@ struct UndoSaveStateBuffer : public SaveStateBuffer
} // namespace
static void CheckCacheLineSize();
static void LogStartupInformation();
static const SettingsInterface& GetInputSourceSettingsLayer(std::unique_lock<std::mutex>& lock);
static const SettingsInterface& GetControllerSettingsLayer(std::unique_lock<std::mutex>& lock);
static const SettingsInterface& GetHotkeySettingsLayer(std::unique_lock<std::mutex>& lock);
@ -311,8 +299,6 @@ struct ALIGN_TO_CACHE_LINE StateVars
std::unique_ptr<INISettingsInterface> input_settings_interface;
std::string input_profile_name;
Threading::ThreadHandle core_thread_handle;
// temporary save state, created when loading, used to undo load state
std::optional<UndoSaveStateBuffer> undo_load_state;
@ -321,9 +307,6 @@ struct ALIGN_TO_CACHE_LINE StateVars
// internal async task counters
std::atomic_uint32_t outstanding_save_state_tasks{0};
// process start time
Timer::Value process_start_time = 0;
};
} // namespace
@ -332,124 +315,7 @@ static StateVars s_state;
} // namespace System
bool System::PerformEarlyHardwareChecks(Error* error)
{
// This shouldn't fail... if it does, just hope for the best.
cpuinfo_initialize();
#ifdef CPU_ARCH_X64
#ifdef CPU_ARCH_SSE41
if (!cpuinfo_has_x86_sse4_1())
{
Error::SetStringFmt(
error, "<h3>Your CPU does not support the SSE4.1 instruction set.</h3><p>SSE4.1 is required for this version of "
"DuckStation. Please download and switch to the legacy SSE2 version.</p><p>You can download this from <a "
"href=\"https://www.duckstation.org/\">www.duckstation.org</a> under \"Other Platforms\".");
return false;
}
#else
if (cpuinfo_has_x86_sse4_1())
{
Error::SetStringFmt(
error, "You are running the <strong>legacy SSE2 DuckStation executable</strong> on a CPU that supports the "
"SSE4.1 instruction set.\nPlease download and switch to the regular, non-SSE2 version.\nYou can download "
"this from <a href=\"https://www.duckstation.org/\">www.duckstation.org</a>.");
}
#endif
#endif
#ifndef DYNAMIC_HOST_PAGE_SIZE
// Check page size. If it doesn't match, it is a fatal error.
const size_t runtime_host_page_size = MemMap::GetRuntimePageSize();
if (runtime_host_page_size == 0)
{
Error::SetStringFmt(error, "Cannot determine size of page. Continuing with expectation of {} byte pages.",
HOST_PAGE_SIZE);
}
else if (HOST_PAGE_SIZE != runtime_host_page_size)
{
Error::SetStringFmt(
error, "Page size mismatch. This build was compiled with {} byte pages, but the system has {} byte pages.",
HOST_PAGE_SIZE, runtime_host_page_size);
return false;
}
#else
if (HOST_PAGE_SIZE == 0 || HOST_PAGE_SIZE < MIN_HOST_PAGE_SIZE || HOST_PAGE_SIZE > MAX_HOST_PAGE_SIZE)
{
Error::SetStringFmt(error, "Page size of {} bytes is out of the range supported by this build: {}-{}.",
HOST_PAGE_SIZE, MIN_HOST_PAGE_SIZE, MAX_HOST_PAGE_SIZE);
return false;
}
#endif
return true;
}
void System::CheckCacheLineSize()
{
u32 max_line_size = 0;
if (cpuinfo_initialize())
{
const u32 num_l1is = cpuinfo_get_l1i_caches_count();
const u32 num_l1ds = cpuinfo_get_l1d_caches_count();
const u32 num_l2s = cpuinfo_get_l2_caches_count();
for (u32 i = 0; i < num_l1is; i++)
{
const cpuinfo_cache* cache = cpuinfo_get_l1i_cache(i);
if (cache)
max_line_size = std::max(max_line_size, cache->line_size);
}
for (u32 i = 0; i < num_l1ds; i++)
{
const cpuinfo_cache* cache = cpuinfo_get_l1d_cache(i);
if (cache)
max_line_size = std::max(max_line_size, cache->line_size);
}
for (u32 i = 0; i < num_l2s; i++)
{
const cpuinfo_cache* cache = cpuinfo_get_l2_cache(i);
if (cache)
max_line_size = std::max(max_line_size, cache->line_size);
}
}
if (max_line_size == 0)
{
ERROR_LOG("Cannot determine size of cache line. Continuing with expectation of {} byte lines.",
HOST_CACHE_LINE_SIZE);
}
else if (HOST_CACHE_LINE_SIZE != max_line_size)
{
// Not fatal, but does have performance implications.
WARNING_LOG(
"Cache line size mismatch. This build was compiled with {} byte lines, but the system has {} byte lines.",
HOST_CACHE_LINE_SIZE, max_line_size);
}
}
void System::LogStartupInformation()
{
#if !defined(CPU_ARCH_X64) || defined(CPU_ARCH_SSE41)
const std::string_view suffix = {};
#else
const std::string_view suffix = " [Legacy SSE2]";
#endif
INFO_LOG("DuckStation for {} ({}){}", TARGET_OS_STR, CPU_ARCH_STR, suffix);
INFO_LOG("Version: {} [{}]", g_scm_tag_str, g_scm_branch_str);
INFO_LOG("SCM Timestamp: {}", g_scm_date_str);
if (const cpuinfo_package* package = cpuinfo_initialize() ? cpuinfo_get_package(0) : nullptr) [[likely]]
{
INFO_LOG("Host CPU: {}", package->name);
INFO_LOG("CPU has {} logical processor(s) and {} core(s) across {} cluster(s).", package->processor_count,
package->core_count, package->cluster_count);
}
#ifdef DYNAMIC_HOST_PAGE_SIZE
INFO_LOG("Host Page Size: {} bytes", HOST_PAGE_SIZE);
#endif
}
bool System::ProcessStartup(Error* error)
bool System::AllocatePersistentMemory(Error* error)
{
Timer timer;
@ -468,122 +334,15 @@ bool System::ProcessStartup(Error* error)
}
VERBOSE_LOG("Memory allocation took {} ms.", timer.GetTimeMilliseconds());
CheckCacheLineSize();
// Initialize rapidyaml before anything can use it.
SetRymlCallbacks();
#ifdef __linux__
// Running DuckStation out of /usr is not supported and makes no sense.
if (std::memcmp(EmuFolders::AppRoot.data(), "/usr/", 5) == 0)
return false;
#endif
s_state.process_start_time = Timer::GetCurrentValue();
return true;
}
void System::ProcessShutdown()
void System::ReleasePersistentMemory()
{
Bus::ReleaseMemory();
CPU::CodeCache::ProcessShutdown();
}
float System::GetProcessUptime()
{
return static_cast<float>(Timer::ConvertValueToSeconds(Timer::GetCurrentValue() - s_state.process_start_time));
}
bool System::CoreThreadInitialize(Error* error)
{
#ifdef _WIN32
// On Win32, we have a bunch of things which use COM (e.g. SDL, Cubeb, etc).
// We need to initialize COM first, before anything else does, because otherwise they might
// initialize it in single-threaded/apartment mode, which can't be changed to multithreaded.
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
Error::SetHResult(error, "CoInitializeEx() failed: ", hr);
return false;
}
#endif
s_state.core_thread_handle = Threading::ThreadHandle::GetForCallingThread();
// This will call back to Host::LoadSettings() -> ReloadSources().
LoadSettings(false);
LogStartupInformation();
VideoThread::Internal::ProcessStartup();
Achievements::Initialize();
#ifdef ENABLE_DISCORD_PRESENCE
if (g_settings.enable_discord_presence)
DiscordPresence::Initialize();
#endif
return true;
}
void System::CoreThreadShutdown()
{
#ifdef ENABLE_DISCORD_PRESENCE
DiscordPresence::Shutdown();
#endif
Achievements::Shutdown();
GPUDevice::UnloadDynamicLibraries();
InputManager::CloseSources();
HTTPCache::Shutdown();
VideoThread::Internal::ProcessShutdown();
s_state.core_thread_handle = {};
#ifdef _WIN32
CoUninitialize();
#endif
}
const Threading::ThreadHandle& System::GetCoreThreadHandle()
{
return s_state.core_thread_handle;
}
void System::SetCoreThreadHandle(Threading::ThreadHandle handle)
{
s_state.core_thread_handle = std::move(handle);
}
bool Host::IsOnCoreThread()
{
// This really doesn't belong here...
return System::GetCoreThreadHandle().IsCallingThread();
}
void System::IdlePollUpdate()
{
InputManager::PollSources();
#ifdef ENABLE_DISCORD_PRESENCE
DiscordPresence::Poll();
#endif
HTTPCache::PollRequests();
Achievements::IdleUpdate();
#ifdef ENABLE_GDB_SERVER
GDBServer::Poll(0);
#endif
}
System::State System::GetState()
{
return s_state.state;
@ -3819,10 +3578,11 @@ void System::UpdateSpeedLimiterState()
{
const u64 typical_time =
std::min(std::max<u64>((new_scheduler_period / 1000000) * 1000000, MIN_FRAME_TIME_NS), TYPICAL_FRAME_TIME_NS);
if (s_state.core_thread_handle)
const Threading::ThreadHandle& core_thread = Host::GetCoreThreadHandle();
if (core_thread)
{
s_state.core_thread_handle.SetTimeConstraints(s_state.optimal_frame_pacing, new_scheduler_period, typical_time,
new_scheduler_period);
core_thread.SetTimeConstraints(s_state.optimal_frame_pacing, new_scheduler_period, typical_time,
new_scheduler_period);
}
const Threading::ThreadHandle& video_thread = VideoThread::Internal::GetThreadHandle();
if (video_thread)
@ -5364,7 +5124,7 @@ void System::DoRewind()
VideoThread::PresentCurrentFrame();
Host::PumpMessagesOnCoreThread();
IdlePollUpdate();
Core::IdleUpdate();
// get back into it straight away if we're no longer rewinding
if (!IsRewinding())

@ -252,8 +252,6 @@ bool PopulateGameListEntryFromCurrentGame(GameList::Entry* entry, Error* error);
void FormatLatencyStats(SmallStringBase& str);
/// Loads global settings (i.e. EmuConfig).
void LoadSettings(bool display_osd_messages);
void SetDefaultSettings(SettingsInterface& si);
/// Reloads settings, and applies any changes present.

@ -59,32 +59,14 @@ void OnMemoryCardAccessed();
/// Immediately terminates the virtual machine, no state is saved.
void AbnormalShutdown(const std::string_view reason);
/// Performs mandatory hardware checks.
bool PerformEarlyHardwareChecks(Error* error);
/// Called on process startup, as early as possible.
bool ProcessStartup(Error* error);
bool AllocatePersistentMemory(Error* error);
/// Called on process shutdown.
void ProcessShutdown();
/// Returns the number of seconds since the process started.
float GetProcessUptime();
/// Called on CPU thread initialization.
bool CoreThreadInitialize(Error* error);
/// Called on CPU thread shutdown.
void CoreThreadShutdown();
void ReleasePersistentMemory();
/// Returns a handle to the CPU thread.
const Threading::ThreadHandle& GetCoreThreadHandle();
/// Changes the CPU thread handle, use with care.
void SetCoreThreadHandle(Threading::ThreadHandle handle);
/// Polls input, updates subsystems which are present while paused/inactive.
void IdlePollUpdate();
/// Loads global settings.
void LoadSettings(bool display_osd_messages);
} // namespace System
@ -114,9 +96,6 @@ void OnSystemResumed();
/// Called when the VM abnormally exits because an error has occurred, and it cannot continue.
void OnSystemAbnormalShutdown(const std::string_view reason);
/// Called when performance metrics are updated, approximately once a second.
void OnPerformanceCountersUpdated(const GPUBackend* gpu_backend);
/// Provided by the host; called when the running executable changes.
void OnSystemGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name,
GameHash game_hash);

@ -1754,7 +1754,7 @@ SettingsInterface& VideoPresenter::GetPostProcessingSettingsInterface(const char
void VideoPresenter::TogglePostProcessing()
{
DebugAssert(System::GetCoreThreadHandle().IsCallingThread());
DebugAssert(Host::IsOnCoreThread());
VideoThread::RunOnThread([]() {
GPUBackend* const backend = VideoThread::GetGPUBackend();
@ -1772,7 +1772,7 @@ void VideoPresenter::TogglePostProcessing()
void VideoPresenter::ReloadPostProcessingSettings(bool display, bool internal, bool reload_shaders)
{
DebugAssert(System::GetCoreThreadHandle().IsCallingThread());
DebugAssert(Host::IsOnCoreThread());
VideoThread::RunOnThread([display, internal, reload_shaders]() {
GPUBackend* const backend = VideoThread::GetGPUBackend();

@ -215,7 +215,7 @@ void QtHost::RegisterTypes()
bool QtHost::PerformEarlyHardwareChecks()
{
Error error;
const bool okay = System::PerformEarlyHardwareChecks(&error);
const bool okay = Core::PerformEarlyHardwareChecks(&error);
if (okay && !error.IsValid()) [[likely]]
return true;
@ -268,7 +268,7 @@ bool QtHost::EarlyProcessStartup()
QApplication::setDesktopFileName("org.duckstation.DuckStation"_L1);
Error error;
if (!System::ProcessStartup(&error)) [[unlikely]]
if (!Core::ProcessStartup(&error)) [[unlikely]]
{
QMessageBox::critical(nullptr, QStringLiteral("Process Startup Failed"),
QString::fromStdString(error.GetDescription()));
@ -286,7 +286,7 @@ bool QtHost::EarlyProcessStartup()
void QtHost::ProcessShutdown()
{
System::ProcessShutdown();
Core::ProcessShutdown();
// Ensure log is flushed.
Log::SetFileOutputParams(false, nullptr);
@ -1024,10 +1024,6 @@ void CoreThread::startFullscreenUI()
if (System::IsValid() || VideoThread::IsFullscreenUIRequested())
return;
// we want settings loaded so we choose the correct renderer
// this also sorts out input sources.
System::LoadSettings(false);
// borrow the game start fullscreen flag
const bool start_fullscreen =
(QtHost::s_state.start_fullscreen_ui_fullscreen || Core::GetBaseBoolSettingValue("Main", "StartFullscreen", false));
@ -2082,7 +2078,7 @@ void CoreThread::processAuxiliaryRenderWindowInputEvent(void* userdata, quint32
void CoreThread::doBackgroundControllerPoll()
{
System::IdlePollUpdate();
Core::IdleUpdate();
}
void CoreThread::createBackgroundControllerPollTimer()
@ -2221,7 +2217,7 @@ void CoreThread::run()
// input source setup must happen on emu thread
{
Error startup_error;
if (!System::CoreThreadInitialize(&startup_error))
if (!Core::CoreThreadInitialize(&startup_error))
{
moveToThread(m_ui_thread);
Host::ReportFatalError("Fatal Startup Error", startup_error.GetDescription());
@ -2273,7 +2269,7 @@ void CoreThread::run()
QtHost::s_async_task_queue.SetWorkerCount(0);
// and tidy up everything left
System::CoreThreadShutdown();
Core::CoreThreadShutdown();
// move back to UI thread
moveToThread(m_ui_thread);

@ -12,6 +12,7 @@
#include "core/gpu.h"
#include "core/gpu_backend.h"
#include "core/host.h"
#include "core/performance_counters.h"
#include "core/spu.h"
#include "core/system.h"
#include "core/system_private.h"
@ -962,7 +963,7 @@ int main(int argc, char* argv[])
CrashHandler::Install(&Bus::CleanupMemoryMap);
Error error;
if (!System::PerformEarlyHardwareChecks(&error) || !System::ProcessStartup(&error))
if (!Core::PerformEarlyHardwareChecks(&error) || !Core::ProcessStartup(&error))
{
std::fprintf(stderr, "ERROR: ProcessStartup() failed: %s\n", error.GetDescription().c_str());
return EXIT_FAILURE;
@ -987,7 +988,7 @@ int main(int argc, char* argv[])
if (!RegTestHost::SetNewDataRoot(autoboot->path))
return EXIT_FAILURE;
if (!System::CoreThreadInitialize(&error))
if (!Core::CoreThreadInitialize(&error))
{
ERROR_LOG("CoreThreadInitialize() failed: {}", error.GetDescription());
return EXIT_FAILURE;
@ -1046,7 +1047,7 @@ cleanup:
RegTestHost::s_async_task_queue.SetWorkerCount(0);
RegTestHost::ProcessCoreThreadEvents();
System::CoreThreadShutdown();
System::ProcessShutdown();
Core::CoreThreadShutdown();
Core::ProcessShutdown();
return result;
}

@ -945,7 +945,7 @@ void ImGuiManager::UpdateOSDMessageRunIdle(const std::unique_lock<std::mutex>& l
return;
}
if (System::GetCoreThreadHandle().IsCallingThread())
if (Host::GetCoreThreadHandle().IsCallingThread())
{
VideoThread::RunOnThread([]() {
const std::unique_lock lock(s_state.osd_messages_lock);

@ -1891,7 +1891,7 @@ void InputManager::OnInputDeviceConnected(InputBindingKey key, std::string_view
Host::OnInputDeviceConnected(key, identifier, device_name);
const bool has_fsui = (System::IsValid() || VideoThread::IsFullscreenUIRequested());
if (has_fsui && System::GetProcessUptime() >= DEVICE_CONNECTED_NOTIFICATION_DELAY)
if (has_fsui && Core::GetProcessUptime() >= DEVICE_CONNECTED_NOTIFICATION_DELAY)
{
Host::AddIconOSDMessage(OSDMessageType::Info, fmt::format("ControllerConnected{}", identifier), ICON_FA_GAMEPAD,
fmt::format(TRANSLATE_FS("InputManager", "Controller {} connected."), identifier));

Loading…
Cancel
Save