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:
baldurk
2019-02-13 18:50:53 +00:00
parent e73c3a0d6b
commit ac95d0ff48
4 changed files with 37 additions and 65 deletions
-2
View File
@@ -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
-51
View File
@@ -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();
-3
View File
@@ -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