Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deferred depth buffer copies #15777

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 37 additions & 8 deletions Common/GPU/Vulkan/VulkanRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1054,7 +1054,17 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
_dbg_assert_msg_(dstPos.x + srcRect.extent.width <= (uint32_t)dst->width, "dstPos + extent x > width");
_dbg_assert_msg_(dstPos.y + srcRect.extent.height <= (uint32_t)dst->height, "dstPos + extent y > height");

for (int i = (int)steps_.size() - 1; i >= 0; i--) {
bool injectBeforeCurrent = false;
int lastStepToCheck = (int)steps_.size() - 1;
if (aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT && curRenderStep_) {
// We allow injection of these while in the render pass, so we don't have to split the render pass.
injectBeforeCurrent = true;
lastStepToCheck--;
} else {
EndCurRenderStep();
}

for (int i = lastStepToCheck; i >= 0; i--) {
if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == src) {
if (aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
Expand All @@ -1070,7 +1080,8 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
break;
}
}
for (int i = (int)steps_.size() - 1; i >= 0; i--) {

for (int i = lastStepToCheck; i >= 0; i--) {
if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == dst) {
if (aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) {
Expand Down Expand Up @@ -1102,7 +1113,12 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
step->dependencies.insert(dst);

std::unique_lock<std::mutex> lock(mutex_);
steps_.push_back(step);

if (injectBeforeCurrent) {
steps_.insert(steps_.begin() + steps_.size() - 1, step);
} else {
steps_.push_back(step);
}
}

void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, VKRFramebuffer *dst, VkRect2D dstRect, VkImageAspectFlags aspectMask, VkFilter filter, const char *tag) {
Expand All @@ -1122,17 +1138,25 @@ void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
_dbg_assert_msg_(dstRect.extent.width > 0, "blit dstwidth == 0");
_dbg_assert_msg_(dstRect.extent.height > 0, "blit dstheight == 0");

// TODO: Seem to be missing final layouts here like in Copy...
bool injectBeforeCurrent = false;

for (int i = (int)steps_.size() - 1; i >= 0; i--) {
int lastStepToCheck = (int)steps_.size() - 1;

if (aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT && curRenderStep_) {
// We allow injection of these while in the render pass, so we don't have to split the render pass.
injectBeforeCurrent = true;
lastStepToCheck--;
} else {
EndCurRenderStep();
}

for (int i = lastStepToCheck; i >= 0; i--) {
if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == src) {
steps_[i]->render.numReads++;
break;
}
}

EndCurRenderStep();

VKRStep *step = new VKRStep{ VKRStepType::BLIT };

step->blit.aspectMask = aspectMask;
Expand All @@ -1148,7 +1172,12 @@ void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
step->dependencies.insert(dst);

std::unique_lock<std::mutex> lock(mutex_);
steps_.push_back(step);

if (injectBeforeCurrent) {
steps_.insert(steps_.begin() + steps_.size() - 1, step);
} else {
steps_.push_back(step);
}
}

VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, int binding, VkImageAspectFlags aspectBit, int attachment) {
Expand Down
49 changes: 26 additions & 23 deletions GPU/Common/FramebufferManagerCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,18 +451,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.
TrackedDepthBuffer *prevDepth = GetOrCreateTrackedDepthBuffer(vfb);

// We might already want to copy depth, in case this is a temp buffer. See #7810.
if (prevDepth->vfb != vfb) {
if (!params.isClearingDepth && prevDepth->vfb) {
BlitFramebufferDepth(prevDepth->vfb, vfb);
}
prevDepth->vfb = 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));
Expand All @@ -480,6 +468,12 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
// TODO: Is it worth trying to upload the depth buffer (only if it wasn't copied above..?)
}

// We don't try to optimize depth buffer tracking on the frame a framebuffer is created.
// See #7810
gstate_c.usingDepth = true;
gstate_c.clearingDepth = false;
SetDepthFrameBuffer();

// Let's check for depth buffer overlap. Might be interesting.
bool sharingReported = false;
for (size_t i = 0, end = vfbs_.size(); i < end; ++i) {
Expand Down Expand Up @@ -520,6 +514,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
VirtualFramebuffer *prev = currentRenderVfb_;
currentRenderVfb_ = vfb;
NotifyRenderFramebufferSwitched(prev, vfb, params.isClearingDepth);
gstate_c.usingDepth = false; // reset depth buffer tracking
} else {
vfb->last_frame_render = gpuStats.numFlips;
frameLastFramebufUsed_ = gpuStats.numFlips;
Expand All @@ -537,6 +532,25 @@ 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.
TrackedDepthBuffer *prevDepth = GetOrCreateTrackedDepthBuffer(currentRenderVfb_);

// We might already want to copy depth, in case this is a temp buffer. See #7810.
if (prevDepth->vfb != currentRenderVfb_) {
if (!gstate_c.clearingDepth && prevDepth->vfb) {
BlitFramebufferDepth(prevDepth->vfb, currentRenderVfb_);
}
prevDepth->vfb = currentRenderVfb_;
}
}

void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) {
// Notify the texture cache of both the color and depth buffers.
textureCache_->NotifyFramebuffer(v, NOTIFY_FB_DESTROYED);
Expand Down Expand Up @@ -857,17 +871,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe
textureCache_->ForgetLastTexture();
shaderManager_->DirtyLastShader();

// Copy depth between the framebuffers, if the z_address is the same (checked inside.)
TrackedDepthBuffer *prevDepth = GetOrCreateTrackedDepthBuffer(vfb);

// We might already want to copy depth, in case this is a temp buffer. See #7810.
if (prevDepth->vfb != vfb) {
if (!isClearingDepth && prevDepth->vfb) {
BlitFramebufferDepth(prevDepth->vfb, vfb);
}
prevDepth->vfb = vfb;
}

if (vfb->drawnFormat != vfb->format) {
ReinterpretFramebuffer(vfb, vfb->drawnFormat, vfb->format);
}
Expand Down
2 changes: 2 additions & 0 deletions GPU/Common/FramebufferManagerCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ class FramebufferManagerCommon {
return vfb;
}
}
void SetDepthFrameBuffer();

void RebindFramebuffer(const char *tag);
std::vector<FramebufferInfo> GetFramebufferList();

Expand Down
8 changes: 8 additions & 0 deletions GPU/GPUCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1685,6 +1685,14 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) {
return;
}

bool isClearingDepth = gstate.isModeClear() && gstate.isClearModeDepthMask();;

if (!gstate_c.usingDepth && (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;
Expand Down
3 changes: 3 additions & 0 deletions GPU/GPUState.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@ struct GPUStateCache {

uint64_t dirty;

bool usingDepth; // For deferred depth copies.
bool clearingDepth;

bool textureFullAlpha;
bool vertexFullAlpha;

Expand Down