diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 6623112428..c1dadb9c44 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -364,6 +364,7 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector &st if (steps.size() > 1 && steps[j]->stepType == VKRStepType::RENDER && steps[j]->render.numDraws == 0 && + steps[j]->render.numReads == 0 && steps[j]->render.color == VKRRenderPassAction::CLEAR && steps[j]->render.stencil == VKRRenderPassAction::CLEAR && steps[j]->render.depth == VKRRenderPassAction::CLEAR) { @@ -391,6 +392,7 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, std::vector &st steps[i]->copy.src == steps[j]->render.framebuffer) { // Can't eliminate the clear if a game copies from it before it's // rendered to. However this should be rare. + // TODO: This should never happen when we check numReads now. break; } } diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index 3ff8e161ea..5acfb22d6b 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -122,6 +122,8 @@ struct VKRStep { float clearDepth; int clearStencil; int numDraws; + // Downloads and textures from this pass. + int numReads; VkImageLayout finalColorLayout; } render; struct { diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index a7cec21ed8..325d0f6851 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -422,6 +422,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR step->render.clearDepth = clearDepth; step->render.clearStencil = clearStencil; step->render.numDraws = 0; + step->render.numReads = 0; step->render.finalColorLayout = !fb ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED; steps_.push_back(step); @@ -431,6 +432,13 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR } bool VulkanRenderManager::CopyFramebufferToMemorySync(VKRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride) { + for (int i = (int)steps_.size() - 1; i >= 0; i--) { + if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == src) { + steps_[i]->render.numReads++; + break; + } + } + VKRStep *step = new VKRStep{ VKRStepType::READBACK }; step->readback.aspectMask = aspectBits; step->readback.src = src; @@ -720,6 +728,7 @@ void VulkanRenderManager::CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; } + steps_[i]->render.numReads++; break; } } @@ -762,6 +771,13 @@ void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, _dbg_assert_msg_(G3D, dstRect.extent.width > 0, "blit dstwidth == 0"); _dbg_assert_msg_(G3D, dstRect.extent.height > 0, "blit dstheight == 0"); + for (int i = (int)steps_.size() - 1; i >= 0; i--) { + if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == src) { + steps_[i]->render.numReads++; + break; + } + } + VKRStep *step = new VKRStep{ VKRStepType::BLIT }; step->blit.aspectMask = aspectMask; @@ -784,6 +800,7 @@ VkImageView VulkanRenderManager::BindFramebufferAsTexture(VKRFramebuffer *fb, in if (steps_[i]->render.finalColorLayout == VK_IMAGE_LAYOUT_UNDEFINED) { steps_[i]->render.finalColorLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } + steps_[i]->render.numReads++; break; } }