summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/common/CMakeLists.txt2
-rw-r--r--src/common/steady_clock.cpp56
-rw-r--r--src/common/steady_clock.h23
3 files changed, 81 insertions, 0 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 56b247ac4..9f5d4c265 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -113,6 +113,8 @@ add_library(common STATIC
socket_types.h
spin_lock.cpp
spin_lock.h
+ steady_clock.cpp
+ steady_clock.h
stream.cpp
stream.h
string_util.cpp
diff --git a/src/common/steady_clock.cpp b/src/common/steady_clock.cpp
new file mode 100644
index 000000000..0d5908aa7
--- /dev/null
+++ b/src/common/steady_clock.cpp
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#if defined(_WIN32)
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+#include "common/steady_clock.h"
+
+namespace Common {
+
+#ifdef _WIN32
+static s64 WindowsQueryPerformanceFrequency() {
+ LARGE_INTEGER frequency;
+ QueryPerformanceFrequency(&frequency);
+ return frequency.QuadPart;
+}
+
+static s64 WindowsQueryPerformanceCounter() {
+ LARGE_INTEGER counter;
+ QueryPerformanceCounter(&counter);
+ return counter.QuadPart;
+}
+#endif
+
+SteadyClock::time_point SteadyClock::Now() noexcept {
+#if defined(_WIN32)
+ static const auto freq = WindowsQueryPerformanceFrequency();
+ const auto counter = WindowsQueryPerformanceCounter();
+
+ // 10 MHz is a very common QPC frequency on modern PCs.
+ // Optimizing for this specific frequency can double the performance of
+ // this function by avoiding the expensive frequency conversion path.
+ static constexpr s64 TenMHz = 10'000'000;
+
+ if (freq == TenMHz) [[likely]] {
+ static_assert(period::den % TenMHz == 0);
+ static constexpr s64 Multiplier = period::den / TenMHz;
+ return time_point{duration{counter * Multiplier}};
+ }
+
+ const auto whole = (counter / freq) * period::den;
+ const auto part = (counter % freq) * period::den / freq;
+ return time_point{duration{whole + part}};
+#elif defined(__APPLE__)
+ return time_point{duration{clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW)}};
+#else
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return time_point{std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}};
+#endif
+}
+
+}; // namespace Common
diff --git a/src/common/steady_clock.h b/src/common/steady_clock.h
new file mode 100644
index 000000000..9497cf865
--- /dev/null
+++ b/src/common/steady_clock.h
@@ -0,0 +1,23 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <chrono>
+
+#include "common/common_types.h"
+
+namespace Common {
+
+struct SteadyClock {
+ using rep = s64;
+ using period = std::nano;
+ using duration = std::chrono::nanoseconds;
+ using time_point = std::chrono::time_point<SteadyClock>;
+
+ static constexpr bool is_steady = true;
+
+ [[nodiscard]] static time_point Now() noexcept;
+};
+
+} // namespace Common