mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2025-06-12 12:37:56 -05:00
Services/NvFlinger: Do vSync in a sepparate thread on Multicore.
This commit is contained in:
@ -9,6 +9,7 @@
|
||||
#include "common/logging/log.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
#include "core/core_timing_util.h"
|
||||
@ -30,6 +31,33 @@ namespace Service::NVFlinger {
|
||||
constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60);
|
||||
constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30);
|
||||
|
||||
void NVFlinger::VSyncThread(NVFlinger& nv_flinger) {
|
||||
nv_flinger.SplitVSync();
|
||||
}
|
||||
|
||||
void NVFlinger::SplitVSync() {
|
||||
system.RegisterHostThread();
|
||||
std::string name = "yuzu:VSyncThread";
|
||||
MicroProfileOnThreadCreate(name.c_str());
|
||||
Common::SetCurrentThreadName(name.c_str());
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
||||
s64 delay = 0;
|
||||
while (is_running) {
|
||||
guard->lock();
|
||||
const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
|
||||
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();
|
||||
if (next_time > 0) {
|
||||
wait_event->WaitFor(std::chrono::nanoseconds{next_time});
|
||||
}
|
||||
delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
|
||||
}
|
||||
}
|
||||
|
||||
NVFlinger::NVFlinger(Core::System& system) : system(system) {
|
||||
displays.emplace_back(0, "Default", system);
|
||||
displays.emplace_back(1, "External", system);
|
||||
@ -47,12 +75,25 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
|
||||
this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),
|
||||
composition_event);
|
||||
});
|
||||
|
||||
system.CoreTiming().ScheduleEvent(frame_ticks, composition_event);
|
||||
if (system.IsMulticore()) {
|
||||
is_running = true;
|
||||
wait_event = std::make_unique<Common::Event>();
|
||||
vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this));
|
||||
} else {
|
||||
system.CoreTiming().ScheduleEvent(frame_ticks, composition_event);
|
||||
}
|
||||
}
|
||||
|
||||
NVFlinger::~NVFlinger() {
|
||||
system.CoreTiming().UnscheduleEvent(composition_event, 0);
|
||||
if (system.IsMulticore()) {
|
||||
is_running = false;
|
||||
wait_event->Set();
|
||||
vsync_thread->join();
|
||||
vsync_thread.reset();
|
||||
wait_event.reset();
|
||||
} else {
|
||||
system.CoreTiming().UnscheduleEvent(composition_event, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
|
||||
@ -200,10 +241,12 @@ void NVFlinger::Compose() {
|
||||
|
||||
auto& gpu = system.GPU();
|
||||
const auto& multi_fence = buffer->get().multi_fence;
|
||||
guard->unlock();
|
||||
for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
|
||||
const auto& fence = multi_fence.fences[fence_id];
|
||||
gpu.WaitFence(fence.id, fence.value);
|
||||
}
|
||||
guard->lock();
|
||||
|
||||
MicroProfileFlip();
|
||||
|
||||
|
Reference in New Issue
Block a user