Rework multi-core vsync

This commit is contained in:
Kelebek1 2022-07-26 22:04:18 +01:00 committed by Morph
parent 9c31edccdf
commit 9d3b190465
2 changed files with 30 additions and 17 deletions

View File

@ -38,20 +38,16 @@ void NVFlinger::SplitVSync(std::stop_token stop_token) {
Common::SetCurrentThreadName(name.c_str()); Common::SetCurrentThreadName(name.c_str());
Common::SetCurrentThreadPriority(Common::ThreadPriority::High); Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
s64 delay = 0;
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
vsync_signal.wait(false);
vsync_signal.store(false);
guard->lock(); guard->lock();
const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
Compose(); Compose();
const auto ticks = GetNextTicks();
const s64 time_end = system.CoreTiming().GetGlobalTimeNs().count();
const s64 time_passed = time_end - time_start;
const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
guard->unlock(); guard->unlock();
if (next_time > 0) {
std::this_thread::sleep_for(std::chrono::nanoseconds{next_time});
}
delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
} }
} }
@ -66,27 +62,41 @@ NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_dr
guard = std::make_shared<std::mutex>(); guard = std::make_shared<std::mutex>();
// Schedule the screen composition events // Schedule the screen composition events
composition_event = Core::Timing::CreateEvent( multi_composition_event = Core::Timing::CreateEvent(
"ScreenComposition",
[this](std::uintptr_t, s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
vsync_signal.store(true);
vsync_signal.notify_all();
return std::chrono::nanoseconds(GetNextTicks());
});
single_composition_event = Core::Timing::CreateEvent(
"ScreenComposition", "ScreenComposition",
[this](std::uintptr_t, s64 time, [this](std::uintptr_t, s64 time,
std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
const auto lock_guard = Lock(); const auto lock_guard = Lock();
Compose(); Compose();
return std::max(std::chrono::nanoseconds::zero(), return std::chrono::nanoseconds(GetNextTicks());
std::chrono::nanoseconds(GetNextTicks()) - ns_late);
}); });
if (system.IsMulticore()) { if (system.IsMulticore()) {
system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event);
vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
} else { } else {
system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, composition_event); system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event);
} }
} }
NVFlinger::~NVFlinger() { NVFlinger::~NVFlinger() {
if (!system.IsMulticore()) { if (system.IsMulticore()) {
system.CoreTiming().UnscheduleEvent(composition_event, 0); system.CoreTiming().UnscheduleEvent(multi_composition_event, {});
vsync_thread.request_stop();
vsync_signal.store(true);
vsync_signal.notify_all();
} else {
system.CoreTiming().UnscheduleEvent(single_composition_event, {});
} }
for (auto& display : displays) { for (auto& display : displays) {

View File

@ -126,12 +126,15 @@ private:
u32 swap_interval = 1; u32 swap_interval = 1;
/// Event that handles screen composition. /// Event that handles screen composition.
std::shared_ptr<Core::Timing::EventType> composition_event; std::shared_ptr<Core::Timing::EventType> multi_composition_event;
std::shared_ptr<Core::Timing::EventType> single_composition_event;
std::shared_ptr<std::mutex> guard; std::shared_ptr<std::mutex> guard;
Core::System& system; Core::System& system;
std::atomic<bool> vsync_signal;
std::jthread vsync_thread; std::jthread vsync_thread;
KernelHelpers::ServiceContext service_context; KernelHelpers::ServiceContext service_context;