diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 3093c42e1..1b6c1b219 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -912,6 +912,19 @@ string ToStrHelper::Get(const VkImageViewCreat return ret; } +template<> +string ToStrHelper::Get(const VkSparseMemoryBindFlagBits &el) +{ + string ret; + + if(el & VK_SPARSE_MEMORY_BIND_REPLICATE_64KIB_BLOCK_BIT) ret += " | VK_SPARSE_MEMORY_BIND_REPLICATE_64KIB_BLOCK_BIT"; + + if(!ret.empty()) + ret = ret.substr(3); + + return ret; +} + template<> string ToStrHelper::Get(const VkCmdPoolCreateFlagBits &el) { @@ -2378,6 +2391,27 @@ void Serialiser::Serialise(const char *name, VkImageViewCreateInfo &el) Serialise("flags", (VkImageViewCreateFlagBits &)el.flags); } +template<> +void Serialiser::Serialise(const char *name, VkSparseImageMemoryBindInfo &el) +{ + Serialise("subresource", el.subresource); + Serialise("offset", el.offset); + Serialise("extent", el.extent); + Serialise("memOffset", el.memOffset); + SerialiseObject(VkDeviceMemory, "mem", el.mem); + Serialise("flags", (VkSparseMemoryBindFlagBits &)el.flags); +} + +template<> +void Serialiser::Serialise(const char *name, VkSparseMemoryBindInfo &el) +{ + Serialise("rangeOffset", el.rangeOffset); + Serialise("rangeSize", el.rangeSize); + Serialise("memOffset", el.memOffset); + SerialiseObject(VkDeviceMemory, "mem", el.mem); + Serialise("flags", (VkSparseMemoryBindFlagBits &)el.flags); +} + template<> void Serialiser::Serialise(const char *name, VkFramebufferCreateInfo &el) { diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 72b9834ac..73970c023 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -84,6 +84,8 @@ template<> void Serialiser::Serialise(const char *name, VkBufferCreateInfo &el); template<> void Serialiser::Serialise(const char *name, VkBufferViewCreateInfo &el); template<> void Serialiser::Serialise(const char *name, VkImageCreateInfo &el); template<> void Serialiser::Serialise(const char *name, VkImageViewCreateInfo &el); +template<> void Serialiser::Serialise(const char *name, VkSparseImageMemoryBindInfo &el); +template<> void Serialiser::Serialise(const char *name, VkSparseMemoryBindInfo &el); template<> void Serialiser::Serialise(const char *name, VkFramebufferCreateInfo &el); template<> void Serialiser::Serialise(const char *name, VkRenderPassCreateInfo &el); template<> void Serialiser::Serialise(const char *name, VkRenderPassBeginInfo &el); @@ -214,6 +216,10 @@ enum VulkanChunkType BIND_BUFFER_MEM, BIND_IMAGE_MEM, + BIND_SPARSE_BUF, + BIND_SPARSE_OPAQUE_IM, + BIND_SPARSE_IM, + BEGIN_RENDERPASS, NEXT_SUBPASS, EXEC_CMDS, diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 895fdb298..3c4d0e099 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -103,6 +103,10 @@ const char *VkChunkNames[] = "vkQueueSubmit", "vkBindBufferMemory", "vkBindImageMemory", + + "vkQueueBindSparseBufferMemory", + "vkQueueBindSparseImageOpaqueMemory", + "vkQueueBindSparseImageMemory", "vkCmdBeginRenderPass", "vkCmdNextSubpass", @@ -1475,6 +1479,16 @@ void WrappedVulkan::ProcessChunk(uint64_t offset, VulkanChunkType context) Serialise_vkBindImageMemory(GetMainSerialiser(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, 0); break; + case BIND_SPARSE_BUF: + Serialise_vkQueueBindSparseBufferMemory(GetMainSerialiser(), VK_NULL_HANDLE, VK_NULL_HANDLE, 0, NULL); + break; + case BIND_SPARSE_OPAQUE_IM: + Serialise_vkQueueBindSparseImageOpaqueMemory(GetMainSerialiser(), VK_NULL_HANDLE, VK_NULL_HANDLE, 0, NULL); + break; + case BIND_SPARSE_IM: + Serialise_vkQueueBindSparseImageMemory(GetMainSerialiser(), VK_NULL_HANDLE, VK_NULL_HANDLE, 0, NULL); + break; + case BEGIN_RENDERPASS: Serialise_vkCmdBeginRenderPass(GetMainSerialiser(), VK_NULL_HANDLE, NULL, VK_RENDER_PASS_CONTENTS_MAX_ENUM); break; diff --git a/renderdoc/driver/vulkan/vk_resources.cpp b/renderdoc/driver/vulkan/vk_resources.cpp index 3bc96238c..446878ad8 100644 --- a/renderdoc/driver/vulkan/vk_resources.cpp +++ b/renderdoc/driver/vulkan/vk_resources.cpp @@ -508,3 +508,11 @@ VkResourceRecord::~VkResourceRecord() SAFE_DELETE(sparseInfo); } } + +void SparseMapping::Update(uint32_t numBindings, const VkSparseImageMemoryBindInfo *pBindings) +{ +} + +void SparseMapping::Update(uint32_t numBindings, const VkSparseMemoryBindInfo *pBindings) +{ +} diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index c47edbb95..ac92be08b 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -596,6 +596,9 @@ struct SparseMapping // pagetable per image aspect (some may be NULL) // in order of width first, then height, then depth pair *pages[VK_IMAGE_ASPECT_NUM]; + + void Update(uint32_t numBindings, const VkSparseImageMemoryBindInfo *pBindings); + void Update(uint32_t numBindings, const VkSparseMemoryBindInfo *pBindings); }; struct CmdBufferRecordingInfo diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index 4c74c98c1..d581b3a56 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -595,7 +595,7 @@ bool WrappedVulkan::Serialise_vkQueueWaitIdle(Serialiser* localSerialiser, VkQue { SERIALISE_ELEMENT(ResourceId, id, GetResID(queue)); - if(m_State < WRITING_CAPFRAME) + if(m_State < WRITING) { queue = GetResourceManager()->GetLiveHandle(id); ObjDisp(queue)->QueueWaitIdle(Unwrap(queue)); diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index 6c5a06e0f..91c4f973b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -660,7 +660,22 @@ bool WrappedVulkan::Serialise_vkQueueBindSparseBufferMemory( uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) { - // VKTODOHIGH stub function + SERIALISE_ELEMENT(ResourceId, qid, GetResID(queue)); + SERIALISE_ELEMENT(ResourceId, bufid, GetResID(buffer)); + + SERIALISE_ELEMENT(uint32_t, num, numBindings); + SERIALISE_ELEMENT_ARR(VkSparseMemoryBindInfo, binds, pBindInfo, num); + + if(m_State < WRITING && GetResourceManager()->HasLiveResource(bufid)) + { + queue = GetResourceManager()->GetLiveHandle(qid); + buffer = GetResourceManager()->GetLiveHandle(bufid); + + ObjDisp(queue)->QueueBindSparseBufferMemory(Unwrap(queue), Unwrap(buffer), num, binds); + } + + SAFE_DELETE_ARRAY(binds); + return true; } @@ -670,9 +685,26 @@ VkResult WrappedVulkan::vkQueueBindSparseBufferMemory( uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) { - // VKTODOHIGH stub function - RDCWARN("Sparse memory operations are not yet implemented"); - return ObjDisp(queue)->QueueBindSparseBufferMemory(Unwrap(queue), Unwrap(buffer), numBindings, pBindInfo); + if(m_State >= WRITING_CAPFRAME) + { + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CONTEXT(BIND_SPARSE_BUF); + Serialise_vkQueueBindSparseBufferMemory(localSerialiser, queue, buffer, numBindings, pBindInfo); + + m_FrameCaptureRecord->AddChunk(scope.Get()); + GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read); + // image isn't marked referenced. If the only ref is a memory bind, we just skip it + } + + if(m_State >= WRITING) + GetRecord(buffer)->sparseInfo->Update(numBindings, pBindInfo); + + VkSparseMemoryBindInfo *unwrappedBinds = GetTempArray(numBindings); + memcpy(unwrappedBinds, pBindInfo, sizeof(VkSparseMemoryBindInfo)*numBindings); + for(uint32_t i=0; i < numBindings; i++) unwrappedBinds[i].mem = Unwrap(unwrappedBinds[i].mem); + + return ObjDisp(queue)->QueueBindSparseBufferMemory(Unwrap(queue), Unwrap(buffer), numBindings, unwrappedBinds); } bool WrappedVulkan::Serialise_vkQueueBindSparseImageOpaqueMemory( @@ -682,7 +714,22 @@ bool WrappedVulkan::Serialise_vkQueueBindSparseImageOpaqueMemory( uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) { - // VKTODOHIGH stub function + SERIALISE_ELEMENT(ResourceId, qid, GetResID(queue)); + SERIALISE_ELEMENT(ResourceId, imid, GetResID(image)); + + SERIALISE_ELEMENT(uint32_t, num, numBindings); + SERIALISE_ELEMENT_ARR(VkSparseMemoryBindInfo, binds, pBindInfo, num); + + if(m_State < WRITING && GetResourceManager()->HasLiveResource(imid)) + { + queue = GetResourceManager()->GetLiveHandle(qid); + image = GetResourceManager()->GetLiveHandle(imid); + + ObjDisp(queue)->QueueBindSparseImageOpaqueMemory(Unwrap(queue), Unwrap(image), num, binds); + } + + SAFE_DELETE_ARRAY(binds); + return true; } @@ -692,9 +739,26 @@ VkResult WrappedVulkan::vkQueueBindSparseImageOpaqueMemory( uint32_t numBindings, const VkSparseMemoryBindInfo* pBindInfo) { - // VKTODOHIGH stub function - RDCWARN("Sparse memory operations are not yet implemented"); - return ObjDisp(queue)->QueueBindSparseImageOpaqueMemory(Unwrap(queue), Unwrap(image), numBindings, pBindInfo); + if(m_State >= WRITING_CAPFRAME) + { + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CONTEXT(BIND_SPARSE_OPAQUE_IM); + Serialise_vkQueueBindSparseImageOpaqueMemory(localSerialiser, queue, image, numBindings, pBindInfo); + + m_FrameCaptureRecord->AddChunk(scope.Get()); + GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read); + // image isn't marked referenced. If the only ref is a memory bind, we just skip it + } + + if(m_State >= WRITING) + GetRecord(image)->sparseInfo->Update(numBindings, pBindInfo); + + VkSparseMemoryBindInfo *unwrappedBinds = GetTempArray(numBindings); + memcpy(unwrappedBinds, pBindInfo, sizeof(VkSparseMemoryBindInfo)*numBindings); + for(uint32_t i=0; i < numBindings; i++) unwrappedBinds[i].mem = Unwrap(unwrappedBinds[i].mem); + + return ObjDisp(queue)->QueueBindSparseImageOpaqueMemory(Unwrap(queue), Unwrap(image), numBindings, unwrappedBinds); } bool WrappedVulkan::Serialise_vkQueueBindSparseImageMemory( @@ -704,7 +768,22 @@ bool WrappedVulkan::Serialise_vkQueueBindSparseImageMemory( uint32_t numBindings, const VkSparseImageMemoryBindInfo* pBindInfo) { - // VKTODOHIGH stub function + SERIALISE_ELEMENT(ResourceId, qid, GetResID(queue)); + SERIALISE_ELEMENT(ResourceId, imid, GetResID(image)); + + SERIALISE_ELEMENT(uint32_t, num, numBindings); + SERIALISE_ELEMENT_ARR(VkSparseImageMemoryBindInfo, binds, pBindInfo, num); + + if(m_State < WRITING && GetResourceManager()->HasLiveResource(imid)) + { + queue = GetResourceManager()->GetLiveHandle(qid); + image = GetResourceManager()->GetLiveHandle(imid); + + ObjDisp(queue)->QueueBindSparseImageMemory(Unwrap(queue), Unwrap(image), num, binds); + } + + SAFE_DELETE_ARRAY(binds); + return true; } @@ -714,9 +793,26 @@ VkResult WrappedVulkan::vkQueueBindSparseImageMemory( uint32_t numBindings, const VkSparseImageMemoryBindInfo* pBindInfo) { - // VKTODOHIGH stub function - RDCWARN("Sparse memory operations are not yet implemented"); - return ObjDisp(queue)->QueueBindSparseImageMemory(Unwrap(queue), Unwrap(image), numBindings, pBindInfo); + if(m_State >= WRITING_CAPFRAME) + { + CACHE_THREAD_SERIALISER(); + + SCOPED_SERIALISE_CONTEXT(BIND_SPARSE_IM); + Serialise_vkQueueBindSparseImageMemory(localSerialiser, queue, image, numBindings, pBindInfo); + + m_FrameCaptureRecord->AddChunk(scope.Get()); + GetResourceManager()->MarkResourceFrameReferenced(GetResID(queue), eFrameRef_Read); + // image isn't marked referenced. If the only ref is a memory bind, we just skip it + } + + if(m_State >= WRITING) + GetRecord(image)->sparseInfo->Update(numBindings, pBindInfo); + + VkSparseImageMemoryBindInfo *unwrappedBinds = GetTempArray(numBindings); + memcpy(unwrappedBinds, pBindInfo, sizeof(VkSparseImageMemoryBindInfo)*numBindings); + for(uint32_t i=0; i < numBindings; i++) unwrappedBinds[i].mem = Unwrap(unwrappedBinds[i].mem); + + return ObjDisp(queue)->QueueBindSparseImageMemory(Unwrap(queue), Unwrap(image), numBindings, unwrappedBinds); } bool WrappedVulkan::Serialise_vkCreateBuffer(