summaryrefslogtreecommitdiff
path: root/src/core/core_timing.cpp
diff options
context:
space:
mode:
authorGravatar liamwhite2023-03-07 10:54:13 -0500
committerGravatar GitHub2023-03-07 10:54:13 -0500
commita7792e5ff83523142230951ac7eacbd7685dc40b (patch)
treea7531c65e2ddec1122fc071d44c8106c48352ce3 /src/core/core_timing.cpp
parentMerge pull request #9890 from Kelebek1/reverb_fix (diff)
parentnative_clock: Round RDTSC frequency to the nearest 1000 (diff)
downloadyuzu-a7792e5ff83523142230951ac7eacbd7685dc40b.tar.gz
yuzu-a7792e5ff83523142230951ac7eacbd7685dc40b.tar.xz
yuzu-a7792e5ff83523142230951ac7eacbd7685dc40b.zip
Merge pull request #9889 from Morph1984/time-is-ticking
core_timing: Reduce CPU usage on Windows
Diffstat (limited to 'src/core/core_timing.cpp')
-rw-r--r--src/core/core_timing.cpp55
1 files changed, 33 insertions, 22 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 3a63b52e3..742cfb996 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -6,6 +6,10 @@
6#include <string> 6#include <string>
7#include <tuple> 7#include <tuple>
8 8
9#ifdef _WIN32
10#include "common/windows/timer_resolution.h"
11#endif
12
9#include "common/microprofile.h" 13#include "common/microprofile.h"
10#include "core/core_timing.h" 14#include "core/core_timing.h"
11#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
@@ -38,7 +42,8 @@ struct CoreTiming::Event {
38}; 42};
39 43
40CoreTiming::CoreTiming() 44CoreTiming::CoreTiming()
41 : clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {} 45 : cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)},
46 event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
42 47
43CoreTiming::~CoreTiming() { 48CoreTiming::~CoreTiming() {
44 Reset(); 49 Reset();
@@ -185,15 +190,15 @@ void CoreTiming::ResetTicks() {
185} 190}
186 191
187u64 CoreTiming::GetCPUTicks() const { 192u64 CoreTiming::GetCPUTicks() const {
188 if (is_multicore) { 193 if (is_multicore) [[likely]] {
189 return clock->GetCPUCycles(); 194 return cpu_clock->GetCPUCycles();
190 } 195 }
191 return ticks; 196 return ticks;
192} 197}
193 198
194u64 CoreTiming::GetClockTicks() const { 199u64 CoreTiming::GetClockTicks() const {
195 if (is_multicore) { 200 if (is_multicore) [[likely]] {
196 return clock->GetClockCycles(); 201 return cpu_clock->GetClockCycles();
197 } 202 }
198 return CpuCyclesToClockCycles(ticks); 203 return CpuCyclesToClockCycles(ticks);
199} 204}
@@ -252,21 +257,20 @@ void CoreTiming::ThreadLoop() {
252 const auto next_time = Advance(); 257 const auto next_time = Advance();
253 if (next_time) { 258 if (next_time) {
254 // There are more events left in the queue, wait until the next event. 259 // There are more events left in the queue, wait until the next event.
255 const auto wait_time = *next_time - GetGlobalTimeNs().count(); 260 auto wait_time = *next_time - GetGlobalTimeNs().count();
256 if (wait_time > 0) { 261 if (wait_time > 0) {
257#ifdef _WIN32 262#ifdef _WIN32
258 // Assume a timer resolution of 1ms. 263 const auto timer_resolution_ns =
259 static constexpr s64 TimerResolutionNS = 1000000; 264 Common::Windows::GetCurrentTimerResolution().count();
260 265
261 // Sleep in discrete intervals of the timer resolution, and spin the rest. 266 while (!paused && !event.IsSet() && wait_time > 0) {
262 const auto sleep_time = wait_time - (wait_time % TimerResolutionNS); 267 wait_time = *next_time - GetGlobalTimeNs().count();
263 if (sleep_time > 0) {
264 event.WaitFor(std::chrono::nanoseconds(sleep_time));
265 }
266 268
267 while (!paused && !event.IsSet() && GetGlobalTimeNs().count() < *next_time) { 269 if (wait_time >= timer_resolution_ns) {
268 // Yield to reduce thread starvation. 270 Common::Windows::SleepForOneTick();
269 std::this_thread::yield(); 271 } else {
272 std::this_thread::yield();
273 }
270 } 274 }
271 275
272 if (event.IsSet()) { 276 if (event.IsSet()) {
@@ -285,9 +289,9 @@ void CoreTiming::ThreadLoop() {
285 } 289 }
286 290
287 paused_set = true; 291 paused_set = true;
288 clock->Pause(true); 292 event_clock->Pause(true);
289 pause_event.Wait(); 293 pause_event.Wait();
290 clock->Pause(false); 294 event_clock->Pause(false);
291 } 295 }
292} 296}
293 297
@@ -303,16 +307,23 @@ void CoreTiming::Reset() {
303 has_started = false; 307 has_started = false;
304} 308}
305 309
310std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const {
311 if (is_multicore) [[likely]] {
312 return cpu_clock->GetTimeNS();
313 }
314 return CyclesToNs(ticks);
315}
316
306std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const { 317std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
307 if (is_multicore) { 318 if (is_multicore) [[likely]] {
308 return clock->GetTimeNS(); 319 return event_clock->GetTimeNS();
309 } 320 }
310 return CyclesToNs(ticks); 321 return CyclesToNs(ticks);
311} 322}
312 323
313std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const { 324std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
314 if (is_multicore) { 325 if (is_multicore) [[likely]] {
315 return clock->GetTimeUS(); 326 return event_clock->GetTimeUS();
316 } 327 }
317 return CyclesToUs(ticks); 328 return CyclesToUs(ticks);
318} 329}