From f08c873a4baeed8c04753ba9991824b47e992d1b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 19 May 2016 21:23:22 -0700 Subject: [PATCH] Save FBOs on decimate when they have a safe size. Fixes #7695. --- GPU/Directx9/FramebufferDX9.cpp | 15 ++++++++++++--- GPU/Directx9/FramebufferDX9.h | 2 +- GPU/Directx9/GPU_DX9.cpp | 4 ++-- GPU/GLES/Framebuffer.cpp | 15 ++++++++++++--- GPU/GLES/Framebuffer.h | 2 +- GPU/GLES/GPU_GLES.cpp | 6 +++--- GPU/Vulkan/FramebufferVulkan.cpp | 15 ++++++++++++--- GPU/Vulkan/FramebufferVulkan.h | 2 +- GPU/Vulkan/GPU_Vulkan.cpp | 6 +++--- 9 files changed, 47 insertions(+), 20 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 63ec3533f99f..66af073c10bb 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -1140,7 +1140,7 @@ namespace DX9 { void FramebufferManagerDX9::EndFrame() { if (resized_) { - DestroyAllFBOs(); + DestroyAllFBOs(false); // Actually, auto mode should be more granular... // Round up to a zoom factor for the render size. int zoom = g_Config.iInternalResolution; @@ -1173,7 +1173,7 @@ namespace DX9 { } void FramebufferManagerDX9::DeviceLost() { - DestroyAllFBOs(); + DestroyAllFBOs(false); resized_ = false; } @@ -1218,6 +1218,9 @@ namespace DX9 { if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { if (age > FBO_OLD_AGE) { INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age); + if (!g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) { + ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight); + } DestroyFramebuf(vfb); vfbs_.erase(vfbs_.begin() + i--); } @@ -1256,7 +1259,7 @@ namespace DX9 { } } - void FramebufferManagerDX9::DestroyAllFBOs() { + void FramebufferManagerDX9::DestroyAllFBOs(bool forceDelete) { fbo_unbind(); currentRenderVfb_ = 0; displayFramebuf_ = 0; @@ -1266,6 +1269,12 @@ namespace DX9 { for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *vfb = vfbs_[i]; INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); + if (!forceDelete && !g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) { + // But also let's check if Memory is shut down already. + if (Memory::IsActive()) { + ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight); + } + } DestroyFramebuf(vfb); } vfbs_.clear(); diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index 0063107981a4..3c8eec8aeee3 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -60,7 +60,7 @@ class FramebufferManagerDX9 : public FramebufferManagerCommon { void DrawActiveTexture(LPDIRECT3DTEXTURE9 texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation); - void DestroyAllFBOs(); + void DestroyAllFBOs(bool forceDelete); void EndFrame(); void Resized(); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 9e29ad3dd8db..62cab89c22f1 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -511,7 +511,7 @@ void GPU_DX9::CheckGPUFeatures() { } GPU_DX9::~GPU_DX9() { - framebufferManager_.DestroyAllFBOs(); + framebufferManager_.DestroyAllFBOs(true); shaderManager_->ClearCache(true); delete shaderManager_; } @@ -2137,7 +2137,7 @@ void GPU_DX9::DoState(PointerWrap &p) { drawEngine_.ClearTrackedVertexArrays(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_.DestroyAllFBOs(); + framebufferManager_.DestroyAllFBOs(true); shaderManager_->ClearCache(true); } } diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 8ecce9e131ef..1f09773f5e5c 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1784,7 +1784,7 @@ void FramebufferManager::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, void FramebufferManager::EndFrame() { if (resized_) { // TODO: Only do this if the new size actually changed the renderwidth/height. - DestroyAllFBOs(); + DestroyAllFBOs(false); // Probably not necessary glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); @@ -1854,7 +1854,7 @@ void FramebufferManager::EndFrame() { } void FramebufferManager::DeviceLost() { - DestroyAllFBOs(); + DestroyAllFBOs(false); DestroyDraw2DProgram(); resized_ = false; } @@ -1897,6 +1897,9 @@ void FramebufferManager::DecimateFBOs() { if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { if (age > FBO_OLD_AGE) { INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age); + if (!g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) { + ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight); + } DestroyFramebuf(vfb); vfbs_.erase(vfbs_.begin() + i--); } @@ -1925,7 +1928,7 @@ void FramebufferManager::DecimateFBOs() { } } -void FramebufferManager::DestroyAllFBOs() { +void FramebufferManager::DestroyAllFBOs(bool forceDelete) { fbo_unbind(); currentRenderVfb_ = 0; displayFramebuf_ = 0; @@ -1935,6 +1938,12 @@ void FramebufferManager::DestroyAllFBOs() { for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *vfb = vfbs_[i]; INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); + if (!forceDelete && !g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) { + // But also let's check if Memory is shut down already. + if (Memory::IsActive()) { + ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight); + } + } DestroyFramebuf(vfb); } vfbs_.clear(); diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 64e9390f982e..5efe76a67a9f 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -82,7 +82,7 @@ class FramebufferManager : public FramebufferManagerCommon { // x,y,w,h are relative to destW, destH which fill out the target completely. void DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation); - void DestroyAllFBOs(); + void DestroyAllFBOs(bool forceDelete); virtual void Init() override; void EndFrame(); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b542631a0a12..9b1034fa9bda 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -469,7 +469,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx) } GPU_GLES::~GPU_GLES() { - framebufferManager_.DestroyAllFBOs(); + framebufferManager_.DestroyAllFBOs(true); shaderManager_->ClearCache(true); depalShaderCache_.Clear(); fragmentTestCache_.Clear(); @@ -660,7 +660,7 @@ void GPU_GLES::Reinitialize() { void GPU_GLES::ReinitializeInternal() { textureCache_.Clear(true); depalShaderCache_.Clear(); - framebufferManager_.DestroyAllFBOs(); + framebufferManager_.DestroyAllFBOs(true); framebufferManager_.Resized(); } @@ -2401,7 +2401,7 @@ void GPU_GLES::DoState(PointerWrap &p) { drawEngine_.ClearTrackedVertexArrays(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_.DestroyAllFBOs(); + framebufferManager_.DestroyAllFBOs(true); shaderManager_->ClearCache(true); } } diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index bef4600ff616..b16a90eab7e3 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -1456,7 +1456,7 @@ void FramebufferManagerVulkan::BeginFrameVulkan() { void FramebufferManagerVulkan::EndFrame() { if (resized_) { // TODO: Only do this if the new size actually changed the renderwidth/height. - DestroyAllFBOs(); + DestroyAllFBOs(false); // Check if postprocessing shader is doing upscaling as it requires native resolution const ShaderInfo *shaderInfo = 0; @@ -1512,7 +1512,7 @@ void FramebufferManagerVulkan::EndFrame() { } void FramebufferManagerVulkan::DeviceLost() { - DestroyAllFBOs(); + DestroyAllFBOs(false); resized_ = false; } @@ -1553,6 +1553,9 @@ void FramebufferManagerVulkan::DecimateFBOs() { if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { if (age > FBO_OLD_AGE) { INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age); + if (!g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) { + ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight); + } DestroyFramebuf(vfb); vfbs_.erase(vfbs_.begin() + i--); } @@ -1560,7 +1563,7 @@ void FramebufferManagerVulkan::DecimateFBOs() { } } -void FramebufferManagerVulkan::DestroyAllFBOs() { +void FramebufferManagerVulkan::DestroyAllFBOs(bool forceDelete) { currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -1569,6 +1572,12 @@ void FramebufferManagerVulkan::DestroyAllFBOs() { for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *vfb = vfbs_[i]; INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); + if (!forceDelete && !g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) { + // But also let's check if Memory is shut down already. + if (Memory::IsActive()) { + ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight); + } + } DestroyFramebuf(vfb); } vfbs_.clear(); diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 9093375625cb..c6dd64864b2b 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -95,7 +95,7 @@ class FramebufferManagerVulkan : public FramebufferManagerCommon { // x,y,w,h are relative to destW, destH which fill out the target completely. void DrawTexture(VulkanTexture *texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, VkPipeline pipeline, int uvRotation); - void DestroyAllFBOs(); + void DestroyAllFBOs(bool forceDelete); virtual void Init() override; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 6f91e2ec7c22..97922f20c76d 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -455,7 +455,7 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx) } GPU_Vulkan::~GPU_Vulkan() { - framebufferManager_->DestroyAllFBOs(); + framebufferManager_->DestroyAllFBOs(true); depalShaderCache_.Clear(); delete framebufferManager_; delete pipelineManager_; @@ -614,7 +614,7 @@ void GPU_Vulkan::Reinitialize() { void GPU_Vulkan::ReinitializeInternal() { textureCache_.Clear(true); depalShaderCache_.Clear(); - framebufferManager_->DestroyAllFBOs(); + framebufferManager_->DestroyAllFBOs(true); framebufferManager_->Resized(); } @@ -2236,7 +2236,7 @@ void GPU_Vulkan::DoState(PointerWrap &p) { depalShaderCache_.Clear(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_->DestroyAllFBOs(); + framebufferManager_->DestroyAllFBOs(true); shaderManager_->ClearShaders(); pipelineManager_->Clear(); }