diff options
| author | 2022-07-10 06:59:40 +0100 | |
|---|---|---|
| committer | 2022-07-10 06:59:40 +0100 | |
| commit | 240650f6a6336df8d3eb11b410cdcd332d8ad562 (patch) | |
| tree | 16ae249e6160a22f88bd2238d43b23079c4afb44 /src/core/core_timing.cpp | |
| parent | Merge pull request #8531 from FernandoS27/core-timing-fix-reg (diff) | |
| download | yuzu-240650f6a6336df8d3eb11b410cdcd332d8ad562.tar.gz yuzu-240650f6a6336df8d3eb11b410cdcd332d8ad562.tar.xz yuzu-240650f6a6336df8d3eb11b410cdcd332d8ad562.zip | |
Rework CoreTiming
Diffstat (limited to 'src/core/core_timing.cpp')
| -rw-r--r-- | src/core/core_timing.cpp | 75 |
1 files changed, 67 insertions, 8 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 07b8e356b..5425637f5 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -22,10 +22,11 @@ std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callbac | |||
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | struct CoreTiming::Event { | 24 | struct CoreTiming::Event { |
| 25 | u64 time; | 25 | s64 time; |
| 26 | u64 fifo_order; | 26 | u64 fifo_order; |
| 27 | std::uintptr_t user_data; | 27 | std::uintptr_t user_data; |
| 28 | std::weak_ptr<EventType> type; | 28 | std::weak_ptr<EventType> type; |
| 29 | s64 reschedule_time; | ||
| 29 | 30 | ||
| 30 | // Sort by time, unless the times are the same, in which case sort by | 31 | // Sort by time, unless the times are the same, in which case sort by |
| 31 | // the order added to the queue | 32 | // the order added to the queue |
| @@ -58,7 +59,8 @@ void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) { | |||
| 58 | event_fifo_id = 0; | 59 | event_fifo_id = 0; |
| 59 | shutting_down = false; | 60 | shutting_down = false; |
| 60 | ticks = 0; | 61 | ticks = 0; |
| 61 | const auto empty_timed_callback = [](std::uintptr_t, std::chrono::nanoseconds) {}; | 62 | const auto empty_timed_callback = [](std::uintptr_t, u64, std::chrono::nanoseconds) |
| 63 | -> std::optional<std::chrono::nanoseconds> { return std::nullopt; }; | ||
| 62 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); | 64 | ev_lost = CreateEvent("_lost_event", empty_timed_callback); |
| 63 | if (is_multicore) { | 65 | if (is_multicore) { |
| 64 | worker_threads.emplace_back(ThreadEntry, std::ref(*this), 0); | 66 | worker_threads.emplace_back(ThreadEntry, std::ref(*this), 0); |
| @@ -76,6 +78,7 @@ void CoreTiming::Shutdown() { | |||
| 76 | thread.join(); | 78 | thread.join(); |
| 77 | } | 79 | } |
| 78 | worker_threads.clear(); | 80 | worker_threads.clear(); |
| 81 | pause_callbacks.clear(); | ||
| 79 | ClearPendingEvents(); | 82 | ClearPendingEvents(); |
| 80 | has_started = false; | 83 | has_started = false; |
| 81 | } | 84 | } |
| @@ -93,6 +96,14 @@ void CoreTiming::Pause(bool is_paused_) { | |||
| 93 | } | 96 | } |
| 94 | } | 97 | } |
| 95 | paused_state.store(is_paused_, std::memory_order_relaxed); | 98 | paused_state.store(is_paused_, std::memory_order_relaxed); |
| 99 | |||
| 100 | if (!is_paused_) { | ||
| 101 | pause_end_time = GetGlobalTimeNs().count(); | ||
| 102 | } | ||
| 103 | |||
| 104 | for (auto& cb : pause_callbacks) { | ||
| 105 | cb(is_paused_); | ||
| 106 | } | ||
| 96 | } | 107 | } |
| 97 | 108 | ||
| 98 | void CoreTiming::SyncPause(bool is_paused_) { | 109 | void CoreTiming::SyncPause(bool is_paused_) { |
| @@ -116,6 +127,14 @@ void CoreTiming::SyncPause(bool is_paused_) { | |||
| 116 | wait_signal_cv.wait(main_lock, [this] { return pause_count == 0; }); | 127 | wait_signal_cv.wait(main_lock, [this] { return pause_count == 0; }); |
| 117 | } | 128 | } |
| 118 | } | 129 | } |
| 130 | |||
| 131 | if (!is_paused_) { | ||
| 132 | pause_end_time = GetGlobalTimeNs().count(); | ||
| 133 | } | ||
| 134 | |||
| 135 | for (auto& cb : pause_callbacks) { | ||
| 136 | cb(is_paused_); | ||
| 137 | } | ||
| 119 | } | 138 | } |
| 120 | 139 | ||
| 121 | bool CoreTiming::IsRunning() const { | 140 | bool CoreTiming::IsRunning() const { |
| @@ -129,12 +148,30 @@ bool CoreTiming::HasPendingEvents() const { | |||
| 129 | 148 | ||
| 130 | void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, | 149 | void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future, |
| 131 | const std::shared_ptr<EventType>& event_type, | 150 | const std::shared_ptr<EventType>& event_type, |
| 132 | std::uintptr_t user_data) { | 151 | std::uintptr_t user_data, bool absolute_time) { |
| 133 | 152 | ||
| 134 | std::unique_lock main_lock(event_mutex); | 153 | std::unique_lock main_lock(event_mutex); |
| 135 | const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count()); | 154 | const auto next_time{absolute_time ? ns_into_future : GetGlobalTimeNs() + ns_into_future}; |
| 136 | 155 | ||
| 137 | event_queue.emplace_back(Event{timeout, event_fifo_id++, user_data, event_type}); | 156 | event_queue.emplace_back(Event{next_time.count(), event_fifo_id++, user_data, event_type, 0}); |
| 157 | pending_events.fetch_add(1, std::memory_order_relaxed); | ||
| 158 | |||
| 159 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | ||
| 160 | |||
| 161 | if (is_multicore) { | ||
| 162 | event_cv.notify_one(); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, | ||
| 167 | std::chrono::nanoseconds resched_time, | ||
| 168 | const std::shared_ptr<EventType>& event_type, | ||
| 169 | std::uintptr_t user_data, bool absolute_time) { | ||
| 170 | std::unique_lock main_lock(event_mutex); | ||
| 171 | const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time}; | ||
| 172 | |||
| 173 | event_queue.emplace_back( | ||
| 174 | Event{next_time.count(), event_fifo_id++, user_data, event_type, resched_time.count()}); | ||
| 138 | pending_events.fetch_add(1, std::memory_order_relaxed); | 175 | pending_events.fetch_add(1, std::memory_order_relaxed); |
| 139 | 176 | ||
| 140 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 177 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); |
| @@ -213,6 +250,11 @@ void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) { | |||
| 213 | } | 250 | } |
| 214 | } | 251 | } |
| 215 | 252 | ||
| 253 | void CoreTiming::RegisterPauseCallback(PauseCallback&& callback) { | ||
| 254 | std::unique_lock main_lock(event_mutex); | ||
| 255 | pause_callbacks.emplace_back(std::move(callback)); | ||
| 256 | } | ||
| 257 | |||
| 216 | std::optional<s64> CoreTiming::Advance() { | 258 | std::optional<s64> CoreTiming::Advance() { |
| 217 | global_timer = GetGlobalTimeNs().count(); | 259 | global_timer = GetGlobalTimeNs().count(); |
| 218 | 260 | ||
| @@ -223,14 +265,31 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 223 | event_queue.pop_back(); | 265 | event_queue.pop_back(); |
| 224 | 266 | ||
| 225 | if (const auto event_type{evt.type.lock()}) { | 267 | if (const auto event_type{evt.type.lock()}) { |
| 226 | |||
| 227 | event_mutex.unlock(); | 268 | event_mutex.unlock(); |
| 228 | 269 | ||
| 229 | const s64 delay = static_cast<s64>(GetGlobalTimeNs().count() - evt.time); | 270 | const auto new_schedule_time{event_type->callback( |
| 230 | event_type->callback(evt.user_data, std::chrono::nanoseconds{delay}); | 271 | evt.user_data, evt.time, |
| 272 | std::chrono::nanoseconds{GetGlobalTimeNs().count() - evt.time})}; | ||
| 231 | 273 | ||
| 232 | event_mutex.lock(); | 274 | event_mutex.lock(); |
| 233 | pending_events.fetch_sub(1, std::memory_order_relaxed); | 275 | pending_events.fetch_sub(1, std::memory_order_relaxed); |
| 276 | |||
| 277 | if (evt.reschedule_time != 0) { | ||
| 278 | // If this event was scheduled into a pause, its time now is going to be way behind. | ||
| 279 | // Re-set this event to continue from the end of the pause. | ||
| 280 | auto next_time{evt.time + evt.reschedule_time}; | ||
| 281 | if (evt.time < pause_end_time) { | ||
| 282 | next_time = pause_end_time + evt.reschedule_time; | ||
| 283 | } | ||
| 284 | |||
| 285 | const auto next_schedule_time{new_schedule_time.has_value() | ||
| 286 | ? new_schedule_time.value().count() | ||
| 287 | : evt.reschedule_time}; | ||
| 288 | event_queue.emplace_back( | ||
| 289 | Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); | ||
| 290 | pending_events.fetch_add(1, std::memory_order_relaxed); | ||
| 291 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | ||
| 292 | } | ||
| 234 | } | 293 | } |
| 235 | 294 | ||
| 236 | global_timer = GetGlobalTimeNs().count(); | 295 | global_timer = GetGlobalTimeNs().count(); |