diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 28aa244776..c896b06b57 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -767,11 +767,13 @@ void VulkanQueueRunner::ApplyRenderPassMerge(std::vector &steps) { TinySet touchedFramebuffers; // must be the same fast-size as the dependencies TinySet for annoying reasons. for (int j = i + 1; j < (int)steps.size(); j++) { // If any other passes are reading from this framebuffer as-is, we cancel the scan. + if (steps[j]->dependencies.contains(fb)) { + // Reading from itself means a KEEP, which is okay. + if (steps[j]->stepType != VKRStepType::RENDER || steps[j]->render.framebuffer != fb) + break; + } switch (steps[j]->stepType) { case VKRStepType::RENDER: - if (steps[j]->dependencies.contains(fb)) { - goto done_fb; - } // Prevent Unknown's example case from https://github.com/hrydgard/ppsspp/pull/12242 if (steps[j]->dependencies.contains(touchedFramebuffers)) { goto done_fb; @@ -793,23 +795,14 @@ void VulkanQueueRunner::ApplyRenderPassMerge(std::vector &steps) { } break; case VKRStepType::COPY: - if (steps[j]->copy.src == fb || steps[j]->copy.dst == fb) { - goto done_fb; - } touchedFramebuffers.insert(steps[j]->copy.dst); break; case VKRStepType::BLIT: - if (steps[j]->blit.src == fb || steps[j]->blit.dst == fb) { - goto done_fb; - } touchedFramebuffers.insert(steps[j]->blit.dst); break; case VKRStepType::READBACK: // Not sure this has much effect, when executed READBACK is always the last step // since we stall the GPU and wait immediately after. - if (steps[j]->readback.src == fb) { - goto done_fb; - } break; default: break; diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 7a639b7d4e..fb39fc3cd0 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -490,6 +490,13 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR step->render.finalColorLayout = !fb ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED; steps_.push_back(step); + if (fb) { + // If there's a KEEP, we naturally read from the framebuffer. + if (color == VKRRenderPassAction::KEEP || depth == VKRRenderPassAction::KEEP || stencil == VKRRenderPassAction::KEEP) { + step->dependencies.insert(fb); + } + } + curRenderStep_ = step; if (fb) { curWidth_ = fb->width; @@ -513,6 +520,7 @@ bool VulkanRenderManager::CopyFramebufferToMemorySync(VKRFramebuffer *src, int a step->readback.src = src; step->readback.srcRect.offset = { x, y }; step->readback.srcRect.extent = { (uint32_t)w, (uint32_t)h }; + step->dependencies.insert(src); steps_.push_back(step); curRenderStep_ = nullptr; @@ -821,6 +829,10 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, step->copy.srcRect = srcRect; step->copy.dst = dst; step->copy.dstPos = dstPos; + step->dependencies.insert(src); + bool fillsDst = dst && srcRect.offset.x == 0 && srcRect.offset.y == 0 && srcRect.extent.width == dst->width && srcRect.extent.height == dst->height; + if (dstPos.x != 0 || dstPos.y != 0 || !fillsDst) + step->dependencies.insert(dst); std::unique_lock lock(mutex_); steps_.push_back(step); @@ -859,6 +871,10 @@ void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, step->blit.dst = dst; step->blit.dstRect = dstRect; step->blit.filter = filter; + step->dependencies.insert(src); + bool fillsDst = dst && dstRect.offset.x == 0 && dstRect.offset.y == 0 && dstRect.extent.width == dst->width && dstRect.extent.height == dst->height; + if (!fillsDst) + step->dependencies.insert(dst); std::unique_lock lock(mutex_); steps_.push_back(step);