[core] move event creation to attached Core::System, remove unused atomics/prevent false share on Core::Timing

Signed-off-by: lizzie <lizzie@eden-emu.dev>
This commit is contained in:
lizzie 2026-06-05 00:58:07 +00:00
parent a4e9b08fe7
commit 4bc22797bb
18 changed files with 122 additions and 211 deletions

View File

@ -19,9 +19,11 @@ using namespace std::literals;
constexpr auto INCREMENT_TIME{5ms}; constexpr auto INCREMENT_TIME{5ms};
DeviceSession::DeviceSession(Core::System& system_) DeviceSession::DeviceSession(Core::System& system_)
: system{system_}, thread_event{Core::Timing::CreateEvent( : system{system_}
"AudioOutSampleTick", , thread_event{system_.CreateEvent("AudioOutSampleTick", [this](s64 time, std::chrono::nanoseconds) {
[this](s64 time, std::chrono::nanoseconds) { return ThreadFunc(); })} {} return ThreadFunc();
})}
{}
DeviceSession::~DeviceSession() { DeviceSession::~DeviceSession() {
Finalize(); Finalize();

View File

@ -968,4 +968,8 @@ void System::ApplySettings() {
} }
} }
std::shared_ptr<Core::Timing::EventType> System::CreateEvent(std::string name, Core::Timing::TimedCallback&& callback) {
return std::make_shared<Core::Timing::EventType>(std::move(callback), std::move(name));
}
} // namespace Core } // namespace Core

View File

@ -19,6 +19,7 @@
#include "core/file_sys/vfs/vfs_types.h" #include "core/file_sys/vfs/vfs_types.h"
#include "core/hle/service/os/event.h" #include "core/hle/service/os/event.h"
#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/kernel_helpers.h"
#include "core/core_timing.h"
namespace Core::Frontend { namespace Core::Frontend {
class EmuWindow; class EmuWindow;
@ -438,6 +439,8 @@ public:
/// Applies any changes to settings to this core instance. /// Applies any changes to settings to this core instance.
void ApplySettings(); void ApplySettings();
std::shared_ptr<Core::Timing::EventType> CreateEvent(std::string name, Core::Timing::TimedCallback&& callback);
private: private:
struct Impl; struct Impl;
std::unique_ptr<Impl> impl; std::unique_ptr<Impl> impl;

View File

@ -23,10 +23,6 @@ namespace Core::Timing {
constexpr s64 MAX_SLICE_LENGTH = 10000; constexpr s64 MAX_SLICE_LENGTH = 10000;
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
return std::make_shared<EventType>(std::move(callback), std::move(name));
}
struct CoreTiming::Event { struct CoreTiming::Event {
s64 time; s64 time;
u64 fifo_order; u64 fifo_order;
@ -36,11 +32,10 @@ struct CoreTiming::Event {
// Sort by time, unless the times are the same, in which case sort by // Sort by time, unless the times are the same, in which case sort by
// the order added to the queue // the order added to the queue
friend bool operator>(const Event& left, const Event& right) { friend bool operator>(const Event& left, const Event& right) noexcept {
return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order); return std::tie(left.time, left.fifo_order) > std::tie(right.time, right.fifo_order);
} }
friend bool operator<(const Event& left, const Event& right) noexcept {
friend bool operator<(const Event& left, const Event& right) {
return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order); return std::tie(left.time, left.fifo_order) < std::tie(right.time, right.fifo_order);
} }
}; };
@ -60,8 +55,6 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
Common::SetCurrentThreadName("HostTiming"); Common::SetCurrentThreadName("HostTiming");
Common::SetCurrentThreadPriority(Common::ThreadPriority::High); Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
on_thread_init(); on_thread_init();
has_started = true;
// base frequency in MHz: 1ns (10^-9) = 1GHz (10^9) // base frequency in MHz: 1ns (10^-9) = 1GHz (10^9)
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
while (!paused && !stop_token.stop_requested()) { while (!paused && !stop_token.stop_requested()) {
@ -77,8 +70,8 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
// continue. // continue.
wait_set = true; wait_set = true;
event.Wait(); event.Wait();
wait_set = false;
} }
wait_set = false;
} }
paused_set = true; paused_set = true;
pause_event.Wait(); pause_event.Wait();
@ -144,39 +137,28 @@ void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
event.Set(); event.Set();
} }
void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, std::chrono::nanoseconds resched_time, const std::shared_ptr<EventType>& event_type, bool absolute_time) {
std::chrono::nanoseconds resched_time,
const std::shared_ptr<EventType>& event_type,
bool absolute_time) {
{ {
std::scoped_lock scope{basic_lock}; std::scoped_lock scope{basic_lock};
const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time}; const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time};
auto h = event_queue.emplace(Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()});
auto h{event_queue.emplace(
Event{next_time.count(), event_fifo_id++, event_type, resched_time.count()})};
(*h).handle = h; (*h).handle = h;
} }
event.Set(); event.Set();
} }
void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, UnscheduleEventType type) {
UnscheduleEventType type) {
{ {
std::scoped_lock lk{basic_lock}; std::scoped_lock lk{basic_lock};
std::vector<heap_t::handle_type> to_remove; std::vector<heap_t::handle_type> to_remove;
for (auto itr = event_queue.begin(); itr != event_queue.end(); itr++) { for (auto it = event_queue.begin(); it != event_queue.end(); it++) {
const Event& e = *itr; auto const& e = *it;
if (e.type.lock().get() == event_type.get()) { if (e.type.lock().get() == event_type.get()) {
to_remove.push_back(itr->handle); to_remove.push_back(it->handle);
} }
} }
for (auto& h : to_remove)
for (auto& h : to_remove) {
event_queue.erase(h); event_queue.erase(h);
}
event_type->sequence_number++; event_type->sequence_number++;
} }
@ -187,16 +169,15 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
} }
static u64 GetNextTickCount(u64 next_ticks) { static u64 GetNextTickCount(u64 next_ticks) {
if (Settings::values.use_custom_cpu_ticks.GetValue()) { if (Settings::values.use_custom_cpu_ticks.GetValue())
return Settings::values.cpu_ticks.GetValue(); return Settings::values.cpu_ticks.GetValue();
}
return next_ticks; return next_ticks;
} }
void CoreTiming::AddTicks(u64 ticks_to_add) { void CoreTiming::AddTicks(u64 ticks_to_add) {
const u64 ticks = GetNextTickCount(ticks_to_add); const u64 ticks = GetNextTickCount(ticks_to_add);
cpu_ticks += ticks; cpu_ticks += ticks;
downcount -= static_cast<s64>(ticks); downcount -= s64(ticks);
} }
void CoreTiming::Idle() { void CoreTiming::Idle() {
@ -270,19 +251,14 @@ std::optional<s64> CoreTiming::Advance() {
next_time = pause_end_time + next_schedule_time; next_time = pause_end_time + next_schedule_time;
} }
event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type, event_queue.update(evt.handle, Event{next_time, event_fifo_id++, evt.type, next_schedule_time, evt.handle});
next_schedule_time, evt.handle});
} }
} }
global_timer = GetGlobalTimeNs().count(); global_timer = GetGlobalTimeNs().count();
} }
if (!event_queue.empty()) { return event_queue.empty() ? std::optional<s64>{} : event_queue.top().time;
return event_queue.top().time;
} else {
return std::nullopt;
}
} }
void CoreTiming::Reset() { void CoreTiming::Reset() {
@ -293,7 +269,6 @@ void CoreTiming::Reset() {
timer_thread.request_stop(); timer_thread.request_stop();
timer_thread.join(); timer_thread.join();
} }
has_started = false;
} }
/// @brief Returns current time in nanoseconds. /// @brief Returns current time in nanoseconds.
@ -310,10 +285,4 @@ std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const noexcept {
: std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)}; : std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
} }
#ifdef _WIN32
void CoreTiming::SetTimerResolutionNs(std::chrono::nanoseconds ns) {
timer_resolution_ns = ns.count();
}
#endif
} // namespace Core::Timing } // namespace Core::Timing

View File

@ -29,8 +29,7 @@ using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>(
/// Contains the characteristics of a particular event. /// Contains the characteristics of a particular event.
struct EventType { struct EventType {
explicit EventType(TimedCallback&& callback_, std::string&& name_) explicit EventType(TimedCallback&& callback_, std::string&& name_) : callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
: callback{std::move(callback_)}, name{std::move(name_)}, sequence_number{0} {}
/// The event's callback function. /// The event's callback function.
TimedCallback callback; TimedCallback callback;
@ -90,11 +89,6 @@ public:
/// Checks if core timing is running. /// Checks if core timing is running.
bool IsRunning() const; bool IsRunning() const;
/// Checks if the timer thread has started.
bool HasStarted() const {
return has_started;
}
/// Checks if there are any pending time events. /// Checks if there are any pending time events.
bool HasPendingEvents() const; bool HasPendingEvents() const;
@ -134,45 +128,29 @@ public:
/// Checks for events manually and returns time in nanoseconds for next event, threadsafe. /// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
std::optional<s64> Advance(); std::optional<s64> Advance();
#ifdef _WIN32
void SetTimerResolutionNs(std::chrono::nanoseconds ns);
#endif
struct Event; struct Event;
void Reset(); void Reset();
using heap_t = boost::heap::fibonacci_heap<CoreTiming::Event, boost::heap::compare<std::greater<>>>; using heap_t = boost::heap::fibonacci_heap<CoreTiming::Event, boost::heap::compare<std::greater<>>>;
Common::Event event{};
Common::Event pause_event{};
alignas(64) mutable std::mutex basic_lock;
alignas(64) std::mutex advance_lock;
alignas(64) std::atomic<bool> paused{};
alignas(64) std::atomic<bool> paused_set{};
alignas(64) std::atomic<bool> wait_set{};
std::function<void()> on_thread_init{};
heap_t event_queue; heap_t event_queue;
std::jthread timer_thread;
s64 global_timer = 0; s64 global_timer = 0;
#ifdef _WIN32
s64 timer_resolution_ns;
#endif
u64 event_fifo_id = 0; u64 event_fifo_id = 0;
s64 pause_end_time{}; s64 pause_end_time{};
/// Cycle timing /// Cycle timing
u64 cpu_ticks{}; u64 cpu_ticks{};
s64 downcount{}; s64 downcount{};
Common::Event event{};
Common::Event pause_event{};
std::function<void()> on_thread_init{};
std::jthread timer_thread;
mutable std::mutex basic_lock;
std::mutex advance_lock;
std::atomic<bool> paused{};
std::atomic<bool> paused_set{};
std::atomic<bool> wait_set{};
std::atomic<bool> has_started{};
bool is_multicore{}; bool is_multicore{};
}; };
/// Creates a core timing event with the given name and callback.
///
/// @param name The name of the core timing event to create.
/// @param callback The callback to execute for the event.
///
/// @returns An EventType instance representing the created event.
///
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback);
} // namespace Core::Timing } // namespace Core::Timing

View File

@ -13,11 +13,10 @@ namespace Kernel {
void KHardwareTimer::Initialize() { void KHardwareTimer::Initialize() {
// Create the timing callback to register with CoreTiming. // Create the timing callback to register with CoreTiming.
m_event_type = Core::Timing::CreateEvent("KHardwareTimer::Callback", m_event_type = m_kernel.System().CreateEvent("KHardwareTimer::Callback", [this](s64, std::chrono::nanoseconds) {
[this](s64, std::chrono::nanoseconds) { this->DoTask();
this->DoTask(); return std::nullopt;
return std::nullopt; });
});
} }
void KHardwareTimer::Finalize() { void KHardwareTimer::Finalize() {

View File

@ -256,7 +256,7 @@ struct KernelCore::Impl {
} }
void InitializePreemption(KernelCore& kernel) { void InitializePreemption(KernelCore& kernel) {
preemption_event = Core::Timing::CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> { preemption_event = system.CreateEvent("PreemptionCallback", [this, &kernel](s64 time, std::chrono::nanoseconds) -> std::optional<std::chrono::nanoseconds> {
{ {
KScopedSchedulerLock lock(kernel); KScopedSchedulerLock lock(kernel);
global_scheduler_context->PreemptThreads(); global_scheduler_context->PreemptThreads();

View File

@ -22,16 +22,11 @@ AlarmWorker::~AlarmWorker() {
void AlarmWorker::Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m) { void AlarmWorker::Initialize(std::shared_ptr<Service::PSC::Time::ServiceManager> time_m) {
m_time_m = std::move(time_m); m_time_m = std::move(time_m);
m_timer_event = m_ctx.CreateEvent("Glue:AlarmWorker:TimerEvent"); m_timer_event = m_ctx.CreateEvent("Glue:AlarmWorker:TimerEvent");
m_timer_timing_event = Core::Timing::CreateEvent( m_timer_timing_event = m_system.CreateEvent("Glue:AlarmWorker::AlarmTimer", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
"Glue:AlarmWorker::AlarmTimer", m_timer_event->Signal();
[this](s64 time, return std::nullopt;
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { });
m_timer_event->Signal();
return std::nullopt;
});
AttachToClosestAlarmEvent(); AttachToClosestAlarmEvent();
} }

View File

@ -19,28 +19,19 @@ namespace Service::Glue::Time {
TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource, TimeWorker::TimeWorker(Core::System& system, StandardSteadyClockResource& steady_clock_resource,
FileTimestampWorker& file_timestamp_worker) FileTimestampWorker& file_timestamp_worker)
: m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent( : m_system{system}, m_ctx{m_system, "Glue:TimeWorker"}, m_event{m_ctx.CreateEvent("Glue:TimeWorker:Event")},
"Glue:TimeWorker:Event")},
m_steady_clock_resource{steady_clock_resource}, m_steady_clock_resource{steady_clock_resource},
m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent( m_file_timestamp_worker{file_timestamp_worker}, m_timer_steady_clock{m_ctx.CreateEvent("Glue:TimeWorker:SteadyClockTimerEvent")},
"Glue:TimeWorker:SteadyClockTimerEvent")},
m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")}, m_timer_file_system{m_ctx.CreateEvent("Glue:TimeWorker:FileTimeTimerEvent")},
m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} { m_alarm_worker{m_system, m_steady_clock_resource}, m_pm_state_change_handler{m_alarm_worker} {
m_timer_steady_clock_timing_event = Core::Timing::CreateEvent( m_timer_steady_clock_timing_event = m_system.CreateEvent("Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
"Time::SteadyClockEvent", m_timer_steady_clock->Signal();
[this](s64 time, return std::nullopt;
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { });
m_timer_steady_clock->Signal(); m_timer_file_system_timing_event = m_system.CreateEvent("Time::SteadyClockEvent", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
return std::nullopt; m_timer_file_system->Signal();
}); return std::nullopt;
});
m_timer_file_system_timing_event = Core::Timing::CreateEvent(
"Time::SteadyClockEvent",
[this](s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
m_timer_file_system->Signal();
return std::nullopt;
});
} }
TimeWorker::~TimeWorker() { TimeWorker::~TimeWorker() {

View File

@ -51,17 +51,12 @@ Hidbus::Hidbus(Core::System& system_)
RegisterHandlers(functions); RegisterHandlers(functions);
// Register update callbacks // Register update callbacks
hidbus_update_event = Core::Timing::CreateEvent( hidbus_update_event = system_.CreateEvent("Hidbus::UpdateCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
"Hidbus::UpdateCallback", const auto guard = LockService();
[this](s64 time, UpdateHidbus(ns_late);
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { return std::nullopt;
const auto guard = LockService(); });
UpdateHidbus(ns_late); system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns, hidbus_update_event);
return std::nullopt;
});
system_.CoreTiming().ScheduleLoopingEvent(hidbus_update_ns, hidbus_update_ns,
hidbus_update_event);
} }
Hidbus::~Hidbus() { Hidbus::~Hidbus() {

View File

@ -23,25 +23,17 @@ Conductor::Conductor(Core::System& system, Container& container, DisplayList& di
}); });
if (system.IsMulticore()) { if (system.IsMulticore()) {
m_event = Core::Timing::CreateEvent( m_event = system.CreateEvent("ScreenComposition", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
"ScreenComposition", m_signal.Set();
[this](s64 time, return std::chrono::nanoseconds(this->GetNextTicks());
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { });
m_signal.Set();
return std::chrono::nanoseconds(this->GetNextTicks());
});
system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); }); m_thread = std::jthread([this](std::stop_token token) { this->VsyncThread(token); });
} else { } else {
m_event = Core::Timing::CreateEvent( m_event = system.CreateEvent("ScreenComposition", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
"ScreenComposition", this->ProcessVsync();
[this](s64 time, return std::chrono::nanoseconds(this->GetNextTicks());
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { });
this->ProcessVsync();
return std::chrono::nanoseconds(this->GetNextTicks());
});
system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event); system.CoreTiming().ScheduleLoopingEvent(FrameNs, FrameNs, m_event);
} }
} }

View File

@ -233,12 +233,12 @@ CheatEngine::~CheatEngine() {
} }
void CheatEngine::Initialize() { void CheatEngine::Initialize() {
event = Core::Timing::CreateEvent( event = system.CreateEvent(
"CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id), "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
[this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
FrameCallback(ns_late); FrameCallback(ns_late);
return std::nullopt; return std::nullopt;
}); });
core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, event); core_timing.ScheduleLoopingEvent(CHEAT_ENGINE_NS, CHEAT_ENGINE_NS, event);
metadata.process_id = system.ApplicationProcess()->GetProcessId(); metadata.process_id = system.ApplicationProcess()->GetProcessId();

View File

@ -52,14 +52,12 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
} // Anonymous namespace } // Anonymous namespace
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) Freezer::Freezer(Core::System& system_, Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
: core_timing{core_timing_}, memory{memory_} { : core_timing{core_timing_}, memory{memory_} {
event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback", event = system_.CreateEvent("MemoryFreezer::FrameCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
[this](s64 time, std::chrono::nanoseconds ns_late) FrameCallback(ns_late);
-> std::optional<std::chrono::nanoseconds> { return std::nullopt;
FrameCallback(ns_late); });
return std::nullopt;
});
core_timing.ScheduleEvent(memory_freezer_ns, event); core_timing.ScheduleEvent(memory_freezer_ns, event);
} }

View File

@ -11,14 +11,16 @@
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
namespace Core::Timing { namespace Core {
class System;
namespace Timing {
class CoreTiming; class CoreTiming;
struct EventType; struct EventType;
} // namespace Core::Timing } // namespace Core::Timing
namespace Memory {
namespace Core::Memory {
class Memory; class Memory;
} } //namespace Core::Memory
} //namespace Core
namespace Tools { namespace Tools {
@ -38,7 +40,7 @@ public:
u64 value; u64 value;
}; };
explicit Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_); explicit Freezer(Core::System& system_, Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_);
~Freezer(); ~Freezer();
// Enables or disables the entire memory freezer. // Enables or disables the entire memory freezer.

View File

@ -56,33 +56,22 @@ ResourceManager::ResourceManager(Core::System& system_,
applet_resource = std::make_shared<AppletResource>(system); applet_resource = std::make_shared<AppletResource>(system);
// Register update callbacks // Register update callbacks
npad_update_event = Core::Timing::CreateEvent("HID::UpdatePadCallback", npad_update_event = system.CreateEvent("HID::UpdatePadCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
[this](s64 time, std::chrono::nanoseconds ns_late) UpdateNpad(ns_late);
-> std::optional<std::chrono::nanoseconds> { return std::nullopt;
UpdateNpad(ns_late); });
return std::nullopt; default_update_event = system.CreateEvent("HID::UpdateDefaultCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
}); UpdateControllers(ns_late);
default_update_event = Core::Timing::CreateEvent( return std::nullopt;
"HID::UpdateDefaultCallback", });
[this](s64 time, mouse_keyboard_update_event = system.CreateEvent("HID::UpdateMouseKeyboardCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { UpdateMouseKeyboard(ns_late);
UpdateControllers(ns_late); return std::nullopt;
return std::nullopt; });
}); motion_update_event = system.CreateEvent("HID::UpdateMotionCallback", [this](s64 time, std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
mouse_keyboard_update_event = Core::Timing::CreateEvent( UpdateMotion(ns_late);
"HID::UpdateMouseKeyboardCallback", return std::nullopt;
[this](s64 time, });
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
UpdateMouseKeyboard(ns_late);
return std::nullopt;
});
motion_update_event = Core::Timing::CreateEvent(
"HID::UpdateMotionCallback",
[this](s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
UpdateMotion(ns_late);
return std::nullopt;
});
} }
ResourceManager::~ResourceManager() { ResourceManager::~ResourceManager() {
@ -267,13 +256,11 @@ void ResourceManager::InitializeTouchScreenSampler() {
touch_screen = std::make_shared<TouchScreen>(touch_resource); touch_screen = std::make_shared<TouchScreen>(touch_resource);
gesture = std::make_shared<Gesture>(touch_resource); gesture = std::make_shared<Gesture>(touch_resource);
touch_update_event = Core::Timing::CreateEvent( touch_update_event = system.CreateEvent("HID::TouchUpdateCallback", [this](s64 time,
"HID::TouchUpdateCallback", std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
[this](s64 time, touch_resource->OnTouchUpdate(time);
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { return std::nullopt;
touch_resource->OnTouchUpdate(time); });
return std::nullopt;
});
touch_resource->SetTouchDriver(touch_driver); touch_resource->SetTouchDriver(touch_driver);
touch_resource->SetAppletResource(applet_resource, &shared_mutex); touch_resource->SetAppletResource(applet_resource, &shared_mutex);

View File

@ -266,12 +266,7 @@ void Init(QWidget* root) {
Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB});
LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB}); LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB});
#ifdef _WIN32 #ifdef _WIN32
LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(Common::Windows::SetCurrentTimerResolutionToMaximum()).count());
std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(
Common::Windows::SetCurrentTimerResolutionToMaximum())
.count());
QtCommon::system->CoreTiming().SetTimerResolutionNs(
Common::Windows::GetCurrentTimerResolution());
#endif #endif
// Remove cached contents generated during the previous session // Remove cached contents generated during the previous session

View File

@ -53,14 +53,15 @@ u64 TestTimerSpeed(Core::Timing::CoreTiming& core_timing) {
} // Anonymous namespace } // Anonymous namespace
TEST_CASE("CoreTiming[BasicOrder]", "[core]") { TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
Core::System system{};
ScopeInit guard; ScopeInit guard;
auto& core_timing = guard.core_timing; auto& core_timing = guard.core_timing;
std::vector<std::shared_ptr<Core::Timing::EventType>> events{ std::vector<std::shared_ptr<Core::Timing::EventType>> events{
Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>), system.CreateEvent("callbackA", HostCallbackTemplate<0>),
Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>), system.CreateEvent("callbackB", HostCallbackTemplate<1>),
Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>), system.CreateEvent("callbackC", HostCallbackTemplate<2>),
Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>), system.CreateEvent("callbackD", HostCallbackTemplate<3>),
Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>), system.CreateEvent("callbackE", HostCallbackTemplate<4>),
}; };
expected_callback = 0; expected_callback = 0;
@ -93,14 +94,15 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") {
} }
TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") { TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
Core::System system{};
ScopeInit guard; ScopeInit guard;
auto& core_timing = guard.core_timing; auto& core_timing = guard.core_timing;
std::vector<std::shared_ptr<Core::Timing::EventType>> events{ std::vector<std::shared_ptr<Core::Timing::EventType>> events{
Core::Timing::CreateEvent("callbackA", HostCallbackTemplate<0>), system.CreateEvent("callbackA", HostCallbackTemplate<0>),
Core::Timing::CreateEvent("callbackB", HostCallbackTemplate<1>), system.CreateEvent("callbackB", HostCallbackTemplate<1>),
Core::Timing::CreateEvent("callbackC", HostCallbackTemplate<2>), system.CreateEvent("callbackC", HostCallbackTemplate<2>),
Core::Timing::CreateEvent("callbackD", HostCallbackTemplate<3>), system.CreateEvent("callbackD", HostCallbackTemplate<3>),
Core::Timing::CreateEvent("callbackE", HostCallbackTemplate<4>), system.CreateEvent("callbackE", HostCallbackTemplate<4>),
}; };
core_timing.SyncPause(true); core_timing.SyncPause(true);

View File

@ -371,7 +371,6 @@ int main(int argc, char** argv) {
#ifdef _WIN32 #ifdef _WIN32
Common::Windows::SetCurrentTimerResolutionToMaximum(); Common::Windows::SetCurrentTimerResolutionToMaximum();
system.CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
#endif #endif
system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());