From 989768aa46720e3fcab9e2111e3ddd70819c382b Mon Sep 17 00:00:00 2001 From: John Date: Mon, 19 Oct 2026 15:58:04 +0200 Subject: [PATCH] Fix [core, gpu, threads] Multithreading refactor (#4254) (#4548) Performance loss regression fixed in Link's Awakening, Castlevania, Super Mario RPG, etc Tested by Mr. Knobs on Android and myself on Linux Multicore ON may be fixed for some users using Intel CPUs. Games include: FF Tactics, Shredder's Revenge, Unity Engine Games. - [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md). - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4548 Reviewed-by: Maufeat Reviewed-by: lizzie --- .../service/nvnflinger/hardware_composer.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp index 5decb791e1..9ac56e17bb 100644 --- a/src/core/hle/service/nvnflinger/hardware_composer.cpp +++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp @@ -57,8 +57,21 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display, // Set default speed limit to 100%. *out_speed_scale = 1.0f; + // If no layers are visible, skip the logic. Acquiring and holding buffers here would + // consume the producer's queue without ever presenting. + bool any_visible = false; + for (auto& layer : display.stack.layers) { + if (layer->visible) { + any_visible = true; + break; + } + } + if (!any_visible) { + return 1; + } + + // Wait for the previous composite, bounding the number of in-flight composites. nvdisp.WaitForComposite(); - this->ReleaseFramebuffersLocked(display); // Determine the number of vsync periods to wait before composing again. std::optional swap_interval{}; @@ -152,6 +165,13 @@ u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, Display& display, // Advance by 1 frame (60 FPS compositing) m_frame_number += 1; + // Release framebuffers once the frame has been handed to the compositor. This happens + // within the same vsync period as the acquire (release_frame_number is checked against + // the advanced counter), so the producer gets its buffers back immediately instead of + // losing a queue slot for a whole frame. + // TODO: support release fences; releasing before the composite has finished can tear. + this->ReleaseFramebuffersLocked(display); + return 1; }