diff options
| author | 2022-07-27 22:31:41 +0100 | |
|---|---|---|
| committer | 2022-08-02 01:01:54 -0400 | |
| commit | 83a24ad638a2c3ff628fe109391586be9bd3a45d (patch) | |
| tree | 3ac77d8c6876200075bd6c68eebc6f4098df1422 /src/core | |
| parent | Rework multi-core vsync (diff) | |
| download | yuzu-83a24ad638a2c3ff628fe109391586be9bd3a45d.tar.gz yuzu-83a24ad638a2c3ff628fe109391586be9bd3a45d.tar.xz yuzu-83a24ad638a2c3ff628fe109391586be9bd3a45d.zip | |
Make coretiming waiting more accurate
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/core_timing.cpp | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index 2dbb99c8b..b45c1b918 100644 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp | |||
| @@ -243,17 +243,17 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 243 | basic_lock.lock(); | 243 | basic_lock.lock(); |
| 244 | 244 | ||
| 245 | if (evt.reschedule_time != 0) { | 245 | if (evt.reschedule_time != 0) { |
| 246 | const auto next_schedule_time{new_schedule_time.has_value() | ||
| 247 | ? new_schedule_time.value().count() | ||
| 248 | : evt.reschedule_time}; | ||
| 249 | |||
| 246 | // If this event was scheduled into a pause, its time now is going to be way behind. | 250 | // If this event was scheduled into a pause, its time now is going to be way behind. |
| 247 | // Re-set this event to continue from the end of the pause. | 251 | // Re-set this event to continue from the end of the pause. |
| 248 | auto next_time{evt.time + evt.reschedule_time}; | 252 | auto next_time{evt.time + next_schedule_time}; |
| 249 | if (evt.time < pause_end_time) { | 253 | if (evt.time < pause_end_time) { |
| 250 | next_time = pause_end_time + evt.reschedule_time; | 254 | next_time = pause_end_time + next_schedule_time; |
| 251 | } | 255 | } |
| 252 | 256 | ||
| 253 | const auto next_schedule_time{new_schedule_time.has_value() | ||
| 254 | ? new_schedule_time.value().count() | ||
| 255 | : evt.reschedule_time}; | ||
| 256 | |||
| 257 | event_queue.emplace_back( | 257 | event_queue.emplace_back( |
| 258 | Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); | 258 | Event{next_time, event_fifo_id++, evt.user_data, evt.type, next_schedule_time}); |
| 259 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); | 259 | std::push_heap(event_queue.begin(), event_queue.end(), std::greater<>()); |
| @@ -264,8 +264,7 @@ std::optional<s64> CoreTiming::Advance() { | |||
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | if (!event_queue.empty()) { | 266 | if (!event_queue.empty()) { |
| 267 | const s64 next_time = event_queue.front().time - global_timer; | 267 | return event_queue.front().time; |
| 268 | return next_time; | ||
| 269 | } else { | 268 | } else { |
| 270 | return std::nullopt; | 269 | return std::nullopt; |
| 271 | } | 270 | } |
| @@ -278,11 +277,28 @@ void CoreTiming::ThreadLoop() { | |||
| 278 | paused_set = false; | 277 | paused_set = false; |
| 279 | const auto next_time = Advance(); | 278 | const auto next_time = Advance(); |
| 280 | if (next_time) { | 279 | if (next_time) { |
| 281 | if (*next_time > 0) { | 280 | // There are more events left in the queue, sleep until the next event. |
| 282 | std::chrono::nanoseconds next_time_ns = std::chrono::nanoseconds(*next_time); | 281 | const auto diff_ns{*next_time - GetGlobalTimeNs().count()}; |
| 283 | event.WaitFor(next_time_ns); | 282 | if (diff_ns > 0) { |
| 283 | // Only try to sleep if the remaining time is >= 1ms. Take off 500 microseconds | ||
| 284 | // from the target time to account for possible over-sleeping, and spin the | ||
| 285 | // remaining. | ||
| 286 | const auto sleep_time_ns{diff_ns - 500LL * 1'000LL}; | ||
| 287 | const auto sleep_time_ms{sleep_time_ns / 1'000'000LL}; | ||
| 288 | if (sleep_time_ms >= 1) { | ||
| 289 | event.WaitFor(std::chrono::nanoseconds(sleep_time_ns)); | ||
| 290 | } | ||
| 291 | |||
| 292 | const auto end_time{std::chrono::nanoseconds(*next_time)}; | ||
| 293 | while (!paused && !event.IsSet() && GetGlobalTimeNs() < end_time) { | ||
| 294 | } | ||
| 295 | |||
| 296 | if (event.IsSet()) { | ||
| 297 | event.Reset(); | ||
| 298 | } | ||
| 284 | } | 299 | } |
| 285 | } else { | 300 | } else { |
| 301 | // Queue is empty, wait until another event is scheduled and signals us to continue. | ||
| 286 | wait_set = true; | 302 | wait_set = true; |
| 287 | event.Wait(); | 303 | event.Wait(); |
| 288 | } | 304 | } |