mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 06:16:55 +01:00
perf: limit high-resolution sleep busy-waiting
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
#include <windows.h> // IWYU pragma: keep
|
#include <windows.h> // IWYU pragma: keep
|
||||||
// IWYU pragma: no_include <winbase.h>
|
// IWYU pragma: no_include <winbase.h>
|
||||||
constexpr DWORD KYTY_CS_SPIN_COUNT = 4000;
|
constexpr DWORD KYTY_CS_SPIN_COUNT = 4000;
|
||||||
|
constexpr uint64_t KYTY_SLEEP_SPIN_LIMIT_100NS = 500; // 50 us
|
||||||
|
|
||||||
#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
|
||||||
#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
|
#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002
|
||||||
@@ -39,7 +40,10 @@ static void SleepHighResolution100ns(uint64_t units_100ns) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (units_100ns <= 10000) {
|
// Keep spinning only where a kernel transition is
|
||||||
|
// likely to cost more than the requested delay; ordinary millisecond sleeps use the
|
||||||
|
// per-thread high-resolution waitable timer below.
|
||||||
|
if (units_100ns <= KYTY_SLEEP_SPIN_LIMIT_100NS) {
|
||||||
LARGE_INTEGER frequency {};
|
LARGE_INTEGER frequency {};
|
||||||
LARGE_INTEGER start {};
|
LARGE_INTEGER start {};
|
||||||
if (QueryPerformanceFrequency(&frequency) != 0 && QueryPerformanceCounter(&start) != 0 &&
|
if (QueryPerformanceFrequency(&frequency) != 0 && QueryPerformanceCounter(&start) != 0 &&
|
||||||
|
|||||||
@@ -788,14 +788,10 @@ void VideoOutDriver::Impl::PresentThread(std::stop_token token) {
|
|||||||
while (!token.stop_requested()) {
|
while (!token.stop_requested()) {
|
||||||
const auto sleep_begin = Common::Timer::QueryPerformanceCounter();
|
const auto sleep_begin = Common::Timer::QueryPerformanceCounter();
|
||||||
if (total_wait > 0) {
|
if (total_wait > 0) {
|
||||||
const auto sleep_end = sleep_begin + static_cast<uint64_t>(total_wait);
|
const auto remaining_us =
|
||||||
auto now = sleep_begin;
|
(static_cast<uint64_t>(total_wait) * 1000000u + frequency - 1) / frequency;
|
||||||
while (!token.stop_requested() && now < sleep_end) {
|
Common::Thread::SleepMicro(static_cast<uint32_t>(
|
||||||
const auto remaining_us = (sleep_end - now) * 1000000u / frequency;
|
std::clamp<uint64_t>(remaining_us, 1, std::numeric_limits<uint32_t>::max())));
|
||||||
Common::Thread::SleepMicro(
|
|
||||||
static_cast<uint32_t>(std::clamp<uint64_t>(remaining_us, 1, 1000)));
|
|
||||||
now = Common::Timer::QueryPerformanceCounter();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (token.stop_requested()) {
|
if (token.stop_requested()) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -752,26 +752,18 @@ void WindowContext::Run() {
|
|||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
DrainMainThreadTasks();
|
DrainMainThreadTasks();
|
||||||
#endif
|
#endif
|
||||||
if (SDL_PollEvent(&loop.event) != 0) {
|
|
||||||
ProcessEvent(timer.GetTimeS());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loop.paused.load(std::memory_order_acquire)) {
|
if (loop.paused.load(std::memory_order_acquire)) {
|
||||||
if (!timer.IsPaused()) {
|
if (!timer.IsPaused()) {
|
||||||
timer.Pause();
|
timer.Pause();
|
||||||
}
|
}
|
||||||
|
} else if (timer.IsPaused()) {
|
||||||
|
timer.Resume();
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_WaitEvent(&loop.event) == 0) {
|
if (SDL_WaitEvent(&loop.event) == 0) {
|
||||||
EXIT("%s\n", SDL_GetError());
|
EXIT("%s\n", SDL_GetError());
|
||||||
}
|
}
|
||||||
ProcessEvent(timer.GetTimeS());
|
ProcessEvent(timer.GetTimeS());
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timer.IsPaused()) {
|
|
||||||
timer.Resume();
|
|
||||||
}
|
|
||||||
Common::Thread::SleepMicro(1000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user