summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Kelebek12022-07-26 22:04:18 +0100
committerGravatar Morph2022-08-01 23:51:53 -0400
commit9d3b1904651321f44b8f801bc0452390afc16ffc (patch)
treeea5ac3344ba73a58ff1499f1d4e49479cdec7489 /src
parentMerge pull request #8701 from liamwhite/elf (diff)
downloadyuzu-9d3b1904651321f44b8f801bc0452390afc16ffc.tar.gz
yuzu-9d3b1904651321f44b8f801bc0452390afc16ffc.tar.xz
yuzu-9d3b1904651321f44b8f801bc0452390afc16ffc.zip
Rework multi-core vsync
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp42
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h5
2 files changed, 30 insertions, 17 deletions
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 5574269eb..9b382bf56 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -38,20 +38,16 @@ void NVFlinger::SplitVSync(std::stop_token stop_token) {
38 38
39 Common::SetCurrentThreadName(name.c_str()); 39 Common::SetCurrentThreadName(name.c_str());
40 Common::SetCurrentThreadPriority(Common::ThreadPriority::High); 40 Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
41 s64 delay = 0; 41
42 while (!stop_token.stop_requested()) { 42 while (!stop_token.stop_requested()) {
43 vsync_signal.wait(false);
44 vsync_signal.store(false);
45
43 guard->lock(); 46 guard->lock();
44 const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count(); 47
45 Compose(); 48 Compose();
46 const auto ticks = GetNextTicks(); 49
47 const s64 time_end = system.CoreTiming().GetGlobalTimeNs().count();
48 const s64 time_passed = time_end - time_start;
49 const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
50 guard->unlock(); 50 guard->unlock();
51 if (next_time > 0) {
52 std::this_thread::sleep_for(std::chrono::nanoseconds{next_time});
53 }
54 delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
55 } 51 }
56} 52}
57 53
@@ -66,27 +62,41 @@ NVFlinger::NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_dr
66 guard = std::make_shared<std::mutex>(); 62 guard = std::make_shared<std::mutex>();
67 63
68 // Schedule the screen composition events 64 // Schedule the screen composition events
69 composition_event = Core::Timing::CreateEvent( 65 multi_composition_event = Core::Timing::CreateEvent(
66 "ScreenComposition",
67 [this](std::uintptr_t, s64 time,
68 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
69 vsync_signal.store(true);
70 vsync_signal.notify_all();
71 return std::chrono::nanoseconds(GetNextTicks());
72 });
73
74 single_composition_event = Core::Timing::CreateEvent(
70 "ScreenComposition", 75 "ScreenComposition",
71 [this](std::uintptr_t, s64 time, 76 [this](std::uintptr_t, s64 time,
72 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> { 77 std::chrono::nanoseconds ns_late) -> std::optional<std::chrono::nanoseconds> {
73 const auto lock_guard = Lock(); 78 const auto lock_guard = Lock();
74 Compose(); 79 Compose();
75 80
76 return std::max(std::chrono::nanoseconds::zero(), 81 return std::chrono::nanoseconds(GetNextTicks());
77 std::chrono::nanoseconds(GetNextTicks()) - ns_late);
78 }); 82 });
79 83
80 if (system.IsMulticore()) { 84 if (system.IsMulticore()) {
85 system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, multi_composition_event);
81 vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); 86 vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
82 } else { 87 } else {
83 system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, composition_event); 88 system.CoreTiming().ScheduleLoopingEvent(frame_ns, frame_ns, single_composition_event);
84 } 89 }
85} 90}
86 91
87NVFlinger::~NVFlinger() { 92NVFlinger::~NVFlinger() {
88 if (!system.IsMulticore()) { 93 if (system.IsMulticore()) {
89 system.CoreTiming().UnscheduleEvent(composition_event, 0); 94 system.CoreTiming().UnscheduleEvent(multi_composition_event, {});
95 vsync_thread.request_stop();
96 vsync_signal.store(true);
97 vsync_signal.notify_all();
98 } else {
99 system.CoreTiming().UnscheduleEvent(single_composition_event, {});
90 } 100 }
91 101
92 for (auto& display : displays) { 102 for (auto& display : displays) {
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 4775597cc..044ac6ac8 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -126,12 +126,15 @@ private:
126 u32 swap_interval = 1; 126 u32 swap_interval = 1;
127 127
128 /// Event that handles screen composition. 128 /// Event that handles screen composition.
129 std::shared_ptr<Core::Timing::EventType> composition_event; 129 std::shared_ptr<Core::Timing::EventType> multi_composition_event;
130 std::shared_ptr<Core::Timing::EventType> single_composition_event;
130 131
131 std::shared_ptr<std::mutex> guard; 132 std::shared_ptr<std::mutex> guard;
132 133
133 Core::System& system; 134 Core::System& system;
134 135
136 std::atomic<bool> vsync_signal;
137
135 std::jthread vsync_thread; 138 std::jthread vsync_thread;
136 139
137 KernelHelpers::ServiceContext service_context; 140 KernelHelpers::ServiceContext service_context;