diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index e25c0b9a35..eeae895d53 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -377,6 +377,11 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame // // We use a special fragment shader flag to convert color to depth. vfb = GetLatestDepthBufferAt(params.fb_address /* !!! */, params.fb_stride); + if (vfb) { + vfb->depthBindSeq = GetBindSeqCount(); + } + // Avoid causing another depth copy on top. + gstate_c.usingDepth = true; } gstate_c.SetFramebufferRenderMode(mode); @@ -416,6 +421,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame // None found? Create one. if (!vfb) { + gstate_c.usingDepth = false; // reset depth buffer tracking + vfb = new VirtualFramebuffer{}; vfb->fbo = nullptr; vfb->fb_address = params.fb_address; @@ -442,17 +449,6 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame ResizeFramebufFBO(vfb, drawing_width, drawing_height, true); NotifyRenderFramebufferCreated(vfb); - // Looks up by z_address, so if one is found here and not have last pointers equal to this one, - // there is another one. - VirtualFramebuffer *prevDepth = GetLatestDepthBufferAt(vfb->z_address, vfb->z_stride); - - // We might already want to copy depth, in case this is a temp buffer. See #7810. - if (prevDepth != vfb) { - if (!params.isClearingDepth && prevDepth) { - BlitFramebufferDepth(prevDepth, vfb); - } - } - SetColorUpdated(vfb, skipDrawReason); INFO_LOG(FRAMEBUF, "Creating FBO for %08x (z: %08x) : %d x %d x %s", vfb->fb_address, vfb->z_address, vfb->width, vfb->height, GeBufferFormatToString(vfb->format)); @@ -510,18 +506,19 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame VirtualFramebuffer *prev = currentRenderVfb_; currentRenderVfb_ = vfb; NotifyRenderFramebufferSwitched(prev, vfb, params.isClearingDepth); + gstate_c.usingDepth = false; // reset depth buffer tracking } else { + // Something changed, but we still got the same framebuffer we were already rendering to. + // Might not be a lot to do here, we check in NotifyRenderFramebufferUpdated vfb->last_frame_render = gpuStats.numFlips; frameLastFramebufUsed_ = gpuStats.numFlips; vfb->dirtyAfterDisplay = true; if ((skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) vfb->reallyDirtyAfterDisplay = true; - NotifyRenderFramebufferUpdated(vfb, vfbFormatChanged); } vfb->colorBindSeq = GetBindSeqCount(); - vfb->depthBindSeq = GetBindSeqCount(); gstate_c.curRTWidth = vfb->width; gstate_c.curRTHeight = vfb->height; @@ -530,6 +527,26 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame return vfb; } +// Called on the first use of depth in a render pass. +void FramebufferManagerCommon::SetDepthFrameBuffer() { + if (!currentRenderVfb_) { + return; + } + + // Looks up by z_address, so if one is found here and not have last pointers equal to this one, + // there is another one. + VirtualFramebuffer *prevDepth = GetLatestDepthBufferAt(currentRenderVfb_->z_address, currentRenderVfb_->z_stride); + + if (prevDepth != currentRenderVfb_) { + if (!gstate_c.clearingDepth && prevDepth) { + BlitFramebufferDepth(prevDepth, currentRenderVfb_); + } + prevDepth = currentRenderVfb_; + } + + currentRenderVfb_->depthBindSeq = GetBindSeqCount(); +} + void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) { // Notify the texture cache of both the color and depth buffers. textureCache_->NotifyFramebuffer(v, NOTIFY_FB_DESTROYED); @@ -669,17 +686,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe textureCache_->ForgetLastTexture(); shaderManager_->DirtyLastShader(); - // Copy depth between the framebuffers, if the z_address is the same (checked inside.) - VirtualFramebuffer * prevDepth = GetLatestDepthBufferAt(vfb->z_address, vfb->z_stride); - - // We might already want to copy depth, in case this is a temp buffer. See #7810. - if (prevDepth != vfb) { - if (!isClearingDepth && prevDepth) { - BlitFramebufferDepth(prevDepth, vfb); - } - prevDepth = vfb; - } - if (vfb->drawnFormat != vfb->format) { ReinterpretFramebuffer(vfb, vfb->drawnFormat, vfb->format); } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index e592ed7b87..87a4e577cd 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -266,6 +266,8 @@ public: return vfb; } } + void SetDepthFrameBuffer(); + void RebindFramebuffer(const char *tag); std::vector GetFramebufferList() const; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index a0deb403aa..d751291a9b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1685,6 +1685,16 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) { return; } + if (!gstate_c.usingDepth) { + bool isClearingDepth = gstate.isModeClear() && gstate.isClearModeDepthMask();; + + if ((gstate.isDepthTestEnabled() || isClearingDepth)) { + gstate_c.usingDepth = true; + gstate_c.clearingDepth = isClearingDepth; + framebufferManager_->SetDepthFrameBuffer(); + } + } + const void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); const void *inds = nullptr; u32 vertexType = gstate.vertType; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 8d6d04039b..3f30be89f7 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -572,6 +572,9 @@ struct GPUStateCache { uint64_t dirty; + bool usingDepth; // For deferred depth copies. + bool clearingDepth; + bool textureFullAlpha; bool vertexFullAlpha;