diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 17a8aa995..2a6ee9b5a 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -890,17 +890,6 @@ private: ResourceDescription &GetResourceDesc(ResourceId id); - bool Prepare_SparseInitialState(WrappedVkBuffer *buf); - bool Prepare_SparseInitialState(WrappedVkImage *im); - template - bool Serialise_SparseBufferInitialState(SerialiserType &ser, ResourceId id, - const VkInitialContents *contents); - template - bool Serialise_SparseImageInitialState(SerialiserType &ser, ResourceId id, - const VkInitialContents *contents); - bool Apply_SparseInitialState(WrappedVkBuffer *buf, const VkInitialContents &contents); - bool Apply_SparseInitialState(WrappedVkImage *im, const VkInitialContents &contents); - void ApplyInitialContents(); rdcarray m_RootEvents, m_Events; @@ -914,6 +903,8 @@ private: ResourceId m_LastPresentedImage; + std::set m_SparseBindResources; + ReplayStatus m_FailedReplayStatus = ReplayStatus::APIReplayFailed; VulkanDrawcallTreeNode m_ParentDrawcall; diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index 73a950893..b75602e22 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -1839,7 +1839,11 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten // we should only get here if we have a sparse page table to apply RDCASSERT(initial.tag == VkInitialContents::SparseTableOnly, (uint32_t)initial.tag); - if(initial.sparseBind) + // only apply sparse bindings the first time we apply initial contents, OR if there are sparse + // bindings of this resource in the capture. This is a simple optimisation to avoid needing to + // re-bind the sparse pages every time if they don't change. + if(initial.sparseBind && + (IsLoading(m_State) || m_SparseBindResources.find(id) != m_SparseBindResources.end())) ObjDisp(m_Queue)->QueueBindSparse(Unwrap(m_Queue), 1, initial.sparseBind, VK_NULL_HANDLE); } else if(type == eResImage) @@ -1869,7 +1873,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten // apply sparse page table mappings and skip memory-bound optimisations if(initial.sparseBind) { - ObjDisp(m_Queue)->QueueBindSparse(Unwrap(m_Queue), 1, initial.sparseBind, VK_NULL_HANDLE); + // only apply sparse bindings the first time we apply initial contents, OR if there are sparse + // bindings of this resource in the capture. This is a simple optimisation to avoid needing to + // re-bind the sparse pages every time if they don't change. + if(IsLoading(m_State) || m_SparseBindResources.find(id) != m_SparseBindResources.end()) + ObjDisp(m_Queue)->QueueBindSparse(Unwrap(m_Queue), 1, initial.sparseBind, VK_NULL_HANDLE); + + // however we don't track the memory bound to it, so always consider it uninitialised. initialized = false; } else if(initialized && boundMemory != ResourceId()) diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index c3521bc30..dd83a9f28 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -1571,6 +1571,9 @@ bool WrappedVulkan::Serialise_vkQueueBindSparse(SerialiserType &ser, VkQueue que } else { + if(IsLoading(m_State)) + m_SparseBindResources.insert(GetResID(buf[i].buffer)); + buf[i].buffer = Unwrap(buf[i].buffer); VkSparseMemoryBind *binds = (VkSparseMemoryBind *)buf[i].pBinds; @@ -1590,6 +1593,9 @@ bool WrappedVulkan::Serialise_vkQueueBindSparse(SerialiserType &ser, VkQueue que } else { + if(IsLoading(m_State)) + m_SparseBindResources.insert(GetResID(imopaque[i].image)); + imopaque[i].image = Unwrap(imopaque[i].image); VkSparseMemoryBind *binds = (VkSparseMemoryBind *)imopaque[i].pBinds; @@ -1608,6 +1614,9 @@ bool WrappedVulkan::Serialise_vkQueueBindSparse(SerialiserType &ser, VkQueue que } else { + if(IsLoading(m_State)) + m_SparseBindResources.insert(GetResID(im[i].image)); + im[i].image = Unwrap(im[i].image); VkSparseImageMemoryBind *binds = (VkSparseImageMemoryBind *)im[i].pBinds;