From b8789af997e5932c098f2911f52b3e2a24d2d606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 29 Sep 2026 13:17:01 -0600 Subject: [PATCH] GPU: Draw frames displayed from RAM in non-buffered mode They were uploaded but never drawn, and the block transfer hack drew whatever source was left over. Draw them straight into the backbuffer pass, without post shaders, which would need to bind their own targets. Co-Authored-By: Claude Opus 5.5 (1M context) --- GPU/Common/FramebufferManagerCommon.cpp | 17 ++++++++++------- GPU/Common/PresentationCommon.cpp | 4 ++-- GPU/Common/PresentationCommon.h | 1 + 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 9250151122..47aaf4e621 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1557,14 +1557,19 @@ bool FramebufferManagerCommon::DrawFramebufferToOutput(const DisplayLayoutConfig if (needBackBufferYSwap_) { flags |= OutputFlags::BACKBUFFER_FLIPPED; } + if (!useBufferedRendering_) { + // We're inside the backbuffer pass, where nothing else will draw this image. + flags |= OutputFlags::NO_POST_SHADER; + } constexpr float u0 = 0.0f, u1 = 1.0f; constexpr float v0 = 0.0f, v1 = 1.0f; - if (useBufferedRendering_) { - presentation_->UpdateUniforms(gpu->VideoIsPlaying()); - presentation_->SourceTexture(pixelsTex, 480, 272); - presentation_->RunPostshaderPasses(config, flags, uvRotation, u0, v0, u1, v1); + presentation_->UpdateUniforms(gpu->VideoIsPlaying()); + presentation_->SourceTexture(pixelsTex, 480, 272); + presentation_->RunPostshaderPasses(config, flags, uvRotation, u0, v0, u1, v1); + if (!useBufferedRendering_) { + presentation_->CopyToOutput(config); } // PresentationCommon sets all kinds of state, we can't rely on anything. @@ -2863,9 +2868,7 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS if (isPrevDisplayBuffer || isDisplayBuffer) { FlushBeforeCopy(); // HACK - if (DrawFramebufferToOutput(displayLayoutConfigCopy_, Memory::GetPointerUnchecked(dstBasePtr), dstStride, displayFormat_)) { - presentation_->CopyToOutput(displayLayoutConfigCopy_); - } + DrawFramebufferToOutput(displayLayoutConfigCopy_, Memory::GetPointerUnchecked(dstBasePtr), dstStride, displayFormat_); return; } } diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index e96a91819b..09910c7db7 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -680,7 +680,7 @@ void PresentationCommon::RunPostshaderPasses(const DisplayLayoutConfig &config, bool useNearest = flags & OutputFlags::NEAREST; bool useStereo = gstate_c.Use(GPU_USE_SIMPLE_STEREO_PERSPECTIVE) && stereoPipeline_ != nullptr; // TODO: Also check that the backend has support for it. - const bool usePostShader = usePostShader_ && !useStereo && !(flags & OutputFlags::RB_SWIZZLE); + const bool usePostShader = usePostShader_ && !useStereo && !(flags & (OutputFlags::RB_SWIZZLE | OutputFlags::NO_POST_SHADER)); const bool isFinalAtOutputResolution = usePostShader && postShaderFramebuffers_.size() < postShaderPipelines_.size(); int lastWidth = srcWidth_; int lastHeight = srcHeight_; @@ -897,7 +897,7 @@ void PresentationCommon::CopyToOutput(const DisplayLayoutConfig &config) { bool useNearest = outputFlags_ & OutputFlags::NEAREST; bool useStereo = gstate_c.Use(GPU_USE_SIMPLE_STEREO_PERSPECTIVE) && stereoPipeline_ != nullptr; // TODO: Also check that the backend has support for it. - const bool usePostShader = usePostShader_ && !useStereo && !(outputFlags_ & OutputFlags::RB_SWIZZLE); + const bool usePostShader = usePostShader_ && !useStereo && !(outputFlags_ & (OutputFlags::RB_SWIZZLE | OutputFlags::NO_POST_SHADER)); const bool isFinalAtOutputResolution = usePostShader && postShaderFramebuffers_.size() < postShaderPipelines_.size(); int lastWidth = srcWidth_; int lastHeight = srcHeight_; diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index eb6caf1969..fe435b47b4 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -75,6 +75,7 @@ enum class OutputFlags { RB_SWIZZLE = 0x0002, BACKBUFFER_FLIPPED = 0x0004, // Viewport/scissor coordinates are y-flipped. PILLARBOX = 0x0010, // Squeeze the image horizontally. Used for the DarkStalkers hack. + NO_POST_SHADER = 0x0020, // Draw straight to the bound target, as post shaders would need to bind their own. }; ENUM_CLASS_BITOPS(OutputFlags);