diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index c3d21c3cb..7b071a4e6 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -2781,6 +2781,8 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay // it back again afterwards. std::vector loadRPImgBarriers; + m_RenderState.rpBarriers.clear(); + // we'll need our own command buffer if we're replaying just a subsection // of events within a single command buffer record - always if it's only // one drawcall, or if start event ID is > 0 we assume the outside code @@ -2802,31 +2804,6 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay if(m_Partial[Primary].renderPassActive) { - // first apply implicit transitions to the right subpass - loadRPImgBarriers = GetImplicitRenderPassBarriers(); - - // don't transition from undefined, or contents will be discarded, instead transition from - // the current state. - for(size_t i = 0; i < loadRPImgBarriers.size(); i++) - { - if(loadRPImgBarriers[i].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) - { - // TODO find overlapping range and transition that instead - loadRPImgBarriers[i].oldLayout = - m_ImageLayouts[GetResourceManager()->GetNonDispWrapper(loadRPImgBarriers[i].image)->id] - .subresourceStates[0] - .newLayout; - } - } - - GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[GetResID(cmd)].imgbarriers, - m_ImageLayouts, (uint32_t)loadRPImgBarriers.size(), - &loadRPImgBarriers[0]); - - ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 0, NULL, 0, NULL, - (uint32_t)loadRPImgBarriers.size(), &loadRPImgBarriers[0]); - const DrawcallDescription *draw = GetDrawcall(endEventID); bool rpUnneeded = false; @@ -2878,23 +2855,13 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay m_RenderState.EndTransformFeedback(cmd); // check if the render pass is active - it could have become active - // even if it wasn't before (if the above event was a CmdBeginRenderPass) + // even if it wasn't before (if the above event was a CmdBeginRenderPass). + // If we began our own custom single-draw loadrp, and it was ended by a CmdEndRenderPass, + // we need to reverse the virtual transitions we did above, as it won't happen otherwise if(m_Partial[Primary].renderPassActive) m_RenderState.EndRenderPass(cmd); - - // reverse the loadRPImgBarriers - for(size_t i = 0; i < loadRPImgBarriers.size(); i++) - { - std::swap(loadRPImgBarriers[i].oldLayout, loadRPImgBarriers[i].newLayout); - } - - GetResourceManager()->RecordBarriers(m_BakedCmdBufferInfo[GetResID(cmd)].imgbarriers, - m_ImageLayouts, (uint32_t)loadRPImgBarriers.size(), - &loadRPImgBarriers[0]); - - ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, - VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 0, NULL, 0, NULL, - (uint32_t)loadRPImgBarriers.size(), &loadRPImgBarriers[0]); + else if(rpWasActive) + m_RenderState.DoRenderpassEndTransitions(cmd); // we might have replayed a CmdBeginRenderPass or CmdEndRenderPass, // but we want to keep the partial replay data state intact, so restore diff --git a/renderdoc/driver/vulkan/vk_state.cpp b/renderdoc/driver/vulkan/vk_state.cpp index 8f0f8def7..0ad42fd41 100644 --- a/renderdoc/driver/vulkan/vk_state.cpp +++ b/renderdoc/driver/vulkan/vk_state.cpp @@ -85,6 +85,8 @@ VulkanRenderState &VulkanRenderState::operator=(const VulkanRenderState &o) void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, PipelineBinding binding) { + DoRenderPassBeginTransitions(cmd); + RDCASSERT(renderPass != ResourceId()); // clear values don't matter as we're using the load renderpass here, that @@ -151,6 +153,12 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, Pipeli } } +void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd) +{ + ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd)); + DoRenderpassEndTransitions(cmd); +} + void VulkanRenderState::EndTransformFeedback(VkCommandBuffer cmd) { if(!xfbcounters.empty()) @@ -467,9 +475,52 @@ void VulkanRenderState::BindDescriptorSet(const DescSetLayout &descLayout, VkCom } } -void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd) +void VulkanRenderState::DoRenderPassBeginTransitions(VkCommandBuffer cmd) { - ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd)); + // first apply implicit transitions to the right subpass + rpBarriers = m_pDriver->GetImplicitRenderPassBarriers(); + + if(!rpBarriers.empty()) + { + // don't transition from undefined, or contents will be discarded, instead transition from + // the current state. + for(size_t i = 0; i < rpBarriers.size(); i++) + { + if(rpBarriers[i].oldLayout == VK_IMAGE_LAYOUT_UNDEFINED) + { + ResourceId imgid = GetResourceManager()->GetNonDispWrapper(rpBarriers[i].image)->id; + + // TODO find overlapping range and transition that instead + rpBarriers[i].oldLayout = m_pDriver->m_ImageLayouts[imgid].subresourceStates[0].newLayout; + } + } + + GetResourceManager()->RecordBarriers(m_pDriver->m_BakedCmdBufferInfo[GetResID(cmd)].imgbarriers, + m_pDriver->m_ImageLayouts, (uint32_t)rpBarriers.size(), + rpBarriers.data()); + + ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 0, NULL, 0, NULL, + (uint32_t)rpBarriers.size(), rpBarriers.data()); + } +} + +void VulkanRenderState::DoRenderpassEndTransitions(VkCommandBuffer cmd) +{ + if(!rpBarriers.empty()) + { + // reverse the rpBarriers that we applied at the start + for(size_t i = 0; i < rpBarriers.size(); i++) + std::swap(rpBarriers[i].oldLayout, rpBarriers[i].newLayout); + + GetResourceManager()->RecordBarriers(m_pDriver->m_BakedCmdBufferInfo[GetResID(cmd)].imgbarriers, + m_pDriver->m_ImageLayouts, (uint32_t)rpBarriers.size(), + rpBarriers.data()); + + ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 0, NULL, 0, NULL, + (uint32_t)rpBarriers.size(), rpBarriers.data()); + } } VulkanResourceManager *VulkanRenderState::GetResourceManager() diff --git a/renderdoc/driver/vulkan/vk_state.h b/renderdoc/driver/vulkan/vk_state.h index a364c5b40..000b0b556 100644 --- a/renderdoc/driver/vulkan/vk_state.h +++ b/renderdoc/driver/vulkan/vk_state.h @@ -44,10 +44,14 @@ struct VulkanRenderState VulkanRenderState(WrappedVulkan *driver, VulkanCreationInfo *createInfo); VulkanRenderState &operator=(const VulkanRenderState &o); void BeginRenderPassAndApplyState(VkCommandBuffer cmd, PipelineBinding binding); - void EndTransformFeedback(VkCommandBuffer cmd); void EndRenderPass(VkCommandBuffer cmd); - void BindPipeline(VkCommandBuffer cmd, PipelineBinding binding, bool subpass0); + void DoRenderPassBeginTransitions(VkCommandBuffer cmd); + void DoRenderpassEndTransitions(VkCommandBuffer cmd); + + void EndTransformFeedback(VkCommandBuffer cmd); + + void BindPipeline(VkCommandBuffer cmd, PipelineBinding binding, bool subpass0); void BindDescriptorSet(const DescSetLayout &descLayout, VkCommandBuffer cmd, VkPipelineLayout layout, VkPipelineBindPoint bindPoint, uint32_t setIndex, uint32_t *dynamicOffsets); @@ -123,4 +127,6 @@ struct VulkanRenderState VulkanResourceManager *GetResourceManager(); VulkanCreationInfo *m_CreationInfo; WrappedVulkan *m_pDriver; + + std::vector rpBarriers; };