diff options
| author | 2022-09-17 11:10:54 -0700 | |
|---|---|---|
| committer | 2022-09-17 11:10:54 -0700 | |
| commit | 9c32f29af18f5412ea4ba9f15fe0da3805e0d858 (patch) | |
| tree | 63f5b2a5b5ad49179067d01e34c11fb2a7510bd8 /src/core/core_timing.cpp | |
| parent | Merge pull request #8914 from lioncash/audio-const (diff) | |
| parent | core_timing: Sleep in discrete intervals, yield during spin (diff) | |
| download | yuzu-9c32f29af18f5412ea4ba9f15fe0da3805e0d858.tar.gz yuzu-9c32f29af18f5412ea4ba9f15fe0da3805e0d858.tar.xz yuzu-9c32f29af18f5412ea4ba9f15fe0da3805e0d858.zip | |
Merge pull request #8650 from Kelebek1/vsync
[Coretiming/NVNFlinger] Improve multi-core vsync timing, and core timing accuracy
Diffstat (limited to 'src/core/core_timing.cpp')
| -rw-r--r-- | src/core/core_timing.cpp | 53 |
1 files changed, 37 insertions, 16 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 5375a5d59..f6c4567ba 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -134,13 +134,17 @@ void CoreTiming::ScheduleLoopingEvent(std::chrono::nanoseconds start_time, | |||
| 134 | std::chrono::nanoseconds resched_time, | 134 | std::chrono::nanoseconds resched_time, |
| 135 | const std::shared_ptr<EventType>& event_type, | 135 | const std::shared_ptr<EventType>& event_type, |
| 136 | std::uintptr_t user_data, bool absolute_time) { | 136 | std::uintptr_t user_data, bool absolute_time) { |
| 137 | std::scoped_lock scope{basic_lock}; | 137 | { |
| 138 | const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time}; | 138 | std::scoped_lock scope{basic_lock}; |
| 139 | const auto next_time{absolute_time ? start_time : GetGlobalTimeNs() + start_time}; | ||
| 140 | |||
| 141 | event_queue.emplace_back( | ||
| 142 | Event{next_time.count(), event_fifo_id++, user_data, event_type, resched_time.count()}); | ||
| 139 | 143 | ||
| 140 | event_queue.emplace_back( | 144 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); |
| 141 | Event{next_time.count(), event_fifo_id++, user_data, event_type, resched_time.count()}); | 145 | } |
| 142 | 146 | ||
| 143 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 147 | event.Set(); |
| 144 | } | 148 | } |
| 145 | 149 | ||
| 146 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, | 150 | void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type, |
| @@ -229,17 +233,17 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 229 | basic_lock.lock(); | 233 | basic_lock.lock(); |
| 230 | 234 | ||
| 231 | if (evt.reschedule_time != 0) { | 235 | if (evt.reschedule_time != 0) { |
| 236 | const auto next_schedule_time{new_schedule_time.has_value() | ||
| 237 | ? new_schedule_time.value().count() | ||
| 238 | : evt.reschedule_time}; | ||
| 239 | |||
| 232 | // If this event was scheduled into a pause, its time now is going to be way behind. | 240 | // If this event was scheduled into a pause, its time now is going to be way behind. |
| 233 | // Re-set this event to continue from the end of the pause. | 241 | // Re-set this event to continue from the end of the pause. |
| 234 | auto next_time{evt.time + evt.reschedule_time}; | 242 | auto next_time{evt.time + next_schedule_time}; |
| 235 | if (evt.time < pause_end_time) { | 243 | if (evt.time < pause_end_time) { |
| 236 | next_time = pause_end_time + evt.reschedule_time; | 244 | next_time = pause_end_time + next_schedule_time; |
| 237 | } | 245 | } |
| 238 | 246 | ||
| 239 | const auto next_schedule_time{new_schedule_time.has_value() | ||
| 240 | ? new_schedule_time.value().count() | ||
| 241 | : evt.reschedule_time}; | ||
| 242 | |||
| 243 | event_queue.emplace_back( | 247 | event_queue.emplace_back( |
| 244 | Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); | 248 | Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); |
| 245 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 249 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); |
| @@ -250,8 +254,7 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 250 | } | 254 | } |
| 251 | 255 | ||
| 252 | if (!event_queue.empty()) { | 256 | if (!event_queue.empty()) { |
| 253 | const s64 next_time = event_queue.front().time - global_timer; | 257 | return event_queue.front().time; |
| 254 | return next_time; | ||
| 255 | } else { | 258 | } else { |
| 256 | return std::nullopt; | 259 | return std::nullopt; |
| 257 | } | 260 | } |
| @@ -264,11 +267,29 @@ void CoreTiming::ThreadLoop() { | |||
| 264 | paused_set = false; | 267 | paused_set = false; |
| 265 | const auto next_time = Advance(); | 268 | const auto next_time = Advance(); |
| 266 | if (next_time) { | 269 | if (next_time) { |
| 267 | if (*next_time > 0) { | 270 | // There are more events left in the queue, wait until the next event. |
| 268 | std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); | 271 | const auto wait_time = *next_time - GetGlobalTimeNs().count(); |
| 269 | event.WaitFor(next_time_ns); | 272 | if (wait_time > 0) { |
| 273 | // Assume a timer resolution of 1ms. | ||
| 274 | static constexpr s64 TimerResolutionNS = 1000000; | ||
| 275 | |||
| 276 | // Sleep in discrete intervals of the timer resolution, and spin the rest. | ||
| 277 | const auto sleep_time = wait_time - (wait_time % TimerResolutionNS); | ||
| 278 | if (sleep_time > 0) { | ||
| 279 | event.WaitFor(std::chrono::nanoseconds(sleep_time)); | ||
| 280 | } | ||
| 281 | |||
| 282 | while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) { | ||
| 283 | // Yield to reduce thread starvation. | ||
| 284 | std::this_thread::yield(); | ||
| 285 | } | ||
| 286 | |||
| 287 | if (event.IsSet()) { | ||
| 288 | event.Reset(); | ||
| 289 | } | ||
| 270 | } | 290 | } |
| 271 | } else { | 291 | } else { |
| 292 | // Queue is empty, wait until another event is scheduled and signals us to continue. | ||
| 272 | wait_set = true; | 293 | wait_set = true; |
| 273 | event.Wait(); | 294 | event.Wait(); |
| 274 | } | 295 | } |