From a8b78a46bd9beef01126d0ab3b8d980b876f1e36 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Aug 2014 23:05:21 -0700 Subject: [PATCH 1/6] Forget the bound texture on fbo_create(). Just in case, since it overrides the texture. --- GPU/GLES/Framebuffer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 88b501350b..aceec1bd70 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1191,6 +1191,7 @@ FBO *FramebufferManager::GetTempFBO(u16 w, u16 h, FBOColorDepth depth) { return it->second.fbo; } + textureCache_->ForgetLastTexture(); FBO *fbo = fbo_create(w, h, 1, false, depth); if (!fbo) return fbo; @@ -1445,6 +1446,7 @@ void FramebufferManager::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool s break; } + textureCache_->ForgetLastTexture(); nvfb->fbo = fbo_create(nvfb->width, nvfb->height, 1, false, nvfb->colorDepth); if (!(nvfb->fbo)) { ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", nvfb->renderWidth, nvfb->renderHeight); From fbb85820f789d62e2f231dc31b52c4d20ea76c57 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Aug 2014 23:07:00 -0700 Subject: [PATCH 2/6] Update native to cache bound fbos. --- native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native b/native index 196facb355..f1ec201dbc 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 196facb35553bc7bbce88ca5ba4703d02b52ee37 +Subproject commit f1ec201dbc6af46fb1b2f6ac57267c2bdd54a0f8 From 77e050d044c4782868073020b0bffaffc07142ad Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Aug 2014 23:07:11 -0700 Subject: [PATCH 3/6] Only unbind the read fbo id draw can be skipped. --- GPU/GLES/Framebuffer.cpp | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index aceec1bd70..0553e01ec1 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1585,6 +1585,7 @@ void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *dst, int dstX, int #endif // defined(USING_GLES2) && defined(ANDROID) } + fbo_unbind_read(); } else { fbo_bind_color_as_texture(src->fbo, 0); @@ -1601,11 +1602,10 @@ void FramebufferManager::BlitFramebuffer_(VirtualFramebuffer *dst, int dstX, int DrawActiveTexture(0, dstX1, dstY, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, !flip, srcX1 / srcW, srcY / srcH, srcX2 / srcW, (srcY + h) / srcH, draw2dprogram_); glBindTexture(GL_TEXTURE_2D, 0); textureCache_->ForgetLastTexture(); + glstate.viewport.restore(); } glstate.scissorTest.restore(); - glstate.viewport.restore(); - fbo_unbind(); } // TODO: SSE/NEON @@ -1825,10 +1825,7 @@ void FramebufferManager::PackFramebufferAsync_(VirtualFramebuffer *vfb) { fbo_bind_for_read(vfb->fbo); } else { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferAsync_: vfb->fbo == 0"); - fbo_unbind(); - if (gl_extensions.FBO_ARB) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - } + fbo_unbind_read(); return; } @@ -1845,10 +1842,7 @@ void FramebufferManager::PackFramebufferAsync_(VirtualFramebuffer *vfb) { if (fbStatus != GL_FRAMEBUFFER_COMPLETE) { ERROR_LOG(SCEGE, "Incomplete source framebuffer, aborting read"); - fbo_unbind(); - if (gl_extensions.FBO_ARB) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - } + fbo_unbind_read(); return; } @@ -1872,11 +1866,7 @@ void FramebufferManager::PackFramebufferAsync_(VirtualFramebuffer *vfb) { // LogReadPixelsError(glGetError()); - fbo_unbind(); - if (gl_extensions.FBO_ARB) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - } - + fbo_unbind_read(); unbind = true; pixelBufObj_[currentPBO_].fb_address = fb_address; @@ -1901,10 +1891,7 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in fbo_bind_for_read(vfb->fbo); } else { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferSync_: vfb->fbo == 0"); - fbo_unbind(); - if (gl_extensions.FBO_ARB) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - } + fbo_unbind_read(); return; } @@ -1949,7 +1936,7 @@ void FramebufferManager::PackFramebufferSync_(VirtualFramebuffer *vfb, int x, in } } - fbo_unbind(); + fbo_unbind_read(); } void FramebufferManager::EndFrame() { From fc5d62804ef9e8e5c152cd47f1870f8cf9b16bd7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Aug 2014 23:08:17 -0700 Subject: [PATCH 4/6] Avoid unbinding the draw fbo where possible. If we're just going to bind another one, no need to trade around. --- GPU/GLES/Framebuffer.cpp | 24 ++++-------------------- GPU/GLES/StencilBuffer.cpp | 2 -- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 0553e01ec1..ada4b95659 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -763,6 +763,8 @@ void FramebufferManager::DestroyFramebuf(VirtualFramebuffer *v) { void FramebufferManager::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { fbo_bind_as_render_target(currentRenderVfb_->fbo); + } else { + fbo_unbind(); } } @@ -2087,20 +2089,15 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) { if (!Memory::IsValidAddress(displayFramebufPtr_)) return; - bool needUnbind = false; for (size_t i = 0; i < vfbs_.size(); ++i) { VirtualFramebuffer *vfb = vfbs_[i]; if (MaskedEqual(vfb->fb_address, addr)) { FlushBeforeCopy(); - fbo_unbind(); - // TODO: This without the fbo_unbind() above would be better than destroying the FBO. - // However, it doesn't seem to work for Star Ocean, at least if (useBufferedRendering_ && vfb->fbo) { DisableState(); fbo_bind_as_render_target(vfb->fbo); glstate.viewport.set(0, 0, vfb->renderWidth, vfb->renderHeight); - needUnbind = true; GEBufferFormat fmt = vfb->format; if (vfb->last_frame_render + 1 < gpuStats.numFlips && isDisplayBuf) { // If we're not rendering to it, format may be wrong. Use displayFormat_ instead. @@ -2116,9 +2113,6 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) { } } - if (needUnbind) { - fbo_unbind(); - } RebindFramebuffer(); } } @@ -2205,12 +2199,7 @@ bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool glViewport(0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight); DrawPixels(dstBuffer, 0, dstY, srcBase, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstH); SetColorUpdated(dstBuffer); - if (useBufferedRendering_) { - RebindFramebuffer(); - } else { - fbo_unbind(); - } - glstate.viewport.restore(); + RebindFramebuffer(); textureCache_->ForgetLastTexture(); // This is a memcpy, let's still copy just in case. return false; @@ -2437,12 +2426,7 @@ void FramebufferManager::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, glViewport(0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight); DrawPixels(dstBuffer, dstX * dstXFactor, dstY, srcBase, dstBuffer->format, srcStride * dstXFactor, dstWidth * dstXFactor, dstHeight); SetColorUpdated(dstBuffer); - if (useBufferedRendering_) { - RebindFramebuffer(); - } else { - fbo_unbind(); - } - glstate.viewport.restore(); + RebindFramebuffer(); textureCache_->ForgetLastTexture(); } } diff --git a/GPU/GLES/StencilBuffer.cpp b/GPU/GLES/StencilBuffer.cpp index 15529f663b..44657e7c89 100644 --- a/GPU/GLES/StencilBuffer.cpp +++ b/GPU/GLES/StencilBuffer.cpp @@ -235,8 +235,6 @@ bool FramebufferManager::NotifyStencilUpload(u32 addr, int size, bool skipZero) } } - fbo_unbind(); RebindFramebuffer(); - glstate.viewport.restore(); return true; } \ No newline at end of file From 9cab344026aad51f019b2985511af00b28d70236 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Aug 2014 23:10:07 -0700 Subject: [PATCH 5/6] Rebind the fbo after inter-buffer copy. Might be needed if the list is stalled, a copy is done, list unstalled, and then something happens to flush a pending prim. --- GPU/GLES/Framebuffer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index ada4b95659..697d1023cd 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -2185,6 +2185,7 @@ bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool if (g_Config.bBlockTransferGPU) { BlitFramebuffer_(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0); SetColorUpdated(dstBuffer); + RebindFramebuffer(); } } return false; From 5a3a972d958328bc0259e697d9d49ea86245e9fc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Aug 2014 23:13:08 -0700 Subject: [PATCH 6/6] Perform intra-buffer blits directly. As far as I can tell, this doesn't need a temp fbo. --- GPU/GLES/Framebuffer.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 697d1023cd..e427f25c72 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -2338,11 +2338,7 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride WARN_LOG_ONCE(dstsrc, G3D, "Intra-buffer block transfer %08x -> %08x", srcBasePtr, dstBasePtr); if (g_Config.bBlockTransferGPU) { FlushBeforeCopy(); - FBO *tempFBO = GetTempFBO(dstBuffer->renderWidth, dstBuffer->renderHeight, dstBuffer->colorDepth); - VirtualFramebuffer tempBuffer = *dstBuffer; - tempBuffer.fbo = tempFBO; - BlitFramebuffer_(&tempBuffer, srcX, srcY, dstBuffer, srcX, srcY, dstWidth, dstHeight, bpp); - BlitFramebuffer_(dstBuffer, dstX, dstY, &tempBuffer, srcX, srcY, dstWidth, dstHeight, bpp); + BlitFramebuffer_(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp); RebindFramebuffer(); SetColorUpdated(dstBuffer); return true;