mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 10:00:40 +00:00
Fix handling of implicit barriers around renderpasses when replaying
* When we replay a draw and artificially call our loadRP renderpasses, we need to be careful to handle the barriers to and from the expected image layouts when the renderpass itself has layout transitions.
This commit is contained in:
@@ -2781,6 +2781,8 @@ void WrappedVulkan::ReplayLog(uint32_t startEventID, uint32_t endEventID, Replay
|
||||
// it back again afterwards.
|
||||
std::vector<VkImageMemoryBarrier> 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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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<VkImageMemoryBarrier> rpBarriers;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user