From 9b12a4893d1bd21cdf76499afcb6d316268a2b7f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 11 Jun 2014 22:21:08 -0700 Subject: [PATCH] Track framebuffer memory dirty more carefully. Fixes #6296, Grand Knights History slowdown during battle transition. May also more correctly identify block transfer downloads. --- GPU/GLES/Framebuffer.cpp | 12 ++++++++---- GPU/GLES/Framebuffer.h | 5 +++++ GPU/GLES/SoftwareTransform.cpp | 1 + GPU/GLES/StencilBuffer.cpp | 1 + GPU/GLES/TransformPipeline.cpp | 1 + 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 94972849d4..a90ac36f00 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -997,7 +997,6 @@ void FramebufferManager::DoSetRenderFrameBuffer() { vfb->dirtyAfterDisplay = true; if ((gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) vfb->reallyDirtyAfterDisplay = true; - vfb->memoryUpdated = false; if (useBufferedRendering_) { if (vfb->fbo) { @@ -1029,7 +1028,7 @@ void FramebufferManager::DoSetRenderFrameBuffer() { // to it. This broke stuff before, so now it only clears on the first use of an // FBO in a frame. This means that some games won't be able to avoid the on-some-GPUs // performance-crushing framebuffer reloads from RAM, but we'll have to live with that. - if (vfb->last_frame_render != gpuStats.numFlips) { + if (vfb->last_frame_render != gpuStats.numFlips) { ClearBuffer(); } #endif @@ -1983,6 +1982,7 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) { fmt = displayFormat_; } DrawPixels(vfb, 0, 0, Memory::GetPointer(addr | 0x04000000), fmt, vfb->fb_stride, vfb->width, vfb->height); + vfb->memoryUpdated = false; } else { INFO_LOG(SCEGE, "Invalidating FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format) DestroyFramebuf(vfb); @@ -2069,6 +2069,7 @@ bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool } glstate.viewport.restore(); textureCache_->ForgetLastTexture(); + dstBuffer->memoryUpdated = false; // This is a memcpy, let's still copy just in case. return false; } @@ -2219,6 +2220,7 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride BlitFramebuffer_(&tempBuffer, srcX, srcY, dstBuffer, srcX, srcY, dstWidth, dstHeight, bpp); BlitFramebuffer_(dstBuffer, dstX, dstY, &tempBuffer, srcX, srcY, dstWidth, dstHeight, bpp); RebindFramebuffer(); + dstBuffer->memoryUpdated = false; return true; } } else { @@ -2234,6 +2236,7 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride FlushBeforeCopy(); BlitFramebuffer_(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp); RebindFramebuffer(); + dstBuffer->memoryUpdated = false; return true; // No need to actually do the memory copy behind, probably. } } @@ -2243,10 +2246,10 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride return false; } else if (srcBuffer) { WARN_LOG_ONCE(btd, G3D, "Block transfer download %08x -> %08x", srcBasePtr, dstBasePtr); - if (g_Config.bBlockTransferGPU && (srcBuffer == currentRenderVfb_ || !srcBuffer->memoryUpdated)) { + FlushBeforeCopy(); + if (g_Config.bBlockTransferGPU && !srcBuffer->memoryUpdated) { int srcBpp = srcBuffer->format == GE_FORMAT_8888 ? 4 : 2; float srcXFactor = (float)bpp / srcBpp; - FlushBeforeCopy(); ReadFramebufferToMemory(srcBuffer, true, srcX * srcXFactor, srcY, srcWidth * srcXFactor, srcHeight); } return false; // Let the bit copy happen @@ -2305,6 +2308,7 @@ void FramebufferManager::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, } glstate.viewport.restore(); textureCache_->ForgetLastTexture(); + dstBuffer->memoryUpdated = false; } } } diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 59e8a5333d..9b3935318f 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -206,6 +206,11 @@ public: currentRenderVfb_->depthUpdated = true; } } + void SetColorUpdated() { + if (currentRenderVfb_) { + currentRenderVfb_->memoryUpdated = false; + } + } bool MayIntersectFramebuffer(u32 start) { // Clear the cache/kernel bits. diff --git a/GPU/GLES/SoftwareTransform.cpp b/GPU/GLES/SoftwareTransform.cpp index cf5e3d6997..de368bf4aa 100644 --- a/GPU/GLES/SoftwareTransform.cpp +++ b/GPU/GLES/SoftwareTransform.cpp @@ -420,6 +420,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw( // Stencil takes alpha. glClearStencil(clearColor >> 24); glClear(target); + framebufferManager_->SetColorUpdated(); return; } diff --git a/GPU/GLES/StencilBuffer.cpp b/GPU/GLES/StencilBuffer.cpp index 192d9c2895..71fa4f6f33 100644 --- a/GPU/GLES/StencilBuffer.cpp +++ b/GPU/GLES/StencilBuffer.cpp @@ -146,5 +146,6 @@ bool FramebufferManager::NotifyStencilUpload(u32 addr, int size) { fbo_unbind(); } glstate.viewport.restore(); + dstBuffer->memoryUpdated = false; return true; } \ No newline at end of file diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 5504b8461f..f62e8f20fd 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -760,6 +760,7 @@ rotateVBO: dcid_ = 0; prevPrim_ = GE_PRIM_INVALID; gstate_c.vertexFullAlpha = true; + framebufferManager_->SetColorUpdated(); #ifndef MOBILE_DEVICE host->GPUNotifyDraw();