mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-08-05 22:31:08 +00:00
When ending partially replayed RP, set image back into layout afterwards
* If we have a renderpass that we stop replaying at subpass 0, we want to pretend that the image is preserved as it was at that point - layout and all. However since we're replaying with the original renderpass any subpass transitions and finalLayout transitions will take effect. When we end any active RP during vkEndCommandBuffer, we then undo any of these implicit transitions to put the image back as it was.
This commit is contained in:
@@ -3014,8 +3014,6 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay
|
||||
// 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);
|
||||
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
|
||||
|
||||
@@ -89,8 +89,6 @@ 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
|
||||
@@ -173,7 +171,6 @@ void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, Pipeli
|
||||
void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd)
|
||||
{
|
||||
ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
|
||||
DoRenderpassEndTransitions(cmd);
|
||||
}
|
||||
|
||||
void VulkanRenderState::EndTransformFeedback(VkCommandBuffer cmd)
|
||||
@@ -517,54 +514,6 @@ void VulkanRenderState::BindDescriptorSet(const DescSetLayout &descLayout, VkCom
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanRenderState::DoRenderPassBeginTransitions(VkCommandBuffer 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()
|
||||
{
|
||||
return m_pDriver->GetResourceManager();
|
||||
|
||||
@@ -46,9 +46,6 @@ struct VulkanRenderState
|
||||
void BeginRenderPassAndApplyState(VkCommandBuffer cmd, PipelineBinding binding);
|
||||
void EndRenderPass(VkCommandBuffer cmd);
|
||||
|
||||
void DoRenderPassBeginTransitions(VkCommandBuffer cmd);
|
||||
void DoRenderpassEndTransitions(VkCommandBuffer cmd);
|
||||
|
||||
void EndTransformFeedback(VkCommandBuffer cmd);
|
||||
|
||||
void EndConditionalRendering(VkCommandBuffer cmd);
|
||||
|
||||
@@ -939,28 +939,56 @@ bool WrappedVulkan::Serialise_vkEndCommandBuffer(SerialiserType &ser, VkCommandB
|
||||
(uint32_t)m_CreationInfo.m_RenderPass[m_RenderState.renderPass].subpasses.size();
|
||||
|
||||
// for each subpass we skip, and for the finalLayout transition at the end of the
|
||||
// renderpass, update our tracking. These are executed implicitly but because we're
|
||||
// sneaking past them here our tracking will get out of date.
|
||||
// renderpass, record these barriers. These are executed implicitly but because we want to
|
||||
// pretend they never happened, we then reverse their effects so that our layout tracking
|
||||
// is accurate and the images end up in the layout they were in during the last active
|
||||
// subpass
|
||||
uint32_t &sub = m_BakedCmdBufferInfo[m_LastCmdBufferID].state.subpass;
|
||||
|
||||
std::vector<std::pair<ResourceId, ImageRegionState> > imgbarriers;
|
||||
|
||||
for(sub = m_RenderState.subpass; sub < numSubpasses - 1; sub++)
|
||||
{
|
||||
ObjDisp(commandBuffer)->CmdNextSubpass(Unwrap(commandBuffer), VK_SUBPASS_CONTENTS_INLINE);
|
||||
|
||||
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers();
|
||||
std::vector<VkImageMemoryBarrier> subpassBarriers = GetImplicitRenderPassBarriers();
|
||||
|
||||
GetResourceManager()->RecordBarriers(
|
||||
m_BakedCmdBufferInfo[GetResID(commandBuffer)].imgbarriers, m_ImageLayouts,
|
||||
(uint32_t)imgBarriers.size(), &imgBarriers[0]);
|
||||
imgbarriers, m_ImageLayouts, (uint32_t)subpassBarriers.size(), &subpassBarriers[0]);
|
||||
}
|
||||
|
||||
std::vector<VkImageMemoryBarrier> imgBarriers = GetImplicitRenderPassBarriers(~0U);
|
||||
std::vector<VkImageMemoryBarrier> finalBarriers = GetImplicitRenderPassBarriers(~0U);
|
||||
|
||||
GetResourceManager()->RecordBarriers(
|
||||
m_BakedCmdBufferInfo[GetResID(commandBuffer)].imgbarriers, m_ImageLayouts,
|
||||
(uint32_t)imgBarriers.size(), &imgBarriers[0]);
|
||||
GetResourceManager()->RecordBarriers(imgbarriers, m_ImageLayouts,
|
||||
(uint32_t)finalBarriers.size(), &finalBarriers[0]);
|
||||
|
||||
ObjDisp(commandBuffer)->CmdEndRenderPass(Unwrap(commandBuffer));
|
||||
|
||||
// undo any implicit transitions we just went through, so that we can pretend that the
|
||||
// image stayed in the same layout as it was when we stopped partially replaying.
|
||||
std::vector<VkImageMemoryBarrier> revertBarriers;
|
||||
|
||||
for(auto it = imgbarriers.begin(); it != imgbarriers.end(); ++it)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER};
|
||||
barrier.srcAccessMask = VK_ACCESS_ALL_READ_BITS | VK_ACCESS_ALL_WRITE_BITS;
|
||||
barrier.dstAccessMask = VK_ACCESS_ALL_READ_BITS | VK_ACCESS_ALL_WRITE_BITS;
|
||||
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||
barrier.image = Unwrap(GetResourceManager()->GetCurrentHandle<VkImage>(it->first));
|
||||
|
||||
// go from the layout we ended up in, to the layout we started in
|
||||
barrier.oldLayout = it->second.newLayout;
|
||||
barrier.newLayout = it->second.oldLayout;
|
||||
|
||||
barrier.subresourceRange = it->second.subresourceRange;
|
||||
|
||||
if(barrier.oldLayout != barrier.newLayout)
|
||||
revertBarriers.push_back(barrier);
|
||||
}
|
||||
|
||||
if(!revertBarriers.empty())
|
||||
DoPipelineBarrier(commandBuffer, (uint32_t)revertBarriers.size(), revertBarriers.data());
|
||||
}
|
||||
|
||||
// also finish any nested markers we truncated and didn't finish
|
||||
|
||||
Reference in New Issue
Block a user