From c9a9fc5e44c111d1e25db67570d1e9f9add41680 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 5 Jun 2016 21:34:06 -0700 Subject: [PATCH] Allow block transfers to resize framebuffers. Helps the ending video in Valkyrie Profile. See #6008. --- GPU/Common/FramebufferCommon.cpp | 5 +++++ GPU/Common/FramebufferCommon.h | 2 +- GPU/Directx9/FramebufferDX9.cpp | 4 ++-- GPU/Directx9/FramebufferDX9.h | 4 ++-- GPU/GLES/Framebuffer.cpp | 4 ++-- GPU/GLES/Framebuffer.h | 2 +- GPU/Vulkan/FramebufferVulkan.cpp | 4 ++-- GPU/Vulkan/FramebufferVulkan.h | 2 +- 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 447c10a26199..2f2bbb7f9851 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -953,6 +953,11 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS const u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp; int dstBpp = dstBuffer->format == GE_FORMAT_8888 ? 4 : 2; float dstXFactor = (float)bpp / dstBpp; + if (dstWidth > dstBuffer->width || dstHeight > dstBuffer->height) { + // The buffer isn't big enough, and we have a clear hint of size. Resize. + // This happens in Valkyrie Profile when uploading video at the ending. + ResizeFramebufFBO(dstBuffer, dstWidth, dstHeight, false, true); + } DrawPixels(dstBuffer, static_cast(dstX * dstXFactor), dstY, srcBase, dstBuffer->format, static_cast(srcStride * dstXFactor), static_cast(dstWidth * dstXFactor), dstHeight); SetColorUpdated(dstBuffer, skipDrawReason); RebindFramebuffer(); diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 8a13b4400257..7fa99ff9df9b 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -245,7 +245,7 @@ class FramebufferManagerCommon { static bool MaskedEqual(u32 addr1, u32 addr2); virtual void DestroyFramebuf(VirtualFramebuffer *vfb) = 0; - virtual void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false) = 0; + virtual void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) = 0; virtual void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) = 0; virtual void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) = 0; virtual void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) = 0; diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index d0d9a9aa1a6c..b934d4bfd863 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -302,7 +302,7 @@ namespace DX9 { } } - void FramebufferManagerDX9::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force) { + void FramebufferManagerDX9::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) { VirtualFramebuffer old = *vfb; if (force) { @@ -362,7 +362,7 @@ namespace DX9 { if (vfb->fbo) { fbo_bind_as_render_target(vfb->fbo_dx9); ClearBuffer(); - if (!g_Config.bDisableSlowFramebufEffects) { + if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0); } } diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index 4c703f25c621..3835b9669fec 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -79,8 +79,8 @@ class FramebufferManagerDX9 : public FramebufferManagerCommon { virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - void DestroyFramebuf(VirtualFramebuffer *vfb); - void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false); + void DestroyFramebuf(VirtualFramebuffer *vfb) override; + void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override; bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, int maxRes); bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index fad46a918558..4bc92f3bf161 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -557,7 +557,7 @@ void FramebufferManager::RebindFramebuffer() { glstate.viewport.restore(); } -void FramebufferManager::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force) { +void FramebufferManager::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) { VirtualFramebuffer old = *vfb; if (force) { @@ -617,7 +617,7 @@ void FramebufferManager::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h if (vfb->fbo) { fbo_bind_as_render_target(vfb->fbo); ClearBuffer(); - if (!g_Config.bDisableSlowFramebufEffects) { + if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0); } } diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index cdc39fc81b8e..dc0070e2d3de 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -106,7 +106,7 @@ class FramebufferManager : public FramebufferManagerCommon { bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; void DestroyFramebuf(VirtualFramebuffer *vfb) override; - void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false) override; + void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override; bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes); bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer); diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 9cda132f25d6..52d8f8e103d8 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -533,7 +533,7 @@ void FramebufferManagerVulkan::RebindFramebuffer() { // Switch command buffer? } -void FramebufferManagerVulkan::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force) { +void FramebufferManagerVulkan::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) { return; /* @@ -596,7 +596,7 @@ void FramebufferManagerVulkan::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, if (vfb->fbo_vk) { /// fbo_bind_as_render_target(vfb->fbo_vk); ClearBuffer(); - if (!g_Config.bDisableSlowFramebufEffects) { + if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0); } } diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 46142a6df3a5..a613af694a17 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -122,7 +122,7 @@ class FramebufferManagerVulkan : public FramebufferManagerCommon { bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; void DestroyFramebuf(VirtualFramebuffer *vfb) override; - void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false) override; + void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override; bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer); bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);