diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 249289183..3ee06484b 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1854,6 +1854,8 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t } VkResult vkr = VK_SUCCESS; + + bool rpWasActive = false; // 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 @@ -1867,6 +1869,15 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo); RDCASSERT(vkr == VK_SUCCESS); + + rpWasActive = m_PartialReplayData.renderPassActive; + + // if a render pass was active, begin it and set up the partial replay state + if(m_PartialReplayData.renderPassActive) + m_RenderState.BeginRenderPassAndApplyState(cmd); + // if we had a compute pipeline, need to bind that + else if(m_RenderState.compute.pipeline != ResourceId()) + m_RenderState.BindPipeline(cmd); } if(replayType == eReplay_Full) @@ -1879,18 +1890,14 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t } else if(replayType == eReplay_OnlyDraw) { - VkCommandBuffer cmd = m_PartialReplayData.outsideCmdBuffer; - - bool rpWasActive = m_PartialReplayData.renderPassActive; - - // if a render pass was active, begin it and set up the partial replay state - if(m_PartialReplayData.renderPassActive) - m_RenderState.BeginRenderPassAndApplyState(cmd); - // if we had a compute pipeline, need to bind that - else if(m_RenderState.compute.pipeline != ResourceId()) - m_RenderState.BindPipeline(cmd); - ContextReplayLog(EXECUTING, endEventID, endEventID, partial); + } + else + RDCFATAL("Unexpected replay type"); + + if(m_PartialReplayData.outsideCmdBuffer != VK_NULL_HANDLE) + { + VkCommandBuffer cmd = m_PartialReplayData.outsideCmdBuffer; // 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) @@ -1901,13 +1908,6 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t // but we want to keep the partial replay data state intact, so restore // whether or not a render pass was active. m_PartialReplayData.renderPassActive = rpWasActive; - } - else - RDCFATAL("Unexpected replay type"); - - if(m_PartialReplayData.outsideCmdBuffer != VK_NULL_HANDLE) - { - VkCommandBuffer cmd = m_PartialReplayData.outsideCmdBuffer; ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); diff --git a/renderdoc/driver/vulkan/vk_debug.cpp b/renderdoc/driver/vulkan/vk_debug.cpp index e9a2eb246..2364d0ad5 100644 --- a/renderdoc/driver/vulkan/vk_debug.cpp +++ b/renderdoc/driver/vulkan/vk_debug.cpp @@ -3119,6 +3119,101 @@ ResourceId VulkanDebugManager::RenderOverlay(ResourceId texid, TextureDisplayOve m_pDriver->vkDestroyFramebuffer(m_Device, depthFB, NULL); } } + else if(overlay == eTexOverlay_ClearBeforeDraw || overlay == eTexOverlay_ClearBeforePass) + { + // clear the overlay image itself + float black[] = { 0.0f, 0.0f, 0.0f, 0.0f }; + vt->CmdClearColorImage(Unwrap(cmd), Unwrap(m_OverlayImage), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, (VkClearColorValue *)black, 1, &subresourceRange); + + vector events = passEvents; + + if(overlay == eTexOverlay_ClearBeforeDraw) + events.clear(); + + events.push_back(eventID); + + { + vkr = vt->EndCommandBuffer(Unwrap(cmd)); + RDCASSERT(vkr == VK_SUCCESS); + + size_t startEvent = 0; + + // if we're ClearBeforePass the first event will be a vkBeginRenderPass. + // if there are any other events, we need to play up to right before them + // so that we have all the render state set up to do + // BeginRenderPassAndApplyState and a clear. If it's just the begin, we + // just play including it, do the clear, then we won't replay anything + // in the loop below + if(overlay == eTexOverlay_ClearBeforePass) + { + const FetchDrawcall *draw = m_pDriver->GetDrawcall(frameID, events[0]); + if(draw && draw->flags & eDraw_BeginPass) + { + if(events.size() == 1) + { + m_pDriver->ReplayLog(frameID, 0, events[0], eReplay_Full); + } + else + { + startEvent = 1; + m_pDriver->ReplayLog(frameID, 0, events[1], eReplay_WithoutDraw); + } + } + } + else + { + m_pDriver->ReplayLog(frameID, 0, events[0], eReplay_WithoutDraw); + } + + cmd = m_pDriver->GetNextCmd(); + + vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERT(vkr == VK_SUCCESS); + + m_pDriver->m_RenderState.BeginRenderPassAndApplyState(cmd); + + VkClearAttachment blackclear = { + VK_IMAGE_ASPECT_COLOR_BIT, 0, + { 0.0f, 0.0f, 0.0f, 0.0f } + }; + vector atts; + + VulkanCreationInfo::Framebuffer &fb = m_pDriver->m_CreationInfo.m_Framebuffer[m_pDriver->m_RenderState.framebuffer]; + VulkanCreationInfo::RenderPass &rp = m_pDriver->m_CreationInfo.m_RenderPass[m_pDriver->m_RenderState.renderPass]; + + for(size_t i=0; i < rp.subpasses[m_pDriver->m_RenderState.subpass].colorAttachments.size(); i++) + { + blackclear.colorAttachment = rp.subpasses[m_pDriver->m_RenderState.subpass].colorAttachments[i]; + atts.push_back(blackclear); + } + + VkClearRect rect = { + { + { 0, 0 }, + { fb.width, fb.height }, + }, + 0, 1, + }; + + vt->CmdClearAttachments(Unwrap(cmd), (uint32_t)atts.size(), &atts[0], 1, &rect); + + vkr = vt->EndCommandBuffer(Unwrap(cmd)); + RDCASSERT(vkr == VK_SUCCESS); + + for(size_t i = startEvent; i < events.size(); i++) + { + m_pDriver->ReplayLog(frameID, events[i], events[i], eReplay_OnlyDraw); + + if(overlay == eTexOverlay_ClearBeforePass && i+1 < events.size()) + m_pDriver->ReplayLog(frameID, events[i]+1, events[i+1], eReplay_WithoutDraw); + } + + cmd = m_pDriver->GetNextCmd(); + + vkr = vt->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERT(vkr == VK_SUCCESS); + } + } else if(overlay == eTexOverlay_QuadOverdrawPass || overlay == eTexOverlay_QuadOverdrawDraw) { VulkanRenderState prevstate = m_pDriver->m_RenderState;