Defer depth copies until depth buffer is actually used.

Fixes
This commit is contained in:
Henrik Rydgård committed 2022-08-20 08:29:33 +02:00
1 parent 21cf6a6f04
commit a0ac2dffc7
4 files changed
+45 -24

No files matched your search

+30 -24
View File
@@ -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);
}
+2
View File
@@ -266,6 +266,8 @@ public:
return vfb;
}
}
void SetDepthFrameBuffer();
void RebindFramebuffer(const char *tag);
std::vector<FramebufferInfo> GetFramebufferList() const;
+10
View File
@@ -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;
+3
View File
@@ -572,6 +572,9 @@ struct GPUStateCache {
uint64_t dirty;
bool usingDepth; // For deferred depth copies.
bool clearingDepth;
bool textureFullAlpha;
bool vertexFullAlpha;