summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/core.cpp8
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp49
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h14
4 files changed, 69 insertions, 5 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 50656697f..8256ec0fc 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -294,8 +294,6 @@ struct System::Impl {
294 service_manager.reset(); 294 service_manager.reset();
295 cheat_engine.reset(); 295 cheat_engine.reset();
296 telemetry_session.reset(); 296 telemetry_session.reset();
297 perf_stats.reset();
298 gpu_core.reset();
299 device_memory.reset(); 297 device_memory.reset();
300 298
301 // Close all CPU/threading state 299 // Close all CPU/threading state
@@ -307,6 +305,8 @@ struct System::Impl {
307 305
308 // Close app loader 306 // Close app loader
309 app_loader.reset(); 307 app_loader.reset();
308 gpu_core.reset();
309 perf_stats.reset();
310 310
311 // Clear all applets 311 // Clear all applets
312 applet_manager.ClearAll(); 312 applet_manager.ClearAll();
@@ -764,4 +764,8 @@ void System::ExitDynarmicProfile() {
764 MicroProfileLeave(impl->microprofile_dynarmic[core], impl->dynarmic_ticks[core]); 764 MicroProfileLeave(impl->microprofile_dynarmic[core], impl->dynarmic_ticks[core]);
765} 765}
766 766
767bool System::IsMulticore() const {
768 return impl->is_multicore;
769}
770
767} // namespace Core 771} // namespace Core
diff --git a/src/core/core.h b/src/core/core.h
index d2d1fcc5b..133ecb8e1 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -381,6 +381,9 @@ public:
381 /// Exit Dynarmic Microprofile 381 /// Exit Dynarmic Microprofile
382 void ExitDynarmicProfile(); 382 void ExitDynarmicProfile();
383 383
384 /// Tells if system is running on multicore.
385 bool IsMulticore() const;
386
384private: 387private:
385 System(); 388 System();
386 389
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index b97f71350..2f44d3779 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -9,6 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/microprofile.h" 10#include "common/microprofile.h"
11#include "common/scope_exit.h" 11#include "common/scope_exit.h"
12#include "common/thread.h"
12#include "core/core.h" 13#include "core/core.h"
13#include "core/core_timing.h" 14#include "core/core_timing.h"
14#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
@@ -30,6 +31,33 @@ namespace Service::NVFlinger {
30constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60); 31constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60);
31constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30); 32constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30);
32 33
34void NVFlinger::VSyncThread(NVFlinger& nv_flinger) {
35 nv_flinger.SplitVSync();
36}
37
38void NVFlinger::SplitVSync() {
39 system.RegisterHostThread();
40 std::string name = "yuzu:VSyncThread";
41 MicroProfileOnThreadCreate(name.c_str());
42 Common::SetCurrentThreadName(name.c_str());
43 Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
44 s64 delay = 0;
45 while (is_running) {
46 guard->lock();
47 const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
48 Compose();
49 const auto ticks = GetNextTicks();
50 const s64 time_end = system.CoreTiming().GetGlobalTimeNs().count();
51 const s64 time_passed = time_end - time_start;
52 const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
53 guard->unlock();
54 if (next_time > 0) {
55 wait_event->WaitFor(std::chrono::nanoseconds{next_time});
56 }
57 delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
58 }
59}
60
33NVFlinger::NVFlinger(Core::System& system) : system(system) { 61NVFlinger::NVFlinger(Core::System& system) : system(system) {
34 displays.emplace_back(0, "Default", system); 62 displays.emplace_back(0, "Default", system);
35 displays.emplace_back(1, "External", system); 63 displays.emplace_back(1, "External", system);
@@ -47,12 +75,25 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
47 this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late), 75 this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),
48 composition_event); 76 composition_event);
49 }); 77 });
50 78 if (system.IsMulticore()) {
51 system.CoreTiming().ScheduleEvent(frame_ticks, composition_event); 79 is_running = true;
80 wait_event = std::make_unique<Common::Event>();
81 vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this));
82 } else {
83 system.CoreTiming().ScheduleEvent(frame_ticks, composition_event);
84 }
52} 85}
53 86
54NVFlinger::~NVFlinger() { 87NVFlinger::~NVFlinger() {
55 system.CoreTiming().UnscheduleEvent(composition_event, 0); 88 if (system.IsMulticore()) {
89 is_running = false;
90 wait_event->Set();
91 vsync_thread->join();
92 vsync_thread.reset();
93 wait_event.reset();
94 } else {
95 system.CoreTiming().UnscheduleEvent(composition_event, 0);
96 }
56} 97}
57 98
58void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) { 99void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
@@ -200,10 +241,12 @@ void NVFlinger::Compose() {
200 241
201 auto& gpu = system.GPU(); 242 auto& gpu = system.GPU();
202 const auto& multi_fence = buffer->get().multi_fence; 243 const auto& multi_fence = buffer->get().multi_fence;
244 guard->unlock();
203 for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) { 245 for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
204 const auto& fence = multi_fence.fences[fence_id]; 246 const auto& fence = multi_fence.fences[fence_id];
205 gpu.WaitFence(fence.id, fence.value); 247 gpu.WaitFence(fence.id, fence.value);
206 } 248 }
249 guard->lock();
207 250
208 MicroProfileFlip(); 251 MicroProfileFlip();
209 252
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 02c081494..4bc3d7ab2 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -4,16 +4,22 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
7#include <memory> 8#include <memory>
8#include <mutex> 9#include <mutex>
9#include <optional> 10#include <optional>
10#include <string> 11#include <string>
11#include <string_view> 12#include <string_view>
12#include <vector> 13#include <vector>
14#include <thread>
13 15
14#include "common/common_types.h" 16#include "common/common_types.h"
15#include "core/hle/kernel/object.h" 17#include "core/hle/kernel/object.h"
16 18
19namespace Common {
20class Event;
21} // namespace Common
22
17namespace Core::Timing { 23namespace Core::Timing {
18class CoreTiming; 24class CoreTiming;
19struct EventType; 25struct EventType;
@@ -97,6 +103,10 @@ private:
97 /// Finds the layer identified by the specified ID in the desired display. 103 /// Finds the layer identified by the specified ID in the desired display.
98 const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const; 104 const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const;
99 105
106 static void VSyncThread(NVFlinger& nv_flinger);
107
108 void SplitVSync();
109
100 std::shared_ptr<Nvidia::Module> nvdrv; 110 std::shared_ptr<Nvidia::Module> nvdrv;
101 111
102 std::vector<VI::Display> displays; 112 std::vector<VI::Display> displays;
@@ -116,6 +126,10 @@ private:
116 std::shared_ptr<std::mutex> guard; 126 std::shared_ptr<std::mutex> guard;
117 127
118 Core::System& system; 128 Core::System& system;
129
130 std::unique_ptr<std::thread> vsync_thread;
131 std::unique_ptr<Common::Event> wait_event;
132 std::atomic<bool> is_running{};
119}; 133};
120 134
121} // namespace Service::NVFlinger 135} // namespace Service::NVFlinger