From f4458edc76715fadefd473514c73c1136eabc5ce Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Apr 2014 21:11:17 -0700 Subject: [PATCH 1/3] Avoid unbinding the current fbo on block transfer. Improves God of War performance by 25% (at least in the demo.) --- GPU/GLES/Framebuffer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 8871eaf57f..8105d237e5 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1674,13 +1674,13 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) { if (!Memory::IsValidAddress(displayFramebufPtr_)) return; - fbo_unbind(); - currentRenderVfb_ = 0; - bool needUnbind = false; for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *vfb = vfbs_[i]; if (MaskedEqual(vfb->fb_address, addr)) { + fbo_unbind(); + currentRenderVfb_ = 0; + vfb->dirtyAfterDisplay = true; vfb->reallyDirtyAfterDisplay = true; // TODO: This without the fbo_unbind() above would be better than destroying the FBO. From 9982d04f9d945b11adfbfa0ff6a4b68564b2d321 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Apr 2014 21:29:55 -0700 Subject: [PATCH 2/3] Optimize the case of a direct byte copy. Small improvement (like 3.5%) in God of War. --- GPU/GLES/GLES_GPU.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 4c1842d646..8edebcfbd9 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -1698,14 +1698,22 @@ void GLES_GPU::DoBlockTransfer() { // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them // entirely by walking a couple of pointers... - // GetPointerUnchecked crash in windows 64 bit of issue 2301 - for (int y = 0; y < height; y++) { - u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; - + if (srcStride == dstStride && width == srcStride) { + // Common case in God of War, let's do it all in one chunk. + u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; + u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * bpp); + memcpy(dst, src, width * height * bpp); + } else { + for (int y = 0; y < height; y++) { + u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; + u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; + + const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); + u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); + memcpy(dst, src, width * bpp); + } } // TODO: Notify all overlapping FBOs that they need to reload. From ed99c33cd72213b29b5d027980cd1e2ff148ad9f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 13 Apr 2014 21:47:11 -0700 Subject: [PATCH 3/3] Interpret iForceMaxEmulatedFPS based on 1.001 NTSC. --- Core/HLE/sceDisplay.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index d4a0bdf3f8..12c3741e0e 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -672,7 +672,8 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync) const int FLIP_DELAY_MIN_FLIPS = 30; u64 now = CoreTiming::GetTicks(); - u64 expected = msToCycles(1000) / g_Config.iForceMaxEmulatedFPS; + // 1001 to account for NTSC timing (59.94 fps.) + u64 expected = msToCycles(1001) / g_Config.iForceMaxEmulatedFPS; u64 actual = now - lastFlipCycles; if (actual < expected - FLIP_DELAY_CYCLES_MIN) { if (lastFlipsTooFrequent >= FLIP_DELAY_MIN_FLIPS) {