diff --git a/renderdoc/driver/vulkan/vk_info.h b/renderdoc/driver/vulkan/vk_info.h index d86926041..9544b759e 100644 --- a/renderdoc/driver/vulkan/vk_info.h +++ b/renderdoc/driver/vulkan/vk_info.h @@ -212,6 +212,8 @@ struct VulkanCreationInfo void Init(VulkanResourceManager *resourceMan, const VkMemoryAllocInfo* pAllocInfo); uint64_t size; + + VkBuffer wholeMemBuf; }; map m_Memory; diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index 44c81a69b..fedaea5f6 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -768,31 +768,18 @@ bool WrappedVulkan::Apply_SparseInitialState(WrappedVkBuffer *buf, VulkanResourc VK_SHARING_MODE_EXCLUSIVE, 0, NULL, }; - vector bufdeletes; - for(uint32_t i=0; i < info->numUniqueMems; i++) { VkDeviceMemory dstMem = GetResourceManager()->GetLiveHandle(info->memDataOffs[i].memId); - // since this is short lived it isn't wrapped. Note that we want - // to cache this up front, so it will then be wrapped - VkBuffer dstBuf; + VkBuffer dstBuf = m_CreationInfo.m_Memory[GetResID(dstMem)].wholeMemBuf; bufInfo.size = m_CreationInfo.m_Memory[GetResID(dstMem)].size; - - // VKTODOMED this should be created once up front, not every time - vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &dstBuf); - RDCASSERT(vkr == VK_SUCCESS); - - vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), dstBuf, Unwrap(dstMem), 0); - RDCASSERT(vkr == VK_SUCCESS); // fill the whole memory from the given offset VkBufferCopy region = { info->memDataOffs[i].memOffs, 0, bufInfo.size }; - ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), dstBuf, 1, ®ion); - - bufdeletes.push_back(dstBuf); + ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), Unwrap(dstBuf), 1, ®ion); } // add memory barrier to ensure this copy completes before any subsequent work @@ -809,16 +796,6 @@ bool WrappedVulkan::Apply_SparseInitialState(WrappedVkBuffer *buf, VulkanResourc vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); - // VKTODOLOW if this dstBuf was persistent or at least cached - // we could batch these command buffers better and wouldn't - // need to flush at all until application of all init states - // is over - SubmitCmds(); - FlushQ(); - - for(size_t i=0; i < bufdeletes.size(); i++) - ObjDisp(d)->DestroyBuffer(Unwrap(d), bufdeletes[i]); - return true; } @@ -873,31 +850,19 @@ bool WrappedVulkan::Apply_SparseInitialState(WrappedVkImage *im, VulkanResourceM VK_SHARING_MODE_EXCLUSIVE, 0, NULL, }; - vector bufdeletes; - for(uint32_t i=0; i < info->numUniqueMems; i++) { VkDeviceMemory dstMem = GetResourceManager()->GetLiveHandle(info->memDataOffs[i].memId); // since this is short lived it isn't wrapped. Note that we want // to cache this up front, so it will then be wrapped - VkBuffer dstBuf; - + VkBuffer dstBuf = m_CreationInfo.m_Memory[GetResID(dstMem)].wholeMemBuf; bufInfo.size = m_CreationInfo.m_Memory[GetResID(dstMem)].size; - - // VKTODOMED this should be created once up front, not every time - vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &dstBuf); - RDCASSERT(vkr == VK_SUCCESS); - - vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), dstBuf, Unwrap(dstMem), 0); - RDCASSERT(vkr == VK_SUCCESS); // fill the whole memory from the given offset VkBufferCopy region = { info->memDataOffs[i].memOffs, 0, bufInfo.size }; - ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), dstBuf, 1, ®ion); - - bufdeletes.push_back(dstBuf); + ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), Unwrap(dstBuf), 1, ®ion); } // add memory barrier to ensure this copy completes before any subsequent work @@ -914,16 +879,6 @@ bool WrappedVulkan::Apply_SparseInitialState(WrappedVkImage *im, VulkanResourceM vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); - // VKTODOLOW if this dstBuf was persistent or at least cached - // we could batch these command buffers better and wouldn't - // need to flush at all until application of all init states - // is over - SubmitCmds(); - FlushQ(); - - for(size_t i=0; i < bufdeletes.size(); i++) - ObjDisp(d)->DestroyBuffer(Unwrap(d), bufdeletes[i]); - return true; } @@ -1969,20 +1924,11 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VulkanResourceManager VK_SHARING_MODE_EXCLUSIVE, 0, NULL, }; - // since this is short lived it isn't wrapped. Note that we want - // to cache this up front, so it will then be wrapped - VkBuffer dstBuf; - - // VKTODOMED this should be created once up front, not every time - vkr = ObjDisp(d)->CreateBuffer(Unwrap(d), &bufInfo, &dstBuf); - RDCASSERT(vkr == VK_SUCCESS); - - vkr = ObjDisp(d)->BindBufferMemory(Unwrap(d), dstBuf, Unwrap(dstMem), 0); - RDCASSERT(vkr == VK_SUCCESS); + VkBuffer dstBuf = m_CreationInfo.m_Memory[id].wholeMemBuf; VkBufferCopy region = { 0, dstMemOffs, datasize }; - ObjDisp(cmd)->CmdCopyBuffer(Unwrap(cmd), Unwrap(srcBuf), dstBuf, 1, ®ion); + 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 = { @@ -1997,15 +1943,6 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, VulkanResourceManager vkr = ObjDisp(cmd)->EndCommandBuffer(Unwrap(cmd)); RDCASSERT(vkr == VK_SUCCESS); - - // VKTODOLOW if this dstBuf was persistent or at least cached - // we could batch these command buffers better and wouldn't - // need to flush at all until application of all init states - // is over - SubmitCmds(); - FlushQ(); - - ObjDisp(d)->DestroyBuffer(Unwrap(d), dstBuf); } else { diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index a9cdb1d37..e907603a2 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -172,6 +172,28 @@ bool WrappedVulkan::Serialise_vkAllocMemory( GetResourceManager()->AddLiveResource(id, mem); m_CreationInfo.m_Memory[live].Init(GetResourceManager(), &info); + + // create a buffer with the whole memory range bound, for copying to and from + // conveniently (for initial state data) + VkBuffer buf = VK_NULL_HANDLE; + + VkBufferCreateInfo bufInfo = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, + info.allocationSize, VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0, + VK_SHARING_MODE_EXCLUSIVE, 0, NULL, + }; + + ret = ObjDisp(device)->CreateBuffer(Unwrap(device), &bufInfo, &buf); + RDCASSERT(ret == VK_SUCCESS); + + ResourceId bufid = GetResourceManager()->WrapResource(Unwrap(device), buf); + + ObjDisp(device)->BindBufferMemory(Unwrap(device), Unwrap(buf), Unwrap(mem), 0); + + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(bufid, buf); + + m_CreationInfo.m_Memory[live].wholeMemBuf = buf; } } @@ -230,6 +252,28 @@ VkResult WrappedVulkan::vkAllocMemory( GetResourceManager()->AddLiveResource(id, *pMem); m_CreationInfo.m_Memory[id].Init(GetResourceManager(), pAllocInfo); + + // create a buffer with the whole memory range bound, for copying to and from + // conveniently (for initial state data) + VkBuffer buf = VK_NULL_HANDLE; + + VkBufferCreateInfo bufInfo = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, NULL, + info.allocationSize, VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT|VK_BUFFER_USAGE_TRANSFER_DESTINATION_BIT, 0, + VK_SHARING_MODE_EXCLUSIVE, 0, NULL, + }; + + ret = ObjDisp(device)->CreateBuffer(Unwrap(device), &bufInfo, &buf); + RDCASSERT(ret == VK_SUCCESS); + + ResourceId bufid = GetResourceManager()->WrapResource(Unwrap(device), buf); + + ObjDisp(device)->BindBufferMemory(Unwrap(device), Unwrap(buf), Unwrap(*pMem), 0); + + // register as a live-only resource, so it is cleaned up properly + GetResourceManager()->AddLiveResource(bufid, buf); + + m_CreationInfo.m_Memory[id].wholeMemBuf = buf; } }