From 078bd67becf4fddf11e96341760f0b4075c3427e Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 7 Jan 2016 20:16:06 +0100 Subject: [PATCH] Add a heavy weight global memory barrier around frame restart * This is reaaaally conservative, but will avoid bugs. --- renderdoc/driver/vulkan/vk_core.cpp | 47 +++++++++++++++++++++++- renderdoc/driver/vulkan/vk_core.h | 2 + renderdoc/driver/vulkan/vk_initstate.cpp | 35 +----------------- 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 10ac7013e..af0cfb24e 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1247,7 +1247,7 @@ void WrappedVulkan::ContextReplayLog(LogState readType, uint32_t startEventID, u // (not undefined) if(readType == READING) { - GetResourceManager()->ApplyInitialContents(); + ApplyInitialContents(); SubmitCmds(); FlushQ(); @@ -1372,6 +1372,49 @@ void WrappedVulkan::ContextReplayLog(LogState readType, uint32_t startEventID, u m_State = READING; } +void WrappedVulkan::ApplyInitialContents() +{ + // add a global memory barrier to ensure all writes have finished and are synchronised + // add memory barrier to ensure this copy completes before any subsequent work + // this is a very blunt instrument but it ensures we don't get random artifacts around + // frame restart where we may be skipping a lot of important synchronisation + VkMemoryBarrier memBarrier = { + VK_STRUCTURE_TYPE_MEMORY_BARRIER, NULL, + VK_ACCESS_ALL_WRITE_BITS, + VK_ACCESS_ALL_READ_BITS, + }; + + void *barrier = (void *)&memBarrier; + + VkCommandBuffer cmd = GetNextCmd(); + + VkResult vkr = VK_SUCCESS; + + VkCommandBufferBeginInfo beginInfo = { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT }; + + vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERT(vkr == VK_SUCCESS); + + ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); + RDCASSERT(vkr == VK_SUCCESS); + + // actually apply the initial contents here + GetResourceManager()->ApplyInitialContents(); + + // likewise again to make sure the initial states are all applied + cmd = GetNextCmd(); + + vkr = ObjDisp(cmd)->BeginCommandBuffer(Unwrap(cmd), &beginInfo); + RDCASSERT(vkr == VK_SUCCESS); + + ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); + + vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); + RDCASSERT(vkr == VK_SUCCESS); +} + void WrappedVulkan::ContextProcessChunk(uint64_t offset, VulkanChunkType chunk, bool forceExecute) { m_CurChunkOffset = offset; @@ -1788,7 +1831,7 @@ void WrappedVulkan::ReplayLog(uint32_t frameID, uint32_t startEventID, uint32_t if(!partial) { - GetResourceManager()->ApplyInitialContents(); + ApplyInitialContents(); SubmitCmds(); FlushQ(); diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index d775fd392..1212d46a8 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -466,6 +466,8 @@ private: bool Serialise_SparseInitialState(ResourceId id, WrappedVkImage *im, VulkanResourceManager::InitialContentData contents); bool Apply_SparseInitialState(WrappedVkBuffer *buf, VulkanResourceManager::InitialContentData contents); bool Apply_SparseInitialState(WrappedVkImage *im, VulkanResourceManager::InitialContentData contents); + + void ApplyInitialContents(); vector m_RootEvents, m_Events; bool m_AddedDrawcall; diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index a2f532bf4..905199312 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -790,17 +790,6 @@ bool WrappedVulkan::Apply_SparseInitialState(WrappedVkBuffer *buf, VulkanResourc ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), Unwrap(dstBuf), 1, ®ion); } - // add memory barrier to ensure this copy completes before any subsequent work - VkMemoryBarrier memBarrier = { - VK_STRUCTURE_TYPE_MEMORY_BARRIER, NULL, - VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_WRITE_BIT, - VK_ACCESS_ALL_READ_BITS, - }; - - void *barrier = (void *)&memBarrier; - - ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); - vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); @@ -929,17 +918,6 @@ bool WrappedVulkan::Apply_SparseInitialState(WrappedVkImage *im, VulkanResourceM ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), Unwrap(dstBuf), 1, ®ion); } - // add memory barrier to ensure this copy completes before any subsequent work - VkMemoryBarrier memBarrier = { - VK_STRUCTURE_TYPE_MEMORY_BARRIER, NULL, - VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_WRITE_BIT, - VK_ACCESS_ALL_READ_BITS, - }; - - void *barrier = (void *)&memBarrier; - - ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); - vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); @@ -2033,18 +2011,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VulkanResourceManager VkBufferCopy region = { 0, dstMemOffs, datasize }; ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), Unwrap(dstBuf), 1, ®ion); - - // add memory barrier to ensure this copy completes before any subsequent work - VkMemoryBarrier memBarrier = { - VK_STRUCTURE_TYPE_MEMORY_BARRIER, NULL, - VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_HOST_WRITE_BIT, - VK_ACCESS_ALL_READ_BITS, - }; - - void *barrier = (void *)&memBarrier; - - ObjDisp(cmd)->CmdPipelineBarrier(Unwrap(cmd), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, false, 1, &barrier); - + vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); }