mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-30 18:18:32 +00:00
videoout: Make present thread realtime on macOS. (#990)
This commit is contained in:
parent
60f315a54d
commit
048b8aef58
src
|
@ -9,6 +9,7 @@
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
|
#include <mach/mach_time.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -31,6 +32,48 @@
|
||||||
|
|
||||||
namespace Common {
|
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
|
#ifdef _WIN32
|
||||||
|
|
||||||
void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
void SetCurrentThreadPriority(ThreadPriority new_priority) {
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
namespace Common {
|
namespace Common {
|
||||||
|
@ -16,6 +17,8 @@ enum class ThreadPriority : u32 {
|
||||||
Critical = 4,
|
Critical = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SetCurrentThreadRealtime(std::chrono::nanoseconds period_ns);
|
||||||
|
|
||||||
void SetCurrentThreadPriority(ThreadPriority new_priority);
|
void SetCurrentThreadPriority(ThreadPriority new_priority);
|
||||||
|
|
||||||
void SetCurrentThreadName(const char* name);
|
void SetCurrentThreadName(const char* name);
|
||||||
|
|
|
@ -261,8 +261,11 @@ void VideoOutDriver::SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoOutDriver::PresentThread(std::stop_token token) {
|
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::SetCurrentThreadName("PresentThread");
|
||||||
|
Common::SetCurrentThreadRealtime(vblank_period);
|
||||||
|
|
||||||
const auto receive_request = [this] -> Request {
|
const auto receive_request = [this] -> Request {
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
|
@ -274,7 +277,6 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
auto vblank_period = VblankPeriod / Config::vblankDiv();
|
|
||||||
auto delay = std::chrono::microseconds{0};
|
auto delay = std::chrono::microseconds{0};
|
||||||
while (!token.stop_requested()) {
|
while (!token.stop_requested()) {
|
||||||
// Sleep for most of the vblank duration.
|
// Sleep for most of the vblank duration.
|
||||||
|
|
Loading…
Reference in a new issue