From c3fbc8d2fe2ff423d774ed3886fc8391c730f637 Mon Sep 17 00:00:00 2001
From: Morph <39850852+Morph1984@users.noreply.github.com>
Date: Sun, 2 Jul 2023 15:05:35 -0400
Subject: [PATCH] core_timing: Remove GetCurrentTimerResolution in CoreTiming
 loop

Other programs may change this value, but if thousands of syscalls in this loop is undesirable, then we can just set this once.
---
 src/core/core_timing.cpp | 9 ++++++---
 src/core/core_timing.h   | 8 ++++++++
 src/yuzu/main.cpp        | 2 ++
 src/yuzu_cmd/yuzu.cpp    | 8 ++++++--
 4 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 4f0a3f8eab..e6112a3c9a 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -253,9 +253,6 @@ void CoreTiming::ThreadLoop() {
                 auto wait_time = *next_time - GetGlobalTimeNs().count();
                 if (wait_time > 0) {
 #ifdef _WIN32
-                    const auto timer_resolution_ns =
-                        Common::Windows::GetCurrentTimerResolution().count();
-
                     while (!paused && !event.IsSet() && wait_time > 0) {
                         wait_time = *next_time - GetGlobalTimeNs().count();
 
@@ -316,4 +313,10 @@ std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
     return std::chrono::microseconds{Common::WallClock::CPUTickToUS(cpu_ticks)};
 }
 
+#ifdef _WIN32
+void CoreTiming::SetTimerResolutionNs(std::chrono::nanoseconds ns) {
+    timer_resolution_ns = ns.count();
+}
+#endif
+
 } // namespace Core::Timing
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 10db1de552..5bca1c78dd 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -131,6 +131,10 @@ public:
     /// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
     std::optional<s64> Advance();
 
+#ifdef _WIN32
+    void SetTimerResolutionNs(std::chrono::nanoseconds ns);
+#endif
+
 private:
     struct Event;
 
@@ -143,6 +147,10 @@ private:
 
     s64 global_timer = 0;
 
+#ifdef _WIN32
+    s64 timer_resolution_ns;
+#endif
+
     // The queue is a min-heap using std::make_heap/push_heap/pop_heap.
     // We don't use std::priority_queue because we need to be able to serialize, unserialize and
     // erase arbitrary events (RemoveEvent()) regardless of the queue order. These aren't
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index e8418b3022..fea5eb614c 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -101,6 +101,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
 #include "common/settings.h"
 #include "common/telemetry.h"
 #include "core/core.h"
+#include "core/core_timing.h"
 #include "core/crypto/key_manager.h"
 #include "core/file_sys/card_image.h"
 #include "core/file_sys/common_funcs.h"
@@ -389,6 +390,7 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
              std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>(
                  Common::Windows::SetCurrentTimerResolutionToMaximum())
                  .count());
+    system->CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
 #endif
     UpdateWindowTitle();
 
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 7b6d49c633..d0433ffc65 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -21,6 +21,7 @@
 #include "common/string_util.h"
 #include "common/telemetry.h"
 #include "core/core.h"
+#include "core/core_timing.h"
 #include "core/cpu_manager.h"
 #include "core/crypto/key_manager.h"
 #include "core/file_sys/registered_cache.h"
@@ -316,8 +317,6 @@ int main(int argc, char** argv) {
 
 #ifdef _WIN32
     LocalFree(argv_w);
-
-    Common::Windows::SetCurrentTimerResolutionToMaximum();
 #endif
 
     MicroProfileOnThreadCreate("EmuThread");
@@ -351,6 +350,11 @@ int main(int argc, char** argv) {
         break;
     }
 
+#ifdef _WIN32
+    Common::Windows::SetCurrentTimerResolutionToMaximum();
+    system.CoreTiming().SetTimerResolutionNs(Common::Windows::GetCurrentTimerResolution());
+#endif
+
     system.SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>());
     system.SetFilesystem(std::make_shared<FileSys::RealVfsFilesystem>());
     system.GetFileSystemController().CreateFactories(*system.GetFilesystem());