From 19b25a2e42d28ffbeab5fe6c3eb288cdfc921f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 17 Oct 2026 18:03:00 +0200 Subject: [PATCH] Common: Use CLOCK_UPTIME_RAW for the monotonic clock on Apple platforms - Fixes #16823 CLOCK_UPTIME_RAW is mach_absolute_time() in nanoseconds (the same value, not just the same rate). That's the clock MoltenVK reports VK_GOOGLE_display_timing present times in, which time_now_raw() is meant to match. Apple's CLOCK_MONOTONIC counts time asleep, unlike Linux's, so on a Mac that had slept since boot, from_time_raw() of a present time was off by all of it. It's also cheaper to read: ~19ns vs ~30ns on M1. mach_absolute_time() itself is ~8ns, but returns ticks, and the timebase on Apple Silicon is 125/3. Timing risk: time_now_d() no longer advances while the machine sleeps, so a sleep/wake shows up as a small delta rather than a huge one. Co-Authored-By: Claude Opus 5.5 (1M context) --- Common/TimeUtil.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Common/TimeUtil.cpp b/Common/TimeUtil.cpp index 2c4d407e36..ec2f43126a 100644 --- a/Common/TimeUtil.cpp +++ b/Common/TimeUtil.cpp @@ -147,9 +147,14 @@ int64_t Instant::ElapsedNanos() const { #else -// Monotonic, in nanoseconds. On Linux and Android this is the clock VK_GOOGLE_display_timing reports in. +// Monotonic, in nanoseconds, and the clock VK_GOOGLE_display_timing reports in. uint64_t time_now_raw() { -#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) +#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) + // mach_absolute_time() in nanoseconds, which is what MoltenVK reports present times in. Apple's + // CLOCK_MONOTONIC keeps counting during sleep (unlike Linux's), so it drifts away from those, + // and is slower to read (~30ns vs ~19ns on M1). + return clock_gettime_nsec_np(CLOCK_UPTIME_RAW); +#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) struct timespec tp; clock_gettime(CLOCK_MONOTONIC, &tp); return tp.tv_sec * 1000000000ULL + tp.tv_nsec;