videoout: Make present thread realtime on macOS. (#990)

This commit is contained in:
squidbus 2024-09-19 15:28:35 -07:00 committed by GitHub
parent 03ba49a3e0
commit 770cbf14e9
3 changed files with 50 additions and 2 deletions

View file

@ -9,6 +9,7 @@
#include "common/thread.h"
#ifdef __APPLE__
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <pthread.h>
#elif defined(_WIN32)
#include <windows.h>
@ -31,6 +32,48 @@
namespace Common {
#ifdef __APPLE__
void SetCurrentThreadRealtime(const std::chrono::nanoseconds period_ns) {
// CPU time to grant.
const std::chrono::nanoseconds computation_ns = period_ns / 2;
// Determine the timebase for converting time to ticks.
struct mach_timebase_info timebase {};
mach_timebase_info(&timebase);
const auto ticks_per_ns =
static_cast<double>(timebase.denom) / static_cast<double>(timebase.numer);
const auto period_ticks =
static_cast<u32>(static_cast<double>(period_ns.count()) * ticks_per_ns);
const auto computation_ticks =
static_cast<u32>(static_cast<double>(computation_ns.count()) * ticks_per_ns);
thread_time_constraint_policy policy = {
.period = period_ticks,
.computation = computation_ticks,
// Should not matter since preemptible is false, but needs to be >= computation regardless.
.constraint = computation_ticks,
.preemptible = false,
};
int ret = thread_policy_set(
pthread_mach_thread_np(pthread_self()), THREAD_TIME_CONSTRAINT_POLICY,
reinterpret_cast<thread_policy_t>(&policy), THREAD_TIME_CONSTRAINT_POLICY_COUNT);
if (ret != KERN_SUCCESS) {
LOG_ERROR(Common, "Could not set thread to real-time with period {} ns: {}",
period_ns.count(), ret);
}
}
#else
void SetCurrentThreadRealtime(const std::chrono::nanoseconds period_ns) {
// Not implemented
}
#endif
#ifdef _WIN32
void SetCurrentThreadPriority(ThreadPriority new_priority) {

View file

@ -4,6 +4,7 @@
#pragma once
#include <chrono>
#include "common/types.h"
namespace Common {
@ -16,6 +17,8 @@ enum class ThreadPriority : u32 {
Critical = 4,
};
void SetCurrentThreadRealtime(std::chrono::nanoseconds period_ns);
void SetCurrentThreadPriority(ThreadPriority new_priority);
void SetCurrentThreadName(const char* name);

View file

@ -261,8 +261,11 @@ void VideoOutDriver::SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_
}
void VideoOutDriver::PresentThread(std::stop_token token) {
static constexpr std::chrono::milliseconds VblankPeriod{16};
static constexpr std::chrono::nanoseconds VblankPeriod{16666667};
const auto vblank_period = VblankPeriod / Config::vblankDiv();
Common::SetCurrentThreadName("PresentThread");
Common::SetCurrentThreadRealtime(vblank_period);
const auto receive_request = [this] -> Request {
std::scoped_lock lk{mutex};
@ -274,7 +277,6 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
return {};
};
auto vblank_period = VblankPeriod / Config::vblankDiv();
auto delay = std::chrono::microseconds{0};
while (!token.stop_requested()) {
// Sleep for most of the vblank duration.