diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/audio_core/stream.cpp | 23 | ||||
| -rw-r--r-- | src/audio_core/stream.h | 10 | ||||
| -rw-r--r-- | src/core/core_timing.cpp | 15 | ||||
| -rw-r--r-- | src/core/core_timing.h | 20 | ||||
| -rw-r--r-- | src/core/hardware_interrupt_manager.cpp | 15 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/server_session.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/time_manager.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.h | 7 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 19 | ||||
| -rw-r--r-- | src/core/memory/cheat_engine.cpp | 16 | ||||
| -rw-r--r-- | src/core/memory/cheat_engine.h | 3 | ||||
| -rw-r--r-- | src/core/tools/freezer.cpp | 17 | ||||
| -rw-r--r-- | src/core/tools/freezer.h | 3 | ||||
| -rw-r--r-- | src/tests/core/core_timing.cpp | 27 |
16 files changed, 111 insertions, 100 deletions
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index aab3e979a..f80ab92e4 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp | |||
| @@ -38,7 +38,7 @@ Stream::Stream(Core::Timing::CoreTiming& core_timing, u32 sample_rate, Format fo | |||
| 38 | sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { | 38 | sink_stream{sink_stream}, core_timing{core_timing}, name{std::move(name_)} { |
| 39 | 39 | ||
| 40 | release_event = Core::Timing::CreateEvent( | 40 | release_event = Core::Timing::CreateEvent( |
| 41 | name, [this](u64 userdata, s64 cycles_late) { ReleaseActiveBuffer(cycles_late); }); | 41 | name, [this](u64, std::chrono::nanoseconds ns_late) { ReleaseActiveBuffer(ns_late); }); |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | void Stream::Play() { | 44 | void Stream::Play() { |
| @@ -59,11 +59,9 @@ Stream::State Stream::GetState() const { | |||
| 59 | return state; | 59 | return state; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | s64 Stream::GetBufferReleaseNS(const Buffer& buffer) const { | 62 | std::chrono::nanoseconds Stream::GetBufferReleaseNS(const Buffer& buffer) const { |
| 63 | const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; | 63 | const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; |
| 64 | const auto ns = | 64 | return std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate); |
| 65 | std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate); | ||
| 66 | return ns.count(); | ||
| 67 | } | 65 | } |
| 68 | 66 | ||
| 69 | static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { | 67 | static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { |
| @@ -80,7 +78,7 @@ static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) { | |||
| 80 | } | 78 | } |
| 81 | } | 79 | } |
| 82 | 80 | ||
| 83 | void Stream::PlayNextBuffer(s64 cycles_late) { | 81 | void Stream::PlayNextBuffer(std::chrono::nanoseconds ns_late) { |
| 84 | if (!IsPlaying()) { | 82 | if (!IsPlaying()) { |
| 85 | // Ensure we are in playing state before playing the next buffer | 83 | // Ensure we are in playing state before playing the next buffer |
| 86 | sink_stream.Flush(); | 84 | sink_stream.Flush(); |
| @@ -105,17 +103,18 @@ void Stream::PlayNextBuffer(s64 cycles_late) { | |||
| 105 | 103 | ||
| 106 | sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); | 104 | sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples()); |
| 107 | 105 | ||
| 108 | core_timing.ScheduleEvent( | 106 | const auto time_stretch_delta = Settings::values.enable_audio_stretching.GetValue() |
| 109 | GetBufferReleaseNS(*active_buffer) - | 107 | ? std::chrono::nanoseconds::zero() |
| 110 | (Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late), | 108 | : ns_late; |
| 111 | release_event, {}); | 109 | const auto future_time = GetBufferReleaseNS(*active_buffer) - time_stretch_delta; |
| 110 | core_timing.ScheduleEvent(future_time, release_event, {}); | ||
| 112 | } | 111 | } |
| 113 | 112 | ||
| 114 | void Stream::ReleaseActiveBuffer(s64 cycles_late) { | 113 | void Stream::ReleaseActiveBuffer(std::chrono::nanoseconds ns_late) { |
| 115 | ASSERT(active_buffer); | 114 | ASSERT(active_buffer); |
| 116 | released_buffers.push(std::move(active_buffer)); | 115 | released_buffers.push(std::move(active_buffer)); |
| 117 | release_callback(); | 116 | release_callback(); |
| 118 | PlayNextBuffer(cycles_late); | 117 | PlayNextBuffer(ns_late); |
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | bool Stream::QueueBuffer(BufferPtr&& buffer) { | 120 | bool Stream::QueueBuffer(BufferPtr&& buffer) { |
diff --git a/src/audio_core/stream.h b/src/audio_core/stream.h index 524376257..6437b8591 100644 --- a/src/audio_core/stream.h +++ b/src/audio_core/stream.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <chrono> | ||
| 7 | #include <functional> | 8 | #include <functional> |
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <string> | 10 | #include <string> |
| @@ -90,16 +91,13 @@ public: | |||
| 90 | 91 | ||
| 91 | private: | 92 | private: |
| 92 | /// Plays the next queued buffer in the audio stream, starting playback if necessary | 93 | /// Plays the next queued buffer in the audio stream, starting playback if necessary |
| 93 | void PlayNextBuffer(s64 cycles_late = 0); | 94 | void PlayNextBuffer(std::chrono::nanoseconds ns_late = {}); |
| 94 | 95 | ||
| 95 | /// Releases the actively playing buffer, signalling that it has been completed | 96 | /// Releases the actively playing buffer, signalling that it has been completed |
| 96 | void ReleaseActiveBuffer(s64 cycles_late = 0); | 97 | void ReleaseActiveBuffer(std::chrono::nanoseconds ns_late = {}); |
| 97 | 98 | ||
| 98 | /// Gets the number of core cycles when the specified buffer will be released | 99 | /// Gets the number of core cycles when the specified buffer will be released |
| 99 | s64 GetBufferReleaseNS(const Buffer& buffer) const; | 100 | std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const; |
| 100 | |||
| 101 | /// Gets the number of core cycles when the specified buffer will be released | ||
| 102 | s64 GetBufferReleaseNSHostTiming(const Buffer& buffer) const; | ||
| 103 | 101 | ||
| 104 | u32 sample_rate; ///< Sample rate of the stream | 102 | u32 sample_rate; ///< Sample rate of the stream |
| 105 | Format format; ///< Format of the stream | 103 | Format format; ///< Format of the stream |
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index a63e60461..b5feb3f24 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -53,12 +53,12 @@ void CoreTiming::ThreadEntry(CoreTiming& instance) { | |||
| 53 | instance.ThreadLoop(); | 53 | instance.ThreadLoop(); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | void CoreTiming::Initialize(std::function<void(void)>&& on_thread_init_) { | 56 | void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { |
| 57 | on_thread_init = std::move(on_thread_init_); | 57 | on_thread_init = std::move(on_thread_init_); |
| 58 | event_fifo_id = 0; | 58 | event_fifo_id = 0; |
| 59 | shutting_down = false; | 59 | shutting_down = false; |
| 60 | ticks = 0; | 60 | ticks = 0; |
| 61 | const auto empty_timed_callback = [](u64, s64) {}; | 61 | const auto empty_timed_callback = [](u64, std::chrono::nanoseconds) {}; |
| 62 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); | 62 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); |
| 63 | if (is_multicore) { | 63 | if (is_multicore) { |
| 64 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); | 64 | timer_thread = std::make_unique<std::thread>(ThreadEntry, std::ref(*this)); |
| @@ -106,11 +106,11 @@ bool CoreTiming::HasPendingEvents() const { | |||
| 106 | return !(wait_set && event_queue.empty()); | 106 | return !(wait_set && event_queue.empty()); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void CoreTiming::ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type, | 109 | void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
| 110 | u64 userdata) { | 110 | const std::shared_ptr<EventType>& event_type, u64 userdata) { |
| 111 | { | 111 | { |
| 112 | std::scoped_lock scope{basic_lock}; | 112 | std::scoped_lock scope{basic_lock}; |
| 113 | const u64 timeout = static_cast<u64>(GetGlobalTimeNs().count() + ns_into_future); | 113 | const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count()); |
| 114 | 114 | ||
| 115 | event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); | 115 | event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type}); |
| 116 | 116 | ||
| @@ -195,8 +195,9 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 195 | event_queue.pop_back(); | 195 | event_queue.pop_back(); |
| 196 | basic_lock.unlock(); | 196 | basic_lock.unlock(); |
| 197 | 197 | ||
| 198 | if (auto event_type{evt.type.lock()}) { | 198 | if (const auto event_type{evt.type.lock()}) { |
| 199 | event_type->callback(evt.userdata, global_timer - evt.time); | 199 | event_type->callback( |
| 200 | evt.userdata, std::chrono::nanoseconds{static_cast<s64>(global_timer - evt.time)}); | ||
| 200 | } | 201 | } |
| 201 | 202 | ||
| 202 | basic_lock.lock(); | 203 | basic_lock.lock(); |
diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 72faaab64..120c74e46 100644 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h | |||
| @@ -17,14 +17,12 @@ | |||
| 17 | #include "common/common_types.h" | 17 | #include "common/common_types.h" |
| 18 | #include "common/spin_lock.h" | 18 | #include "common/spin_lock.h" |
| 19 | #include "common/thread.h" | 19 | #include "common/thread.h" |
| 20 | #include "common/threadsafe_queue.h" | ||
| 21 | #include "common/wall_clock.h" | 20 | #include "common/wall_clock.h" |
| 22 | #include "core/hardware_properties.h" | ||
| 23 | 21 | ||
| 24 | namespace Core::Timing { | 22 | namespace Core::Timing { |
| 25 | 23 | ||
| 26 | /// A callback that may be scheduled for a particular core timing event. | 24 | /// A callback that may be scheduled for a particular core timing event. |
| 27 | using TimedCallback = std::function<void(u64 userdata, s64 cycles_late)>; | 25 | using TimedCallback = std::function<void(u64 userdata, std::chrono::nanoseconds ns_late)>; |
| 28 | 26 | ||
| 29 | /// Contains the characteristics of a particular event. | 27 | /// Contains the characteristics of a particular event. |
| 30 | struct EventType { | 28 | struct EventType { |
| @@ -42,12 +40,12 @@ struct EventType { | |||
| 42 | * in main CPU clock cycles. | 40 | * in main CPU clock cycles. |
| 43 | * | 41 | * |
| 44 | * To schedule an event, you first have to register its type. This is where you pass in the | 42 | * To schedule an event, you first have to register its type. This is where you pass in the |
| 45 | * callback. You then schedule events using the type id you get back. | 43 | * callback. You then schedule events using the type ID you get back. |
| 46 | * | 44 | * |
| 47 | * The int cyclesLate that the callbacks get is how many cycles late it was. | 45 | * The s64 ns_late that the callbacks get is how many ns late it was. |
| 48 | * So to schedule a new event on a regular basis: | 46 | * So to schedule a new event on a regular basis: |
| 49 | * inside callback: | 47 | * inside callback: |
| 50 | * ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever") | 48 | * ScheduleEvent(period_in_ns - ns_late, callback, "whatever") |
| 51 | */ | 49 | */ |
| 52 | class CoreTiming { | 50 | class CoreTiming { |
| 53 | public: | 51 | public: |
| @@ -62,7 +60,7 @@ public: | |||
| 62 | 60 | ||
| 63 | /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is | 61 | /// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is |
| 64 | /// required to end slice - 1 and start slice 0 before the first cycle of code is executed. | 62 | /// required to end slice - 1 and start slice 0 before the first cycle of code is executed. |
| 65 | void Initialize(std::function<void(void)>&& on_thread_init_); | 63 | void Initialize(std::function<void()>&& on_thread_init_); |
| 66 | 64 | ||
| 67 | /// Tears down all timing related functionality. | 65 | /// Tears down all timing related functionality. |
| 68 | void Shutdown(); | 66 | void Shutdown(); |
| @@ -95,8 +93,8 @@ public: | |||
| 95 | bool HasPendingEvents() const; | 93 | bool HasPendingEvents() const; |
| 96 | 94 | ||
| 97 | /// Schedules an event in core timing | 95 | /// Schedules an event in core timing |
| 98 | void ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type, | 96 | void ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
| 99 | u64 userdata = 0); | 97 | const std::shared_ptr<EventType>& event_type, u64 userdata = 0); |
| 100 | 98 | ||
| 101 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata); | 99 | void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata); |
| 102 | 100 | ||
| @@ -141,8 +139,6 @@ private: | |||
| 141 | 139 | ||
| 142 | u64 global_timer = 0; | 140 | u64 global_timer = 0; |
| 143 | 141 | ||
| 144 | std::chrono::nanoseconds start_point; | ||
| 145 | |||
| 146 | // The queue is a min-heap using std::make_heap/push_heap/pop_heap. | 142 | // The queue is a min-heap using std::make_heap/push_heap/pop_heap. |
| 147 | // We don't use std::priority_queue because we need to be able to serialize, unserialize and | 143 | // We don't use std::priority_queue because we need to be able to serialize, unserialize and |
| 148 | // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't | 144 | // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't |
| @@ -161,7 +157,7 @@ private: | |||
| 161 | std::atomic<bool> wait_set{}; | 157 | std::atomic<bool> wait_set{}; |
| 162 | std::atomic<bool> shutting_down{}; | 158 | std::atomic<bool> shutting_down{}; |
| 163 | std::atomic<bool> has_started{}; | 159 | std::atomic<bool> has_started{}; |
| 164 | std::function<void(void)> on_thread_init{}; | 160 | std::function<void()> on_thread_init{}; |
| 165 | 161 | ||
| 166 | bool is_multicore{}; | 162 | bool is_multicore{}; |
| 167 | 163 | ||
diff --git a/src/core/hardware_interrupt_manager.cpp b/src/core/hardware_interrupt_manager.cpp index c629d9fa1..efc1030c1 100644 --- a/src/core/hardware_interrupt_manager.cpp +++ b/src/core/hardware_interrupt_manager.cpp | |||
| @@ -11,19 +11,20 @@ | |||
| 11 | namespace Core::Hardware { | 11 | namespace Core::Hardware { |
| 12 | 12 | ||
| 13 | InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { | 13 | InterruptManager::InterruptManager(Core::System& system_in) : system(system_in) { |
| 14 | gpu_interrupt_event = Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, s64) { | 14 | gpu_interrupt_event = |
| 15 | auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); | 15 | Core::Timing::CreateEvent("GPUInterrupt", [this](u64 message, std::chrono::nanoseconds) { |
| 16 | const u32 syncpt = static_cast<u32>(message >> 32); | 16 | auto nvdrv = system.ServiceManager().GetService<Service::Nvidia::NVDRV>("nvdrv"); |
| 17 | const u32 value = static_cast<u32>(message); | 17 | const u32 syncpt = static_cast<u32>(message >> 32); |
| 18 | nvdrv->SignalGPUInterruptSyncpt(syncpt, value); | 18 | const u32 value = static_cast<u32>(message); |
| 19 | }); | 19 | nvdrv->SignalGPUInterruptSyncpt(syncpt, value); |
| 20 | }); | ||
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | InterruptManager::~InterruptManager() = default; | 23 | InterruptManager::~InterruptManager() = default; |
| 23 | 24 | ||
| 24 | void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { | 25 | void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) { |
| 25 | const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value; | 26 | const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value; |
| 26 | system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, msg); | 27 | system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{10}, gpu_interrupt_event, msg); |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | } // namespace Core::Hardware | 30 | } // namespace Core::Hardware |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index e1c7a0f3b..8dd4a2637 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -145,16 +145,18 @@ struct KernelCore::Impl { | |||
| 145 | 145 | ||
| 146 | void InitializePreemption(KernelCore& kernel) { | 146 | void InitializePreemption(KernelCore& kernel) { |
| 147 | preemption_event = Core::Timing::CreateEvent( | 147 | preemption_event = Core::Timing::CreateEvent( |
| 148 | "PreemptionCallback", [this, &kernel](u64 userdata, s64 cycles_late) { | 148 | "PreemptionCallback", [this, &kernel](u64, std::chrono::nanoseconds) { |
| 149 | { | 149 | { |
| 150 | SchedulerLock lock(kernel); | 150 | SchedulerLock lock(kernel); |
| 151 | global_scheduler.PreemptThreads(); | 151 | global_scheduler.PreemptThreads(); |
| 152 | } | 152 | } |
| 153 | s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); | 153 | const auto time_interval = std::chrono::nanoseconds{ |
| 154 | Core::Timing::msToCycles(std::chrono::milliseconds(10))}; | ||
| 154 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); | 155 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); |
| 155 | }); | 156 | }); |
| 156 | 157 | ||
| 157 | s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10)); | 158 | const auto time_interval = |
| 159 | std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))}; | ||
| 158 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); | 160 | system.CoreTiming().ScheduleEvent(time_interval, preemption_event); |
| 159 | } | 161 | } |
| 160 | 162 | ||
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 7b23a6889..af22f4c33 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp | |||
| @@ -34,7 +34,7 @@ ResultVal<std::shared_ptr<ServerSession>> ServerSession::Create(KernelCore& kern | |||
| 34 | std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; | 34 | std::shared_ptr<ServerSession> session{std::make_shared<ServerSession>(kernel)}; |
| 35 | 35 | ||
| 36 | session->request_event = Core::Timing::CreateEvent( | 36 | session->request_event = Core::Timing::CreateEvent( |
| 37 | name, [session](u64 userdata, s64 cycles_late) { session->CompleteSyncRequest(); }); | 37 | name, [session](u64, std::chrono::nanoseconds) { session->CompleteSyncRequest(); }); |
| 38 | session->name = std::move(name); | 38 | session->name = std::move(name); |
| 39 | session->parent = std::move(parent); | 39 | session->parent = std::move(parent); |
| 40 | 40 | ||
| @@ -184,8 +184,8 @@ ResultCode ServerSession::CompleteSyncRequest() { | |||
| 184 | 184 | ||
| 185 | ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, | 185 | ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread, |
| 186 | Core::Memory::Memory& memory) { | 186 | Core::Memory::Memory& memory) { |
| 187 | ResultCode result = QueueSyncRequest(std::move(thread), memory); | 187 | const ResultCode result = QueueSyncRequest(std::move(thread), memory); |
| 188 | const u64 delay = kernel.IsMulticore() ? 0U : 20000U; | 188 | const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000}; |
| 189 | Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {}); | 189 | Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {}); |
| 190 | return result; | 190 | return result; |
| 191 | } | 191 | } |
diff --git a/src/core/hle/kernel/time_manager.cpp b/src/core/hle/kernel/time_manager.cpp index 941305e8e..88b01b751 100644 --- a/src/core/hle/kernel/time_manager.cpp +++ b/src/core/hle/kernel/time_manager.cpp | |||
| @@ -16,7 +16,7 @@ namespace Kernel { | |||
| 16 | 16 | ||
| 17 | TimeManager::TimeManager(Core::System& system_) : system{system_} { | 17 | TimeManager::TimeManager(Core::System& system_) : system{system_} { |
| 18 | time_manager_event_type = Core::Timing::CreateEvent( | 18 | time_manager_event_type = Core::Timing::CreateEvent( |
| 19 | "Kernel::TimeManagerCallback", [this](u64 thread_handle, [[maybe_unused]] s64 cycles_late) { | 19 | "Kernel::TimeManagerCallback", [this](u64 thread_handle, std::chrono::nanoseconds) { |
| 20 | SchedulerLock lock(system.Kernel()); | 20 | SchedulerLock lock(system.Kernel()); |
| 21 | Handle proper_handle = static_cast<Handle>(thread_handle); | 21 | Handle proper_handle = static_cast<Handle>(thread_handle); |
| 22 | if (cancelled_events[proper_handle]) { | 22 | if (cancelled_events[proper_handle]) { |
| @@ -34,7 +34,8 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64 | |||
| 34 | ASSERT(timetask); | 34 | ASSERT(timetask); |
| 35 | ASSERT(timetask->GetStatus() != ThreadStatus::Ready); | 35 | ASSERT(timetask->GetStatus() != ThreadStatus::Ready); |
| 36 | ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex); | 36 | ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex); |
| 37 | system.CoreTiming().ScheduleEvent(nanoseconds, time_manager_event_type, event_handle); | 37 | system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds}, |
| 38 | time_manager_event_type, event_handle); | ||
| 38 | } else { | 39 | } else { |
| 39 | event_handle = InvalidHandle; | 40 | event_handle = InvalidHandle; |
| 40 | } | 41 | } |
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index e9020e0dc..680290cbd 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -39,9 +39,10 @@ namespace Service::HID { | |||
| 39 | 39 | ||
| 40 | // Updating period for each HID device. | 40 | // Updating period for each HID device. |
| 41 | // TODO(ogniK): Find actual polling rate of hid | 41 | // TODO(ogniK): Find actual polling rate of hid |
| 42 | constexpr s64 pad_update_ticks = static_cast<s64>(1000000000 / 66); | 42 | constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66}; |
| 43 | [[maybe_unused]] constexpr s64 accelerometer_update_ticks = static_cast<s64>(1000000000 / 100); | 43 | [[maybe_unused]] constexpr auto accelerometer_update_ns = |
| 44 | [[maybe_unused]] constexpr s64 gyroscope_update_ticks = static_cast<s64>(1000000000 / 100); | 44 | std::chrono::nanoseconds{1000000000 / 100}; |
| 45 | [[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100}; | ||
| 45 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; | 46 | constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; |
| 46 | 47 | ||
| 47 | IAppletResource::IAppletResource(Core::System& system) | 48 | IAppletResource::IAppletResource(Core::System& system) |
| @@ -75,14 +76,14 @@ IAppletResource::IAppletResource(Core::System& system) | |||
| 75 | GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000); | 76 | GetController<Controller_Stubbed>(HidController::Unknown3).SetCommonHeaderOffset(0x5000); |
| 76 | 77 | ||
| 77 | // Register update callbacks | 78 | // Register update callbacks |
| 78 | pad_update_event = | 79 | pad_update_event = Core::Timing::CreateEvent( |
| 79 | Core::Timing::CreateEvent("HID::UpdatePadCallback", [this](u64 userdata, s64 ns_late) { | 80 | "HID::UpdatePadCallback", [this](u64 userdata, std::chrono::nanoseconds ns_late) { |
| 80 | UpdateControllers(userdata, ns_late); | 81 | UpdateControllers(userdata, ns_late); |
| 81 | }); | 82 | }); |
| 82 | 83 | ||
| 83 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) | 84 | // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) |
| 84 | 85 | ||
| 85 | system.CoreTiming().ScheduleEvent(pad_update_ticks, pad_update_event); | 86 | system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event); |
| 86 | 87 | ||
| 87 | ReloadInputDevices(); | 88 | ReloadInputDevices(); |
| 88 | } | 89 | } |
| @@ -107,7 +108,7 @@ void IAppletResource::GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { | |||
| 107 | rb.PushCopyObjects(shared_mem); | 108 | rb.PushCopyObjects(shared_mem); |
| 108 | } | 109 | } |
| 109 | 110 | ||
| 110 | void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) { | 111 | void IAppletResource::UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late) { |
| 111 | auto& core_timing = system.CoreTiming(); | 112 | auto& core_timing = system.CoreTiming(); |
| 112 | 113 | ||
| 113 | const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); | 114 | const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); |
| @@ -118,7 +119,7 @@ void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) { | |||
| 118 | controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); | 119 | controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE); |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | core_timing.ScheduleEvent(pad_update_ticks - ns_late, pad_update_event); | 122 | core_timing.ScheduleEvent(pad_update_ns - ns_late, pad_update_event); |
| 122 | } | 123 | } |
| 123 | 124 | ||
| 124 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { | 125 | class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> { |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 6fb048360..c6f0a2584 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -4,10 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/service/hid/controllers/controller_base.h" | 7 | #include <chrono> |
| 8 | #include "core/hle/service/service.h" | ||
| 9 | 8 | ||
| 10 | #include "controllers/controller_base.h" | 9 | #include "core/hle/service/hid/controllers/controller_base.h" |
| 11 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 12 | 11 | ||
| 13 | namespace Core::Timing { | 12 | namespace Core::Timing { |
| @@ -65,7 +64,7 @@ private: | |||
| 65 | } | 64 | } |
| 66 | 65 | ||
| 67 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); | 66 | void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx); |
| 68 | void UpdateControllers(u64 userdata, s64 cycles_late); | 67 | void UpdateControllers(u64 userdata, std::chrono::nanoseconds ns_late); |
| 69 | 68 | ||
| 70 | std::shared_ptr<Kernel::SharedMemory> shared_mem; | 69 | std::shared_ptr<Kernel::SharedMemory> shared_mem; |
| 71 | 70 | ||
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 2f44d3779..789856118 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -28,8 +28,7 @@ | |||
| 28 | 28 | ||
| 29 | namespace Service::NVFlinger { | 29 | namespace Service::NVFlinger { |
| 30 | 30 | ||
| 31 | constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60); | 31 | constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60}; |
| 32 | constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30); | ||
| 33 | 32 | ||
| 34 | void NVFlinger::VSyncThread(NVFlinger& nv_flinger) { | 33 | void NVFlinger::VSyncThread(NVFlinger& nv_flinger) { |
| 35 | nv_flinger.SplitVSync(); | 34 | nv_flinger.SplitVSync(); |
| @@ -67,20 +66,24 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) { | |||
| 67 | guard = std::make_shared<std::mutex>(); | 66 | guard = std::make_shared<std::mutex>(); |
| 68 | 67 | ||
| 69 | // Schedule the screen composition events | 68 | // Schedule the screen composition events |
| 70 | composition_event = | 69 | composition_event = Core::Timing::CreateEvent( |
| 71 | Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) { | 70 | "ScreenComposition", [this](u64, std::chrono::nanoseconds ns_late) { |
| 72 | Lock(); | 71 | Lock(); |
| 73 | Compose(); | 72 | Compose(); |
| 74 | const auto ticks = GetNextTicks(); | 73 | |
| 75 | this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late), | 74 | const auto ticks = std::chrono::nanoseconds{GetNextTicks()}; |
| 76 | composition_event); | 75 | const auto ticks_delta = ticks - ns_late; |
| 76 | const auto future_ns = std::max(std::chrono::nanoseconds::zero(), ticks_delta); | ||
| 77 | |||
| 78 | this->system.CoreTiming().ScheduleEvent(future_ns, composition_event); | ||
| 77 | }); | 79 | }); |
| 80 | |||
| 78 | if (system.IsMulticore()) { | 81 | if (system.IsMulticore()) { |
| 79 | is_running = true; | 82 | is_running = true; |
| 80 | wait_event = std::make_unique<Common::Event>(); | 83 | wait_event = std::make_unique<Common::Event>(); |
| 81 | vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this)); | 84 | vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this)); |
| 82 | } else { | 85 | } else { |
| 83 | system.CoreTiming().ScheduleEvent(frame_ticks, composition_event); | 86 | system.CoreTiming().ScheduleEvent(frame_ns, composition_event); |
| 84 | } | 87 | } |
| 85 | } | 88 | } |
| 86 | 89 | ||
diff --git a/src/core/memory/cheat_engine.cpp b/src/core/memory/cheat_engine.cpp index 53d27859b..ced41b1fe 100644 --- a/src/core/memory/cheat_engine.cpp +++ b/src/core/memory/cheat_engine.cpp | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | 20 | ||
| 21 | namespace Core::Memory { | 21 | namespace Core::Memory { |
| 22 | 22 | ||
| 23 | constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(1000000000 / 12); | 23 | constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12}; |
| 24 | constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; | 24 | constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF; |
| 25 | 25 | ||
| 26 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) | 26 | StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata) |
| @@ -188,10 +188,12 @@ CheatEngine::~CheatEngine() { | |||
| 188 | } | 188 | } |
| 189 | 189 | ||
| 190 | void CheatEngine::Initialize() { | 190 | void CheatEngine::Initialize() { |
| 191 | event = Core::Timing::CreateEvent( | 191 | event = Core::Timing::CreateEvent("CheatEngine::FrameCallback::" + |
| 192 | "CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id), | 192 | Common::HexToString(metadata.main_nso_build_id), |
| 193 | [this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); }); | 193 | [this](u64 userdata, std::chrono::nanoseconds ns_late) { |
| 194 | core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event); | 194 | FrameCallback(userdata, ns_late); |
| 195 | }); | ||
| 196 | core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event); | ||
| 195 | 197 | ||
| 196 | metadata.process_id = system.CurrentProcess()->GetProcessID(); | 198 | metadata.process_id = system.CurrentProcess()->GetProcessID(); |
| 197 | metadata.title_id = system.CurrentProcess()->GetTitleID(); | 199 | metadata.title_id = system.CurrentProcess()->GetTitleID(); |
| @@ -217,7 +219,7 @@ void CheatEngine::Reload(std::vector<CheatEntry> cheats) { | |||
| 217 | 219 | ||
| 218 | MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); | 220 | MICROPROFILE_DEFINE(Cheat_Engine, "Add-Ons", "Cheat Engine", MP_RGB(70, 200, 70)); |
| 219 | 221 | ||
| 220 | void CheatEngine::FrameCallback(u64 userdata, s64 ns_late) { | 222 | void CheatEngine::FrameCallback(u64, std::chrono::nanoseconds ns_late) { |
| 221 | if (is_pending_reload.exchange(false)) { | 223 | if (is_pending_reload.exchange(false)) { |
| 222 | vm.LoadProgram(cheats); | 224 | vm.LoadProgram(cheats); |
| 223 | } | 225 | } |
| @@ -230,7 +232,7 @@ void CheatEngine::FrameCallback(u64 userdata, s64 ns_late) { | |||
| 230 | 232 | ||
| 231 | vm.Execute(metadata); | 233 | vm.Execute(metadata); |
| 232 | 234 | ||
| 233 | core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - ns_late, event); | 235 | core_timing.ScheduleEvent(CHEAT_ENGINE_NS - ns_late, event); |
| 234 | } | 236 | } |
| 235 | 237 | ||
| 236 | } // namespace Core::Memory | 238 | } // namespace Core::Memory |
diff --git a/src/core/memory/cheat_engine.h b/src/core/memory/cheat_engine.h index 2649423f8..d4068cf84 100644 --- a/src/core/memory/cheat_engine.h +++ b/src/core/memory/cheat_engine.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <chrono> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| @@ -71,7 +72,7 @@ public: | |||
| 71 | void Reload(std::vector<CheatEntry> cheats); | 72 | void Reload(std::vector<CheatEntry> cheats); |
| 72 | 73 | ||
| 73 | private: | 74 | private: |
| 74 | void FrameCallback(u64 userdata, s64 cycles_late); | 75 | void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); |
| 75 | 76 | ||
| 76 | DmntCheatVm vm; | 77 | DmntCheatVm vm; |
| 77 | CheatProcessMetadata metadata; | 78 | CheatProcessMetadata metadata; |
diff --git a/src/core/tools/freezer.cpp b/src/core/tools/freezer.cpp index 8b0c50d11..27b894b51 100644 --- a/src/core/tools/freezer.cpp +++ b/src/core/tools/freezer.cpp | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | namespace Tools { | 14 | namespace Tools { |
| 15 | namespace { | 15 | namespace { |
| 16 | 16 | ||
| 17 | constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(1000000000 / 60); | 17 | constexpr auto memory_freezer_ns = std::chrono::nanoseconds{1000000000 / 60}; |
| 18 | 18 | ||
| 19 | u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) { | 19 | u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) { |
| 20 | switch (width) { | 20 | switch (width) { |
| @@ -55,10 +55,11 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v | |||
| 55 | 55 | ||
| 56 | Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) | 56 | Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) |
| 57 | : core_timing{core_timing_}, memory{memory_} { | 57 | : core_timing{core_timing_}, memory{memory_} { |
| 58 | event = Core::Timing::CreateEvent( | 58 | event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback", |
| 59 | "MemoryFreezer::FrameCallback", | 59 | [this](u64 userdata, std::chrono::nanoseconds ns_late) { |
| 60 | [this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); }); | 60 | FrameCallback(userdata, ns_late); |
| 61 | core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event); | 61 | }); |
| 62 | core_timing.ScheduleEvent(memory_freezer_ns, event); | ||
| 62 | } | 63 | } |
| 63 | 64 | ||
| 64 | Freezer::~Freezer() { | 65 | Freezer::~Freezer() { |
| @@ -68,7 +69,7 @@ Freezer::~Freezer() { | |||
| 68 | void Freezer::SetActive(bool active) { | 69 | void Freezer::SetActive(bool active) { |
| 69 | if (!this->active.exchange(active)) { | 70 | if (!this->active.exchange(active)) { |
| 70 | FillEntryReads(); | 71 | FillEntryReads(); |
| 71 | core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event); | 72 | core_timing.ScheduleEvent(memory_freezer_ns, event); |
| 72 | LOG_DEBUG(Common_Memory, "Memory freezer activated!"); | 73 | LOG_DEBUG(Common_Memory, "Memory freezer activated!"); |
| 73 | } else { | 74 | } else { |
| 74 | LOG_DEBUG(Common_Memory, "Memory freezer deactivated!"); | 75 | LOG_DEBUG(Common_Memory, "Memory freezer deactivated!"); |
| @@ -158,7 +159,7 @@ std::vector<Freezer::Entry> Freezer::GetEntries() const { | |||
| 158 | return entries; | 159 | return entries; |
| 159 | } | 160 | } |
| 160 | 161 | ||
| 161 | void Freezer::FrameCallback(u64 userdata, s64 ns_late) { | 162 | void Freezer::FrameCallback(u64, std::chrono::nanoseconds ns_late) { |
| 162 | if (!IsActive()) { | 163 | if (!IsActive()) { |
| 163 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); | 164 | LOG_DEBUG(Common_Memory, "Memory freezer has been deactivated, ending callback events."); |
| 164 | return; | 165 | return; |
| @@ -173,7 +174,7 @@ void Freezer::FrameCallback(u64 userdata, s64 ns_late) { | |||
| 173 | MemoryWriteWidth(memory, entry.width, entry.address, entry.value); | 174 | MemoryWriteWidth(memory, entry.width, entry.address, entry.value); |
| 174 | } | 175 | } |
| 175 | 176 | ||
| 176 | core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS - ns_late, event); | 177 | core_timing.ScheduleEvent(memory_freezer_ns - ns_late, event); |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | void Freezer::FillEntryReads() { | 180 | void Freezer::FillEntryReads() { |
diff --git a/src/core/tools/freezer.h b/src/core/tools/freezer.h index 62fc6aa6c..8438783d5 100644 --- a/src/core/tools/freezer.h +++ b/src/core/tools/freezer.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <chrono> | ||
| 8 | #include <memory> | 9 | #include <memory> |
| 9 | #include <mutex> | 10 | #include <mutex> |
| 10 | #include <optional> | 11 | #include <optional> |
| @@ -72,7 +73,7 @@ public: | |||
| 72 | std::vector<Entry> GetEntries() const; | 73 | std::vector<Entry> GetEntries() const; |
| 73 | 74 | ||
| 74 | private: | 75 | private: |
| 75 | void FrameCallback(u64 userdata, s64 cycles_late); | 76 | void FrameCallback(u64 userdata, std::chrono::nanoseconds ns_late); |
| 76 | void FillEntryReads(); | 77 | void FillEntryReads(); |
| 77 | 78 | ||
| 78 | std::atomic_bool active{false}; | 79 | std::atomic_bool active{false}; |
diff --git a/src/tests/core/core_timing.cpp b/src/tests/core/core_timing.cpp index e66db1940..244463a47 100644 --- a/src/tests/core/core_timing.cpp +++ b/src/tests/core/core_timing.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <bitset> | 8 | #include <bitset> |
| 9 | #include <chrono> | ||
| 9 | #include <cstdlib> | 10 | #include <cstdlib> |
| 10 | #include <memory> | 11 | #include <memory> |
| 11 | #include <string> | 12 | #include <string> |
| @@ -17,7 +18,6 @@ | |||
| 17 | namespace { | 18 | namespace { |
| 18 | // Numbers are chosen randomly to make sure the correct one is given. | 19 | // Numbers are chosen randomly to make sure the correct one is given. |
| 19 | constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; | 20 | constexpr std::array<u64, 5> CB_IDS{{42, 144, 93, 1026, UINT64_C(0xFFFF7FFFF7FFFF)}}; |
| 20 | constexpr int MAX_SLICE_LENGTH = 10000; // Copied from CoreTiming internals | ||
| 21 | constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}}; | 21 | constexpr std::array<u64, 5> calls_order{{2, 0, 1, 4, 3}}; |
| 22 | std::array<s64, 5> delays{}; | 22 | std::array<s64, 5> delays{}; |
| 23 | 23 | ||
| @@ -25,12 +25,12 @@ std::bitset<CB_IDS.size()> callbacks_ran_flags; | |||
| 25 | u64 expected_callback = 0; | 25 | u64 expected_callback = 0; |
| 26 | 26 | ||
| 27 | template <unsigned int IDX> | 27 | template <unsigned int IDX> |
| 28 | void HostCallbackTemplate(u64 userdata, s64 nanoseconds_late) { | 28 | void HostCallbackTemplate(u64 userdata, std::chrono::nanoseconds ns_late) { |
| 29 | static_assert(IDX < CB_IDS.size(), "IDX out of range"); | 29 | static_assert(IDX < CB_IDS.size(), "IDX out of range"); |
| 30 | callbacks_ran_flags.set(IDX); | 30 | callbacks_ran_flags.set(IDX); |
| 31 | REQUIRE(CB_IDS[IDX] == userdata); | 31 | REQUIRE(CB_IDS[IDX] == userdata); |
| 32 | REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]); | 32 | REQUIRE(CB_IDS[IDX] == CB_IDS[calls_order[expected_callback]]); |
| 33 | delays[IDX] = nanoseconds_late; | 33 | delays[IDX] = ns_late.count(); |
| 34 | ++expected_callback; | 34 | ++expected_callback; |
| 35 | } | 35 | } |
| 36 | 36 | ||
| @@ -77,10 +77,12 @@ TEST_CASE("CoreTiming[BasicOrder]", "[core]") { | |||
| 77 | 77 | ||
| 78 | core_timing.SyncPause(true); | 78 | core_timing.SyncPause(true); |
| 79 | 79 | ||
| 80 | u64 one_micro = 1000U; | 80 | const u64 one_micro = 1000U; |
| 81 | for (std::size_t i = 0; i < events.size(); i++) { | 81 | for (std::size_t i = 0; i < events.size(); i++) { |
| 82 | u64 order = calls_order[i]; | 82 | const u64 order = calls_order[i]; |
| 83 | core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); | 83 | const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)}; |
| 84 | |||
| 85 | core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]); | ||
| 84 | } | 86 | } |
| 85 | /// test pause | 87 | /// test pause |
| 86 | REQUIRE(callbacks_ran_flags.none()); | 88 | REQUIRE(callbacks_ran_flags.none()); |
| @@ -116,13 +118,16 @@ TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") { | |||
| 116 | 118 | ||
| 117 | expected_callback = 0; | 119 | expected_callback = 0; |
| 118 | 120 | ||
| 119 | u64 start = core_timing.GetGlobalTimeNs().count(); | 121 | const u64 start = core_timing.GetGlobalTimeNs().count(); |
| 120 | u64 one_micro = 1000U; | 122 | const u64 one_micro = 1000U; |
| 123 | |||
| 121 | for (std::size_t i = 0; i < events.size(); i++) { | 124 | for (std::size_t i = 0; i < events.size(); i++) { |
| 122 | u64 order = calls_order[i]; | 125 | const u64 order = calls_order[i]; |
| 123 | core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]); | 126 | const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)}; |
| 127 | core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]); | ||
| 124 | } | 128 | } |
| 125 | u64 end = core_timing.GetGlobalTimeNs().count(); | 129 | |
| 130 | const u64 end = core_timing.GetGlobalTimeNs().count(); | ||
| 126 | const double scheduling_time = static_cast<double>(end - start); | 131 | const double scheduling_time = static_cast<double>(end - start); |
| 127 | const double timer_time = static_cast<double>(TestTimerSpeed(core_timing)); | 132 | const double timer_time = static_cast<double>(TestTimerSpeed(core_timing)); |
| 128 | 133 | ||