mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Services/NvFlinger: Do vSync in a sepparate thread on Multicore.
This commit is contained in:
		
							parent
							
								
									39ddce1ab5
								
							
						
					
					
						commit
						272a87127a
					
				@ -294,8 +294,6 @@ struct System::Impl {
 | 
				
			|||||||
        service_manager.reset();
 | 
					        service_manager.reset();
 | 
				
			||||||
        cheat_engine.reset();
 | 
					        cheat_engine.reset();
 | 
				
			||||||
        telemetry_session.reset();
 | 
					        telemetry_session.reset();
 | 
				
			||||||
        perf_stats.reset();
 | 
					 | 
				
			||||||
        gpu_core.reset();
 | 
					 | 
				
			||||||
        device_memory.reset();
 | 
					        device_memory.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Close all CPU/threading state
 | 
					        // Close all CPU/threading state
 | 
				
			||||||
@ -307,6 +305,8 @@ struct System::Impl {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Close app loader
 | 
					        // Close app loader
 | 
				
			||||||
        app_loader.reset();
 | 
					        app_loader.reset();
 | 
				
			||||||
 | 
					        gpu_core.reset();
 | 
				
			||||||
 | 
					        perf_stats.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Clear all applets
 | 
					        // Clear all applets
 | 
				
			||||||
        applet_manager.ClearAll();
 | 
					        applet_manager.ClearAll();
 | 
				
			||||||
@ -764,4 +764,8 @@ void System::ExitDynarmicProfile() {
 | 
				
			|||||||
    MicroProfileLeave(impl->microprofile_dynarmic[core], impl->dynarmic_ticks[core]);
 | 
					    MicroProfileLeave(impl->microprofile_dynarmic[core], impl->dynarmic_ticks[core]);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool System::IsMulticore() const {
 | 
				
			||||||
 | 
					    return impl->is_multicore;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Core
 | 
					} // namespace Core
 | 
				
			||||||
 | 
				
			|||||||
@ -381,6 +381,9 @@ public:
 | 
				
			|||||||
    /// Exit Dynarmic Microprofile
 | 
					    /// Exit Dynarmic Microprofile
 | 
				
			||||||
    void ExitDynarmicProfile();
 | 
					    void ExitDynarmicProfile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Tells if system is running on multicore.
 | 
				
			||||||
 | 
					    bool IsMulticore() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    System();
 | 
					    System();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@
 | 
				
			|||||||
#include "common/logging/log.h"
 | 
					#include "common/logging/log.h"
 | 
				
			||||||
#include "common/microprofile.h"
 | 
					#include "common/microprofile.h"
 | 
				
			||||||
#include "common/scope_exit.h"
 | 
					#include "common/scope_exit.h"
 | 
				
			||||||
 | 
					#include "common/thread.h"
 | 
				
			||||||
#include "core/core.h"
 | 
					#include "core/core.h"
 | 
				
			||||||
#include "core/core_timing.h"
 | 
					#include "core/core_timing.h"
 | 
				
			||||||
#include "core/core_timing_util.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 = static_cast<s64>(1000000000 / 60);
 | 
				
			||||||
constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30);
 | 
					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) {
 | 
					NVFlinger::NVFlinger(Core::System& system) : system(system) {
 | 
				
			||||||
    displays.emplace_back(0, "Default", system);
 | 
					    displays.emplace_back(0, "Default", system);
 | 
				
			||||||
    displays.emplace_back(1, "External", 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),
 | 
					            this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),
 | 
				
			||||||
                                                    composition_event);
 | 
					                                                    composition_event);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					    if (system.IsMulticore()) {
 | 
				
			||||||
    system.CoreTiming().ScheduleEvent(frame_ticks, composition_event);
 | 
					        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() {
 | 
					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) {
 | 
					void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
 | 
				
			||||||
@ -200,10 +241,12 @@ void NVFlinger::Compose() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        auto& gpu = system.GPU();
 | 
					        auto& gpu = system.GPU();
 | 
				
			||||||
        const auto& multi_fence = buffer->get().multi_fence;
 | 
					        const auto& multi_fence = buffer->get().multi_fence;
 | 
				
			||||||
 | 
					        guard->unlock();
 | 
				
			||||||
        for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
 | 
					        for (u32 fence_id = 0; fence_id < multi_fence.num_fences; fence_id++) {
 | 
				
			||||||
            const auto& fence = multi_fence.fences[fence_id];
 | 
					            const auto& fence = multi_fence.fences[fence_id];
 | 
				
			||||||
            gpu.WaitFence(fence.id, fence.value);
 | 
					            gpu.WaitFence(fence.id, fence.value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        guard->lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        MicroProfileFlip();
 | 
					        MicroProfileFlip();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,16 +4,22 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <atomic>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <mutex>
 | 
					#include <mutex>
 | 
				
			||||||
#include <optional>
 | 
					#include <optional>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <string_view>
 | 
					#include <string_view>
 | 
				
			||||||
#include <vector>
 | 
					#include <vector>
 | 
				
			||||||
 | 
					#include <thread>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "common/common_types.h"
 | 
					#include "common/common_types.h"
 | 
				
			||||||
#include "core/hle/kernel/object.h"
 | 
					#include "core/hle/kernel/object.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Common {
 | 
				
			||||||
 | 
					class Event;
 | 
				
			||||||
 | 
					} // namespace Common
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Core::Timing {
 | 
					namespace Core::Timing {
 | 
				
			||||||
class CoreTiming;
 | 
					class CoreTiming;
 | 
				
			||||||
struct EventType;
 | 
					struct EventType;
 | 
				
			||||||
@ -97,6 +103,10 @@ private:
 | 
				
			|||||||
    /// Finds the layer identified by the specified ID in the desired display.
 | 
					    /// Finds the layer identified by the specified ID in the desired display.
 | 
				
			||||||
    const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const;
 | 
					    const VI::Layer* FindLayer(u64 display_id, u64 layer_id) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static void VSyncThread(NVFlinger& nv_flinger);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void SplitVSync();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<Nvidia::Module> nvdrv;
 | 
					    std::shared_ptr<Nvidia::Module> nvdrv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<VI::Display> displays;
 | 
					    std::vector<VI::Display> displays;
 | 
				
			||||||
@ -116,6 +126,10 @@ private:
 | 
				
			|||||||
    std::shared_ptr<std::mutex> guard;
 | 
					    std::shared_ptr<std::mutex> guard;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Core::System& system;
 | 
					    Core::System& system;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::unique_ptr<std::thread> vsync_thread;
 | 
				
			||||||
 | 
					    std::unique_ptr<Common::Event> wait_event;
 | 
				
			||||||
 | 
					    std::atomic<bool> is_running{};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Service::NVFlinger
 | 
					} // namespace Service::NVFlinger
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user