From 4e9f975935b4208b29e158dabe62f8ad1122a447 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 25 Sep 2019 16:08:33 -0400 Subject: Nvdrv: Correct Async regression and avoid signaling empty buffer vsyncs --- src/core/hle/service/nvflinger/nvflinger.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service/nvflinger') diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 2e4d707b9..3b251f8c8 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -170,8 +170,13 @@ const VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { void NVFlinger::Compose() { for (auto& display : displays) { + bool trigger_event = false; // Trigger vsync for this display at the end of drawing - SCOPE_EXIT({ display.SignalVSyncEvent(); }); + SCOPE_EXIT({ + if (trigger_event) { + display.SignalVSyncEvent(); + } + }); // Don't do anything for displays without layers. if (!display.HasLayers()) @@ -194,6 +199,7 @@ void NVFlinger::Compose() { } const auto& igbp_buffer = buffer->get().igbp_buffer; + trigger_event = true; // Now send the buffer to the GPU for drawing. // TODO(Subv): Support more than just disp0. The display device selection is probably based -- cgit v1.2.3 From 5b5e60ffeca1a718cd980e74f0528d6ab91788cf Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Wed, 25 Sep 2019 19:43:23 -0400 Subject: GPU_Async: Correct fences, display events and more. This commit uses guest fences on vSync event instead of an articial fake fence we had. It also corrects to keep signaling display events while loading the game as the OS is suppose to send buffers to vSync during that time. --- src/core/hle/service/nvflinger/nvflinger.cpp | 21 +++++++++++++++++++-- src/core/hle/service/nvflinger/nvflinger.h | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/nvflinger') diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 3b251f8c8..86a90526c 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -36,6 +36,10 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) { displays.emplace_back(3, "Internal", system); displays.emplace_back(4, "Null", system); + for (auto& display : displays) { + display.SignalVSyncEvent(); + } + // Schedule the screen composition events composition_event = system.CoreTiming().RegisterEvent( "ScreenComposition", [this](u64 userdata, s64 cycles_late) { @@ -173,7 +177,13 @@ void NVFlinger::Compose() { bool trigger_event = false; // Trigger vsync for this display at the end of drawing SCOPE_EXIT({ - if (trigger_event) { + // TODO(Blinkhawk): Correctly send buffers through nvflinger while + // loading the game thorugh the OS. + // During loading, the OS takes care of sending buffers to vsync, + // thus it triggers, since this is not properly emulated due to + // HLE complications, we allow it to signal until the game enqueues + // it's first buffer. + if (trigger_event || !first_buffer_enqueued) { display.SignalVSyncEvent(); } }); @@ -193,13 +203,20 @@ void NVFlinger::Compose() { if (!buffer) { // There was no queued buffer to draw, render previous frame - system.GetPerfStats().EndGameFrame(); system.GPU().SwapBuffers({}); continue; } const auto& igbp_buffer = buffer->get().igbp_buffer; trigger_event = true; + first_buffer_enqueued = true; + + const auto& gpu = system.GPU(); + const auto& multi_fence = buffer->get().multi_fence; + 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); + } // Now send the buffer to the GPU for drawing. // TODO(Subv): Support more than just disp0. The display device selection is probably based diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 5d7e3bfb8..95d7278f5 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -102,6 +102,8 @@ private: u32 swap_interval = 1; + bool first_buffer_enqueued{}; + /// Event that handles screen composition. Core::Timing::EventType* composition_event; -- cgit v1.2.3 From 976d9ef43c6eb431a1963a2e5857c100eeacd952 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 26 Sep 2019 08:46:22 -0400 Subject: NvFlinger: Don't swap buffers if a frame is missing and always trigger event in sync gpu. --- src/core/hle/service/nvflinger/nvflinger.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service/nvflinger') diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 86a90526c..3c08ac9a3 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -203,7 +203,9 @@ void NVFlinger::Compose() { if (!buffer) { // There was no queued buffer to draw, render previous frame - system.GPU().SwapBuffers({}); + auto& gpu = system.GPU(); + // Always trigger on sync GPU. + trigger_event = !gpu.IsAsync(); continue; } -- cgit v1.2.3 From 782b7a0ca45b08d981e48a6d9a7af73cbed13281 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Thu, 26 Sep 2019 15:41:10 -0400 Subject: NVFlinger: Reverse the change that only signaled events on buffer acquire. This has been hardware tested and it seems that NVFlinger will still signal even if there are no buffers to present. --- src/core/hle/service/nvflinger/nvflinger.cpp | 19 +------------------ src/core/hle/service/nvflinger/nvflinger.h | 2 -- 2 files changed, 1 insertion(+), 20 deletions(-) (limited to 'src/core/hle/service/nvflinger') diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 3c08ac9a3..6eee20efe 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -174,19 +174,8 @@ const VI::Layer* NVFlinger::FindLayer(u64 display_id, u64 layer_id) const { void NVFlinger::Compose() { for (auto& display : displays) { - bool trigger_event = false; // Trigger vsync for this display at the end of drawing - SCOPE_EXIT({ - // TODO(Blinkhawk): Correctly send buffers through nvflinger while - // loading the game thorugh the OS. - // During loading, the OS takes care of sending buffers to vsync, - // thus it triggers, since this is not properly emulated due to - // HLE complications, we allow it to signal until the game enqueues - // it's first buffer. - if (trigger_event || !first_buffer_enqueued) { - display.SignalVSyncEvent(); - } - }); + SCOPE_EXIT({ display.SignalVSyncEvent(); }); // Don't do anything for displays without layers. if (!display.HasLayers()) @@ -202,16 +191,10 @@ void NVFlinger::Compose() { MicroProfileFlip(); if (!buffer) { - // There was no queued buffer to draw, render previous frame - auto& gpu = system.GPU(); - // Always trigger on sync GPU. - trigger_event = !gpu.IsAsync(); continue; } const auto& igbp_buffer = buffer->get().igbp_buffer; - trigger_event = true; - first_buffer_enqueued = true; const auto& gpu = system.GPU(); const auto& multi_fence = buffer->get().multi_fence; diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 95d7278f5..5d7e3bfb8 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -102,8 +102,6 @@ private: u32 swap_interval = 1; - bool first_buffer_enqueued{}; - /// Event that handles screen composition. Core::Timing::EventType* composition_event; -- cgit v1.2.3 From 75395605d69f3515c72437135ebafee80eba775c Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 27 Sep 2019 12:00:34 -0400 Subject: NvFlinger: Remove leftover from corrections and clang format. --- src/core/hle/service/nvflinger/nvflinger.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/core/hle/service/nvflinger') diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 6eee20efe..e00b665ea 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -36,10 +36,6 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) { displays.emplace_back(3, "Internal", system); displays.emplace_back(4, "Null", system); - for (auto& display : displays) { - display.SignalVSyncEvent(); - } - // Schedule the screen composition events composition_event = system.CoreTiming().RegisterEvent( "ScreenComposition", [this](u64 userdata, s64 cycles_late) { -- cgit v1.2.3