summaryrefslogtreecommitdiff
path: root/src/core/core_timing.cpp
diff options
context:
space:
mode:
authorGravatar Kelebek12022-07-27 22:31:41 +0100
committerGravatar Morph2022-08-02 01:01:54 -0400
commit83a24ad638a2c3ff628fe109391586be9bd3a45d (patch)
tree3ac77d8c6876200075bd6c68eebc6f4098df1422 /src/core/core_timing.cpp
parentRework multi-core vsync (diff)
downloadyuzu-83a24ad638a2c3ff628fe109391586be9bd3a45d.tar.gz
yuzu-83a24ad638a2c3ff628fe109391586be9bd3a45d.tar.xz
yuzu-83a24ad638a2c3ff628fe109391586be9bd3a45d.zip
Make coretiming waiting more accurate
Diffstat (limited to 'src/core/core_timing.cpp')
-rw-r--r--src/core/core_timing.cpp38
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 }