From df8dac4aae74e52aae1eeb3d7ede5ce81fbffa03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 16 Mar 2018 13:35:49 +0100 Subject: [PATCH] If the first renderpass is an empty clear, merge it into the next one that touches the same framebuffer. Works around #10723 in Wipeout. --- ext/native/thin3d/VulkanQueueRunner.cpp | 37 +++++++++++++++++++++++-- ext/native/thin3d/VulkanQueueRunner.h | 1 + 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/ext/native/thin3d/VulkanQueueRunner.cpp b/ext/native/thin3d/VulkanQueueRunner.cpp index 235000821f..fdeafcd6b2 100644 --- a/ext/native/thin3d/VulkanQueueRunner.cpp +++ b/ext/native/thin3d/VulkanQueueRunner.cpp @@ -255,11 +255,39 @@ VkRenderPass VulkanQueueRunner::GetRenderPass(VKRRenderPassAction colorLoadActio void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector &steps) { // Optimizes renderpasses, then sequences them. // Planned optimizations: - // * Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer. - // (These happen in Wipeout) // * Create copies of render target that are rendered to multiple times and textured from in sequence, and push those render passes // as early as possible in the frame (Wipeout billboards). + // Push down empty "Clear/Store" renderpasses, and merge them with the first "Load/Store" to the same framebuffer. + // Actually let's just bother with the first one for now. This affects Wipeout Pure. + if (steps.size() > 1 && steps[0]->stepType == VKRStepType::RENDER && + steps[0]->render.numDraws == 0 && + steps[0]->render.color == VKRRenderPassAction::CLEAR && + steps[0]->render.stencil == VKRRenderPassAction::CLEAR && + steps[0]->render.depth == VKRRenderPassAction::CLEAR) { + // Drop the first step, and merge it into the next step that touches the same framebuffer. + for (size_t i = 1; i < steps.size(); i++) { + if (steps[i]->stepType == VKRStepType::RENDER && + steps[i]->render.framebuffer == steps[0]->render.framebuffer) { + if (steps[i]->render.color != VKRRenderPassAction::CLEAR) { + steps[i]->render.color = VKRRenderPassAction::CLEAR; + steps[i]->render.clearColor = steps[0]->render.clearColor; + } + if (steps[i]->render.depth != VKRRenderPassAction::CLEAR) { + steps[i]->render.depth = VKRRenderPassAction::CLEAR; + steps[i]->render.clearDepth = steps[0]->render.clearDepth; + } + if (steps[i]->render.stencil != VKRRenderPassAction::CLEAR) { + steps[i]->render.stencil = VKRRenderPassAction::CLEAR; + steps[i]->render.clearStencil = steps[0]->render.clearStencil; + } + // Cheaply skip the first step. + steps[0]->stepType = VKRStepType::RENDER_SKIP; + break; + } + } + } + for (size_t i = 0; i < steps.size(); i++) { const VKRStep &step = *steps[i]; switch (step.stepType) { @@ -278,6 +306,8 @@ void VulkanQueueRunner::RunSteps(VkCommandBuffer cmd, const std::vector &steps) { case VKRStepType::READBACK_IMAGE: LogReadbackImage(step); break; + case VKRStepType::RENDER_SKIP: + ILOG("(skipped render pass)"); + break; } } } diff --git a/ext/native/thin3d/VulkanQueueRunner.h b/ext/native/thin3d/VulkanQueueRunner.h index 8257fa450a..f10326ff95 100644 --- a/ext/native/thin3d/VulkanQueueRunner.h +++ b/ext/native/thin3d/VulkanQueueRunner.h @@ -82,6 +82,7 @@ struct VkRenderData { enum class VKRStepType : uint8_t { RENDER, + RENDER_SKIP, COPY, BLIT, READBACK,