From 7791cc8c2e585dcc377e22a26f548db914250a5d Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Tue, 24 Nov 2020 14:31:58 -0800
Subject: [PATCH] hle: services: Fix a crash with improper NVFlinger lifetime
 management. (#4977)

* hle: services: Fix a crash with improper NVFlinger lifetime management.

- This crash would happen when attempting to shutdown yuzu early on in boot.
---
 src/core/core.cpp                     |  9 +++--
 src/core/hle/service/am/am.cpp        | 17 ++++----
 src/core/hle/service/am/am.h          |  9 ++---
 src/core/hle/service/am/applet_ae.cpp | 21 +++++-----
 src/core/hle/service/am/applet_ae.h   |  4 +-
 src/core/hle/service/am/applet_oe.cpp | 14 +++----
 src/core/hle/service/am/applet_oe.h   |  4 +-
 src/core/hle/service/service.cpp      | 20 +++++-----
 src/core/hle/service/service.h        | 21 +++++++---
 src/core/hle/service/vi/vi.cpp        | 57 +++++++++++++--------------
 src/core/hle/service/vi/vi.h          |  7 ++--
 src/core/hle/service/vi/vi_m.cpp      |  3 +-
 src/core/hle/service/vi/vi_m.h        |  4 +-
 src/core/hle/service/vi/vi_s.cpp      |  3 +-
 src/core/hle/service/vi/vi_s.h        |  4 +-
 src/core/hle/service/vi/vi_u.cpp      |  3 +-
 src/core/hle/service/vi/vi_u.h        |  4 +-
 17 files changed, 104 insertions(+), 100 deletions(-)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index 5accdc783d..1aa477a291 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -187,7 +187,7 @@ struct System::Impl {
 
         service_manager = std::make_shared<Service::SM::ServiceManager>(kernel);
 
-        Service::Init(service_manager, system);
+        services = std::make_unique<Service::Services>(service_manager, system);
         GDBStub::DeferStart();
 
         interrupt_manager = std::make_unique<Core::Hardware::InterruptManager>(system);
@@ -296,7 +296,7 @@ struct System::Impl {
 
         // Shutdown emulation session
         GDBStub::Shutdown();
-        Service::Shutdown();
+        services.reset();
         service_manager.reset();
         cheat_engine.reset();
         telemetry_session.reset();
@@ -306,8 +306,8 @@ struct System::Impl {
         cpu_manager.Shutdown();
 
         // Shutdown kernel and core timing
-        kernel.Shutdown();
         core_timing.Shutdown();
+        kernel.Shutdown();
 
         // Close app loader
         app_loader.reset();
@@ -398,6 +398,9 @@ struct System::Impl {
     /// Service manager
     std::shared_ptr<Service::SM::ServiceManager> service_manager;
 
+    /// Services
+    std::unique_ptr<Service::Services> services;
+
     /// Telemetry session for this emulation session
     std::unique_ptr<Core::TelemetrySession> telemetry_session;
 
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 63421b9634..55e428456c 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -246,9 +246,8 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} {
 
 IDebugFunctions::~IDebugFunctions() = default;
 
-ISelfController::ISelfController(Core::System& system,
-                                 std::shared_ptr<NVFlinger::NVFlinger> nvflinger)
-    : ServiceFramework("ISelfController"), system(system), nvflinger(std::move(nvflinger)) {
+ISelfController::ISelfController(Core::System& system, NVFlinger::NVFlinger& nvflinger)
+    : ServiceFramework("ISelfController"), system(system), nvflinger(nvflinger) {
     // clang-format off
     static const FunctionInfo functions[] = {
         {0, &ISelfController::Exit, "Exit"},
@@ -458,8 +457,8 @@ void ISelfController::CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx)
 
     // TODO(Subv): Find out how AM determines the display to use, for now just
     // create the layer in the Default display.
-    const auto display_id = nvflinger->OpenDisplay("Default");
-    const auto layer_id = nvflinger->CreateLayer(*display_id);
+    const auto display_id = nvflinger.OpenDisplay("Default");
+    const auto layer_id = nvflinger.CreateLayer(*display_id);
 
     IPC::ResponseBuilder rb{ctx, 4};
     rb.Push(RESULT_SUCCESS);
@@ -476,8 +475,8 @@ void ISelfController::CreateManagedDisplaySeparableLayer(Kernel::HLERequestConte
     // Outputting 1 layer id instead of the expected 2 has not been observed to cause any adverse
     // side effects.
     // TODO: Support multiple layers
-    const auto display_id = nvflinger->OpenDisplay("Default");
-    const auto layer_id = nvflinger->CreateLayer(*display_id);
+    const auto display_id = nvflinger.OpenDisplay("Default");
+    const auto layer_id = nvflinger.CreateLayer(*display_id);
 
     IPC::ResponseBuilder rb{ctx, 4};
     rb.Push(RESULT_SUCCESS);
@@ -1586,8 +1585,8 @@ void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERe
     rb.PushCopyObjects(friend_invitation_storage_channel_event.readable);
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager,
-                       std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system) {
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
+                       Core::System& system) {
     auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel());
     // Needed on game boot
     message_queue->PushMessage(AppletMessageQueue::AppletMessage::FocusStateChanged);
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index bcc06affeb..09c2d05bcb 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -121,8 +121,7 @@ public:
 
 class ISelfController final : public ServiceFramework<ISelfController> {
 public:
-    explicit ISelfController(Core::System& system_,
-                             std::shared_ptr<NVFlinger::NVFlinger> nvflinger_);
+    explicit ISelfController(Core::System& system_, NVFlinger::NVFlinger& nvflinger_);
     ~ISelfController() override;
 
 private:
@@ -156,7 +155,7 @@ private:
     };
 
     Core::System& system;
-    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+    NVFlinger::NVFlinger& nvflinger;
     Kernel::EventPair launchable_event;
     Kernel::EventPair accumulated_suspended_tick_changed_event;
 
@@ -332,7 +331,7 @@ public:
 };
 
 /// Registers all AM services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager,
-                       std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system);
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nvflinger,
+                       Core::System& system);
 
 } // namespace Service::AM
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index be23ca747a..7de506b708 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -13,10 +13,10 @@ namespace Service::AM {
 
 class ILibraryAppletProxy final : public ServiceFramework<ILibraryAppletProxy> {
 public:
-    explicit ILibraryAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
+    explicit ILibraryAppletProxy(NVFlinger::NVFlinger& nvflinger,
                                  std::shared_ptr<AppletMessageQueue> msg_queue,
                                  Core::System& system)
-        : ServiceFramework("ILibraryAppletProxy"), nvflinger(std::move(nvflinger)),
+        : ServiceFramework("ILibraryAppletProxy"), nvflinger(nvflinger),
           msg_queue(std::move(msg_queue)), system(system) {
         // clang-format off
         static const FunctionInfo functions[] = {
@@ -109,16 +109,16 @@ private:
         rb.PushIpcInterface<IApplicationFunctions>(system);
     }
 
-    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+    NVFlinger::NVFlinger& nvflinger;
     std::shared_ptr<AppletMessageQueue> msg_queue;
     Core::System& system;
 };
 
 class ISystemAppletProxy final : public ServiceFramework<ISystemAppletProxy> {
 public:
-    explicit ISystemAppletProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
+    explicit ISystemAppletProxy(NVFlinger::NVFlinger& nvflinger,
                                 std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
-        : ServiceFramework("ISystemAppletProxy"), nvflinger(std::move(nvflinger)),
+        : ServiceFramework("ISystemAppletProxy"), nvflinger(nvflinger),
           msg_queue(std::move(msg_queue)), system(system) {
         // clang-format off
         static const FunctionInfo functions[] = {
@@ -220,7 +220,8 @@ private:
         rb.Push(RESULT_SUCCESS);
         rb.PushIpcInterface<IApplicationCreator>();
     }
-    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+
+    NVFlinger::NVFlinger& nvflinger;
     std::shared_ptr<AppletMessageQueue> msg_queue;
     Core::System& system;
 };
@@ -249,10 +250,10 @@ void AppletAE::OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx) {
     rb.PushIpcInterface<ILibraryAppletProxy>(nvflinger, msg_queue, system);
 }
 
-AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
-                   std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
-    : ServiceFramework("appletAE"), nvflinger(std::move(nvflinger)),
-      msg_queue(std::move(msg_queue)), system(system) {
+AppletAE::AppletAE(NVFlinger::NVFlinger& nvflinger, std::shared_ptr<AppletMessageQueue> msg_queue,
+                   Core::System& system)
+    : ServiceFramework("appletAE"), nvflinger(nvflinger), msg_queue(std::move(msg_queue)),
+      system(system) {
     // clang-format off
     static const FunctionInfo functions[] = {
         {100, &AppletAE::OpenSystemAppletProxy, "OpenSystemAppletProxy"},
diff --git a/src/core/hle/service/am/applet_ae.h b/src/core/hle/service/am/applet_ae.h
index 2e3e45915b..761844a1fe 100644
--- a/src/core/hle/service/am/applet_ae.h
+++ b/src/core/hle/service/am/applet_ae.h
@@ -23,7 +23,7 @@ class AppletMessageQueue;
 
 class AppletAE final : public ServiceFramework<AppletAE> {
 public:
-    explicit AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
+    explicit AppletAE(NVFlinger::NVFlinger& nvflinger,
                       std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system);
     ~AppletAE() override;
 
@@ -34,7 +34,7 @@ private:
     void OpenLibraryAppletProxy(Kernel::HLERequestContext& ctx);
     void OpenLibraryAppletProxyOld(Kernel::HLERequestContext& ctx);
 
-    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+    NVFlinger::NVFlinger& nvflinger;
     std::shared_ptr<AppletMessageQueue> msg_queue;
     Core::System& system;
 };
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp
index a2ffaa4408..7bed86ec42 100644
--- a/src/core/hle/service/am/applet_oe.cpp
+++ b/src/core/hle/service/am/applet_oe.cpp
@@ -12,9 +12,9 @@ namespace Service::AM {
 
 class IApplicationProxy final : public ServiceFramework<IApplicationProxy> {
 public:
-    explicit IApplicationProxy(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
+    explicit IApplicationProxy(NVFlinger::NVFlinger& nvflinger,
                                std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
-        : ServiceFramework("IApplicationProxy"), nvflinger(std::move(nvflinger)),
+        : ServiceFramework("IApplicationProxy"), nvflinger(nvflinger),
           msg_queue(std::move(msg_queue)), system(system) {
         // clang-format off
         static const FunctionInfo functions[] = {
@@ -98,7 +98,7 @@ private:
         rb.PushIpcInterface<IApplicationFunctions>(system);
     }
 
-    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+    NVFlinger::NVFlinger& nvflinger;
     std::shared_ptr<AppletMessageQueue> msg_queue;
     Core::System& system;
 };
@@ -111,10 +111,10 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) {
     rb.PushIpcInterface<IApplicationProxy>(nvflinger, msg_queue, system);
 }
 
-AppletOE::AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
-                   std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system)
-    : ServiceFramework("appletOE"), nvflinger(std::move(nvflinger)),
-      msg_queue(std::move(msg_queue)), system(system) {
+AppletOE::AppletOE(NVFlinger::NVFlinger& nvflinger, std::shared_ptr<AppletMessageQueue> msg_queue,
+                   Core::System& system)
+    : ServiceFramework("appletOE"), nvflinger(nvflinger), msg_queue(std::move(msg_queue)),
+      system(system) {
     static const FunctionInfo functions[] = {
         {0, &AppletOE::OpenApplicationProxy, "OpenApplicationProxy"},
     };
diff --git a/src/core/hle/service/am/applet_oe.h b/src/core/hle/service/am/applet_oe.h
index 758da792d9..88906d3545 100644
--- a/src/core/hle/service/am/applet_oe.h
+++ b/src/core/hle/service/am/applet_oe.h
@@ -23,7 +23,7 @@ class AppletMessageQueue;
 
 class AppletOE final : public ServiceFramework<AppletOE> {
 public:
-    explicit AppletOE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
+    explicit AppletOE(NVFlinger::NVFlinger& nvflinger,
                       std::shared_ptr<AppletMessageQueue> msg_queue, Core::System& system);
     ~AppletOE() override;
 
@@ -32,7 +32,7 @@ public:
 private:
     void OpenApplicationProxy(Kernel::HLERequestContext& ctx);
 
-    std::shared_ptr<NVFlinger::NVFlinger> nvflinger;
+    NVFlinger::NVFlinger& nvflinger;
     std::shared_ptr<AppletMessageQueue> msg_queue;
     Core::System& system;
 };
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index fbfda2d5b8..fb4979af27 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -188,17 +188,19 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
     return RESULT_SUCCESS;
 }
 
-/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {
+/// Initialize Services
+Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system)
+    : nv_flinger{std::make_unique<NVFlinger::NVFlinger>(system)} {
+
     // NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
     // here and pass it into the respective InstallInterfaces functions.
-    auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>(system);
+
     system.GetFileSystemController().CreateFactories(*system.GetFilesystem(), false);
 
     SM::ServiceManager::InstallInterfaces(sm, system.Kernel());
 
     Account::InstallInterfaces(system);
-    AM::InstallInterfaces(*sm, nv_flinger, system);
+    AM::InstallInterfaces(*sm, *nv_flinger, system);
     AOC::InstallInterfaces(*sm, system);
     APM::InstallInterfaces(system);
     Audio::InstallInterfaces(*sm, system);
@@ -246,14 +248,10 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) {
     SSL::InstallInterfaces(*sm);
     Time::InstallInterfaces(system);
     USB::InstallInterfaces(*sm);
-    VI::InstallInterfaces(*sm, nv_flinger);
+    VI::InstallInterfaces(*sm, *nv_flinger);
     WLAN::InstallInterfaces(*sm);
-
-    LOG_DEBUG(Service, "initialized OK");
 }
 
-/// Shutdown ServiceManager
-void Shutdown() {
-    LOG_DEBUG(Service, "shutdown OK");
-}
+Services::~Services() = default;
+
 } // namespace Service
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index a01ef33532..ed47922891 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -29,7 +29,11 @@ namespace Service {
 
 namespace FileSystem {
 class FileSystemController;
-} // namespace FileSystem
+}
+
+namespace NVFlinger {
+class NVFlinger;
+}
 
 namespace SM {
 class ServiceManager;
@@ -181,10 +185,17 @@ private:
     }
 };
 
-/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
+/**
+ * The purpose of this class is to own any objects that need to be shared across the other service
+ * implementations. Will be torn down when the global system instance is shutdown.
+ */
+class Services final {
+public:
+    explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
+    ~Services();
 
-/// Shutdown ServiceManager
-void Shutdown();
+private:
+    std::unique_ptr<NVFlinger::NVFlinger> nv_flinger;
+};
 
 } // namespace Service
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 55e00dd93b..86bd604f4a 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -492,8 +492,8 @@ private:
 
 class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
 public:
-    explicit IHOSBinderDriver(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
-        : ServiceFramework("IHOSBinderDriver"), nv_flinger(std::move(nv_flinger)) {
+    explicit IHOSBinderDriver(NVFlinger::NVFlinger& nv_flinger)
+        : ServiceFramework("IHOSBinderDriver"), nv_flinger(nv_flinger) {
         static const FunctionInfo functions[] = {
             {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
             {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
@@ -530,8 +530,8 @@ private:
         LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
                   static_cast<u32>(transaction), flags);
 
-        const auto guard = nv_flinger->Lock();
-        auto& buffer_queue = nv_flinger->FindBufferQueue(id);
+        const auto guard = nv_flinger.Lock();
+        auto& buffer_queue = nv_flinger.FindBufferQueue(id);
 
         switch (transaction) {
         case TransactionId::Connect: {
@@ -570,8 +570,8 @@ private:
                     [=, this](std::shared_ptr<Kernel::Thread> thread,
                               Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) {
                         // Repeat TransactParcel DequeueBuffer when a buffer is available
-                        const auto guard = nv_flinger->Lock();
-                        auto& buffer_queue = nv_flinger->FindBufferQueue(id);
+                        const auto guard = nv_flinger.Lock();
+                        auto& buffer_queue = nv_flinger.FindBufferQueue(id);
                         auto result = buffer_queue.DequeueBuffer(width, height);
                         ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
 
@@ -676,7 +676,7 @@ private:
 
         LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
 
-        const auto& buffer_queue = nv_flinger->FindBufferQueue(id);
+        const auto& buffer_queue = nv_flinger.FindBufferQueue(id);
 
         // TODO(Subv): Find out what this actually is.
         IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -684,8 +684,8 @@ private:
         rb.PushCopyObjects(buffer_queue.GetBufferWaitEvent());
     }
 
-    std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
-}; // namespace VI
+    NVFlinger::NVFlinger& nv_flinger;
+};
 
 class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
 public:
@@ -790,8 +790,8 @@ private:
 
 class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
 public:
-    explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
-        : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) {
+    explicit IManagerDisplayService(NVFlinger::NVFlinger& nv_flinger)
+        : ServiceFramework("IManagerDisplayService"), nv_flinger(nv_flinger) {
         // clang-format off
         static const FunctionInfo functions[] = {
             {200, nullptr, "AllocateProcessHeapBlock"},
@@ -893,7 +893,7 @@ private:
                     "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
                     unknown, display, aruid);
 
-        const auto layer_id = nv_flinger->CreateLayer(display);
+        const auto layer_id = nv_flinger.CreateLayer(display);
         if (!layer_id) {
             LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
             IPC::ResponseBuilder rb{ctx, 2};
@@ -930,12 +930,12 @@ private:
         rb.Push(RESULT_SUCCESS);
     }
 
-    std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
+    NVFlinger::NVFlinger& nv_flinger;
 };
 
 class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
 public:
-    explicit IApplicationDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
+    explicit IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger);
 
 private:
     enum class ConvertedScaleMode : u64 {
@@ -1010,7 +1010,7 @@ private:
 
         ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
 
-        const auto display_id = nv_flinger->OpenDisplay(name);
+        const auto display_id = nv_flinger.OpenDisplay(name);
         if (!display_id) {
             LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
             IPC::ResponseBuilder rb{ctx, 2};
@@ -1110,7 +1110,7 @@ private:
 
         LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
 
-        const auto display_id = nv_flinger->OpenDisplay(display_name);
+        const auto display_id = nv_flinger.OpenDisplay(display_name);
         if (!display_id) {
             LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
             IPC::ResponseBuilder rb{ctx, 2};
@@ -1118,7 +1118,7 @@ private:
             return;
         }
 
-        const auto buffer_queue_id = nv_flinger->FindBufferQueueId(*display_id, layer_id);
+        const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id);
         if (!buffer_queue_id) {
             LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
             IPC::ResponseBuilder rb{ctx, 2};
@@ -1138,7 +1138,7 @@ private:
 
         LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
 
-        nv_flinger->CloseLayer(layer_id);
+        nv_flinger.CloseLayer(layer_id);
 
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_SUCCESS);
@@ -1154,7 +1154,7 @@ private:
 
         // TODO(Subv): What's the difference between a Stray and a Managed layer?
 
-        const auto layer_id = nv_flinger->CreateLayer(display_id);
+        const auto layer_id = nv_flinger.CreateLayer(display_id);
         if (!layer_id) {
             LOG_ERROR(Service_VI, "Layer not found! layer_id={}", *layer_id);
             IPC::ResponseBuilder rb{ctx, 2};
@@ -1162,7 +1162,7 @@ private:
             return;
         }
 
-        const auto buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, *layer_id);
+        const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id);
         if (!buffer_queue_id) {
             LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
             IPC::ResponseBuilder rb{ctx, 2};
@@ -1193,7 +1193,7 @@ private:
 
         LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
 
-        const auto vsync_event = nv_flinger->FindVsyncEvent(display_id);
+        const auto vsync_event = nv_flinger.FindVsyncEvent(display_id);
         if (!vsync_event) {
             LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
             IPC::ResponseBuilder rb{ctx, 2};
@@ -1258,12 +1258,11 @@ private:
         }
     }
 
-    std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
+    NVFlinger::NVFlinger& nv_flinger;
 };
 
-IApplicationDisplayService::IApplicationDisplayService(
-    std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
-    : ServiceFramework("IApplicationDisplayService"), nv_flinger(std::move(nv_flinger)) {
+IApplicationDisplayService::IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger)
+    : ServiceFramework("IApplicationDisplayService"), nv_flinger(nv_flinger) {
     static const FunctionInfo functions[] = {
         {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
         {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
@@ -1304,8 +1303,7 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {
     return false;
 }
 
-void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx,
-                                   std::shared_ptr<NVFlinger::NVFlinger> nv_flinger,
+void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, NVFlinger::NVFlinger& nv_flinger,
                                    Permission permission) {
     IPC::RequestParser rp{ctx};
     const auto policy = rp.PopEnum<Policy>();
@@ -1319,11 +1317,10 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx,
 
     IPC::ResponseBuilder rb{ctx, 2, 0, 1};
     rb.Push(RESULT_SUCCESS);
-    rb.PushIpcInterface<IApplicationDisplayService>(std::move(nv_flinger));
+    rb.PushIpcInterface<IApplicationDisplayService>(nv_flinger);
 }
 
-void InstallInterfaces(SM::ServiceManager& service_manager,
-                       std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) {
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nv_flinger) {
     std::make_shared<VI_M>(nv_flinger)->InstallAsService(service_manager);
     std::make_shared<VI_S>(nv_flinger)->InstallAsService(service_manager);
     std::make_shared<VI_U>(nv_flinger)->InstallAsService(service_manager);
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h
index 6b66f8b811..5229fa753e 100644
--- a/src/core/hle/service/vi/vi.h
+++ b/src/core/hle/service/vi/vi.h
@@ -43,12 +43,11 @@ enum class Policy {
 };
 
 namespace detail {
-void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx,
-                           std::shared_ptr<NVFlinger::NVFlinger> nv_flinger, Permission permission);
+void GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, NVFlinger::NVFlinger& nv_flinger,
+                           Permission permission);
 } // namespace detail
 
 /// Registers all VI services with the specified service manager.
-void InstallInterfaces(SM::ServiceManager& service_manager,
-                       std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
+void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nv_flinger);
 
 } // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_m.cpp b/src/core/hle/service/vi/vi_m.cpp
index 06070087f8..41da3ee936 100644
--- a/src/core/hle/service/vi/vi_m.cpp
+++ b/src/core/hle/service/vi/vi_m.cpp
@@ -8,8 +8,7 @@
 
 namespace Service::VI {
 
-VI_M::VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
-    : ServiceFramework{"vi:m"}, nv_flinger{std::move(nv_flinger)} {
+VI_M::VI_M(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:m"}, nv_flinger{nv_flinger} {
     static const FunctionInfo functions[] = {
         {2, &VI_M::GetDisplayService, "GetDisplayService"},
         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
diff --git a/src/core/hle/service/vi/vi_m.h b/src/core/hle/service/vi/vi_m.h
index 290e066891..ee24898749 100644
--- a/src/core/hle/service/vi/vi_m.h
+++ b/src/core/hle/service/vi/vi_m.h
@@ -18,13 +18,13 @@ namespace Service::VI {
 
 class VI_M final : public ServiceFramework<VI_M> {
 public:
-    explicit VI_M(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
+    explicit VI_M(NVFlinger::NVFlinger& nv_flinger);
     ~VI_M() override;
 
 private:
     void GetDisplayService(Kernel::HLERequestContext& ctx);
 
-    std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
+    NVFlinger::NVFlinger& nv_flinger;
 };
 
 } // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_s.cpp b/src/core/hle/service/vi/vi_s.cpp
index 57c596cc43..6acb51e2a9 100644
--- a/src/core/hle/service/vi/vi_s.cpp
+++ b/src/core/hle/service/vi/vi_s.cpp
@@ -8,8 +8,7 @@
 
 namespace Service::VI {
 
-VI_S::VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
-    : ServiceFramework{"vi:s"}, nv_flinger{std::move(nv_flinger)} {
+VI_S::VI_S(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:s"}, nv_flinger{nv_flinger} {
     static const FunctionInfo functions[] = {
         {1, &VI_S::GetDisplayService, "GetDisplayService"},
         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
diff --git a/src/core/hle/service/vi/vi_s.h b/src/core/hle/service/vi/vi_s.h
index 47804dc0be..6790673ab6 100644
--- a/src/core/hle/service/vi/vi_s.h
+++ b/src/core/hle/service/vi/vi_s.h
@@ -18,13 +18,13 @@ namespace Service::VI {
 
 class VI_S final : public ServiceFramework<VI_S> {
 public:
-    explicit VI_S(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
+    explicit VI_S(NVFlinger::NVFlinger& nv_flinger);
     ~VI_S() override;
 
 private:
     void GetDisplayService(Kernel::HLERequestContext& ctx);
 
-    std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
+    NVFlinger::NVFlinger& nv_flinger;
 };
 
 } // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi_u.cpp b/src/core/hle/service/vi/vi_u.cpp
index 6b73293459..44e00a4f60 100644
--- a/src/core/hle/service/vi/vi_u.cpp
+++ b/src/core/hle/service/vi/vi_u.cpp
@@ -8,8 +8,7 @@
 
 namespace Service::VI {
 
-VI_U::VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
-    : ServiceFramework{"vi:u"}, nv_flinger{std::move(nv_flinger)} {
+VI_U::VI_U(NVFlinger::NVFlinger& nv_flinger) : ServiceFramework{"vi:u"}, nv_flinger{nv_flinger} {
     static const FunctionInfo functions[] = {
         {0, &VI_U::GetDisplayService, "GetDisplayService"},
         {1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
diff --git a/src/core/hle/service/vi/vi_u.h b/src/core/hle/service/vi/vi_u.h
index 19bdb73b0b..b59f986f09 100644
--- a/src/core/hle/service/vi/vi_u.h
+++ b/src/core/hle/service/vi/vi_u.h
@@ -18,13 +18,13 @@ namespace Service::VI {
 
 class VI_U final : public ServiceFramework<VI_U> {
 public:
-    explicit VI_U(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger);
+    explicit VI_U(NVFlinger::NVFlinger& nv_flinger);
     ~VI_U() override;
 
 private:
     void GetDisplayService(Kernel::HLERequestContext& ctx);
 
-    std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
+    NVFlinger::NVFlinger& nv_flinger;
 };
 
 } // namespace Service::VI