From 3f8d645c42d71a7e4d053b7117188d5bf9216667 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Sun, 15 Dec 2024 15:55:28 +0100 Subject: [PATCH] rend: last frame was sometimes presented after the game is stopped When the clearLastFrame flag is set, renderers should return false from Present() and RenderLastFrame() until a new frame is rendered. --- core/rend/dx11/dx11_renderer.cpp | 2 ++ core/rend/dx11/dx11_renderer.h | 3 +-- core/rend/dx11/oit/dx11_oitrenderer.cpp | 1 + core/rend/dx9/d3d_renderer.cpp | 2 ++ core/rend/dx9/d3d_renderer.h | 3 +-- core/rend/gl4/gles.cpp | 1 + core/rend/gles/gldraw.cpp | 1 + core/rend/gles/gles.cpp | 1 + core/rend/gles/gles.h | 3 +-- core/rend/vulkan/oit/oit_renderer.cpp | 3 ++- core/rend/vulkan/vulkan_renderer.cpp | 10 ++++++++-- 11 files changed, 21 insertions(+), 9 deletions(-) diff --git a/core/rend/dx11/dx11_renderer.cpp b/core/rend/dx11/dx11_renderer.cpp index 199c586f1..ebb15ede2 100644 --- a/core/rend/dx11/dx11_renderer.cpp +++ b/core/rend/dx11/dx11_renderer.cpp @@ -525,6 +525,7 @@ bool DX11Renderer::Render() #endif frameRendered = true; frameRenderedOnce = true; + clearLastFrame = false; } return !is_rtt; @@ -1040,6 +1041,7 @@ void DX11Renderer::RenderFramebuffer(const FramebufferInfo& info) #endif frameRendered = true; frameRenderedOnce = true; + clearLastFrame = false; } void DX11Renderer::setBaseScissor() diff --git a/core/rend/dx11/dx11_renderer.h b/core/rend/dx11/dx11_renderer.h index c6d0ca63e..fb73fd7e8 100644 --- a/core/rend/dx11/dx11_renderer.h +++ b/core/rend/dx11/dx11_renderer.h @@ -42,10 +42,9 @@ struct DX11Renderer : public Renderer bool Present() override { - if (!frameRendered) + if (!frameRendered || clearLastFrame) return false; frameRendered = false; - clearLastFrame = false; #ifndef LIBRETRO imguiDriver->setFrameRendered(); #else diff --git a/core/rend/dx11/oit/dx11_oitrenderer.cpp b/core/rend/dx11/oit/dx11_oitrenderer.cpp index 5911cadf3..faaa430a9 100644 --- a/core/rend/dx11/oit/dx11_oitrenderer.cpp +++ b/core/rend/dx11/oit/dx11_oitrenderer.cpp @@ -694,6 +694,7 @@ struct DX11OITRenderer : public DX11Renderer #endif frameRendered = true; frameRenderedOnce = true; + clearLastFrame = false; } return !is_rtt; diff --git a/core/rend/dx9/d3d_renderer.cpp b/core/rend/dx9/d3d_renderer.cpp index ec77cb1c5..f3554a56d 100644 --- a/core/rend/dx9/d3d_renderer.cpp +++ b/core/rend/dx9/d3d_renderer.cpp @@ -302,6 +302,7 @@ void D3DRenderer::RenderFramebuffer(const FramebufferInfo& info) drawOSD(); frameRendered = true; frameRenderedOnce = true; + clearLastFrame = false; theDXContext.setFrameRendered(); } @@ -1181,6 +1182,7 @@ bool D3DRenderer::Render() drawOSD(); frameRendered = true; frameRenderedOnce = true; + clearLastFrame = false; theDXContext.setFrameRendered(); } diff --git a/core/rend/dx9/d3d_renderer.h b/core/rend/dx9/d3d_renderer.h index e6392131b..045c7a03e 100644 --- a/core/rend/dx9/d3d_renderer.h +++ b/core/rend/dx9/d3d_renderer.h @@ -106,11 +106,10 @@ struct D3DRenderer : public Renderer bool RenderLastFrame() override; bool Present() override { - if (!frameRendered) + if (!frameRendered || clearLastFrame) return false; imguiDriver->setFrameRendered(); frameRendered = false; - clearLastFrame = false; return true; } BaseTextureCacheData *GetTexture(TSP tsp, TCW tcw) override; diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 5cd12b6aa..ff0f64ec8 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -713,6 +713,7 @@ struct OpenGL4Renderer : OpenGLRenderer if (!config::EmulateFramebuffer) { frameRendered = true; + clearLastFrame = false; drawOSD(); renderVideoRouting(); } diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 01327cc26..d79d8e824 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -688,6 +688,7 @@ void OpenGLRenderer::RenderFramebuffer(const FramebufferInfo& info) drawOSD(); frameRendered = true; + clearLastFrame = false; renderVideoRouting(); restoreCurrentFramebuffer(); } diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index f9354131b..d2d7b7ffd 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -1361,6 +1361,7 @@ bool OpenGLRenderer::Render() if (!config::EmulateFramebuffer) { frameRendered = true; + clearLastFrame = false; drawOSD(); renderVideoRouting(); } diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index d5bb74252..13f3a1d71 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -516,12 +516,11 @@ struct OpenGLRenderer : Renderer bool Present() override { - if (!frameRendered) + if (!frameRendered || clearLastFrame) return false; #ifndef LIBRETRO imguiDriver->setFrameRendered(); #endif - clearLastFrame = false; frameRendered = false; return true; } diff --git a/core/rend/vulkan/oit/oit_renderer.cpp b/core/rend/vulkan/oit/oit_renderer.cpp index 8422f47d4..090808b16 100644 --- a/core/rend/vulkan/oit/oit_renderer.cpp +++ b/core/rend/vulkan/oit/oit_renderer.cpp @@ -105,7 +105,8 @@ class OITVulkanRenderer final : public BaseVulkanRenderer bool Present() override { - clearLastFrame = false; + if (clearLastFrame) + return false; if (config::EmulateFramebuffer || framebufferRendered) return presentFramebuffer(); else diff --git a/core/rend/vulkan/vulkan_renderer.cpp b/core/rend/vulkan/vulkan_renderer.cpp index 108073901..c40fc989b 100644 --- a/core/rend/vulkan/vulkan_renderer.cpp +++ b/core/rend/vulkan/vulkan_renderer.cpp @@ -86,7 +86,11 @@ BaseTextureCacheData *BaseVulkanRenderer::GetTexture(TSP tsp, TCW tcw) void BaseVulkanRenderer::Process(TA_context* ctx) { - framebufferRendered = false; + if (!ctx->rend.isRTT) { + framebufferRendered = false; + if (!config::EmulateFramebuffer) + clearLastFrame = false; + } if (resetTextureCache) { textureCache.Clear(); resetTextureCache = false; @@ -156,6 +160,7 @@ void BaseVulkanRenderer::RenderFramebuffer(const FramebufferInfo& info) commandBuffer.end(); fbCommandPool.EndFrame(); framebufferRendered = true; + clearLastFrame = false; } void BaseVulkanRenderer::RenderVideoRouting() @@ -300,7 +305,8 @@ class VulkanRenderer final : public BaseVulkanRenderer bool Present() override { - clearLastFrame = false; + if (clearLastFrame) + return false; if (config::EmulateFramebuffer || framebufferRendered) return presentFramebuffer(); else