From b8f7029d59a301dd4502128fa9673b13f058f693 Mon Sep 17 00:00:00 2001 From: baldurk Date: Thu, 26 Nov 2020 11:29:49 +0000 Subject: [PATCH] Refactor chunk-allocator to two level pool and allocator * This fixes a bug with granular command buffer resetting. On vulkan we assume each command buffer owns the entirety of the pages it uses, so they can be reset all together. However there's nothing to stop an application from allocating from the same pool on the same thread interleaved to two command buffers. It's unexpected because of the threading rules but perfectly legal. * In this case we need to ensure that the command buffers have disjoint sets of pages because they may not be reset together and one may be in used while another is reset and even re-recorded over. This can't be achieved with a single allocator, so instead we split the pool (that owns/provides/frees pages) from the allocator (that grabs whole pages and suballocates for chunks). --- renderdoc/driver/d3d12/d3d12_resources.h | 5 +- renderdoc/driver/vulkan/vk_core.cpp | 9 +- renderdoc/driver/vulkan/vk_resources.h | 36 ++-- .../driver/vulkan/wrappers/vk_cmd_funcs.cpp | 96 ++++----- .../driver/vulkan/wrappers/vk_draw_funcs.cpp | 52 ++--- .../vulkan/wrappers/vk_dynamic_funcs.cpp | 46 ++--- .../driver/vulkan/wrappers/vk_sync_funcs.cpp | 6 +- renderdoc/serialise/serialiser.cpp | 194 ++++++++++-------- renderdoc/serialise/serialiser.h | 133 +++++++----- 9 files changed, 314 insertions(+), 263 deletions(-) diff --git a/renderdoc/driver/d3d12/d3d12_resources.h b/renderdoc/driver/d3d12/d3d12_resources.h index f305e2ff4..7a9272859 100644 --- a/renderdoc/driver/d3d12/d3d12_resources.h +++ b/renderdoc/driver/d3d12/d3d12_resources.h @@ -333,6 +333,7 @@ class WrappedID3D12CommandAllocator : public WrappedDeviceChild12Reset(); diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 532ce9df8..859b9254b 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -2048,10 +2048,15 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd) // otherwise order must be preserved (vs. queue submits and desc set updates) for(size_t i = 0; i < m_CmdBufferRecords.size(); i++) { + RDCDEBUG("Adding chunks from command buffer %s", + ToStr(m_CmdBufferRecords[i]->GetResourceID()).c_str()); + + size_t prevSize = recordlist.size(); + (void)prevSize; + m_CmdBufferRecords[i]->Insert(recordlist); - RDCDEBUG("Adding %u chunks to file serialiser from command buffer %s", - (uint32_t)recordlist.size(), ToStr(m_CmdBufferRecords[i]->GetResourceID()).c_str()); + RDCDEBUG("Added %zu chunks to file serialiser", recordlist.size() - prevSize); } m_FrameCaptureRecord->Insert(recordlist); diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index f0b411914..d73456849 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -989,19 +989,35 @@ struct MemRefs; struct ImgRefs; struct ImageState; +struct CmdPoolInfo +{ + CmdPoolInfo() : pool(4 * 1024) {} + CmdPoolInfo(const CmdPoolInfo &) = delete; + CmdPoolInfo(CmdPoolInfo &&) = delete; + CmdPoolInfo &operator=(const CmdPoolInfo &) = delete; + ~CmdPoolInfo() + { // nothing to do, pool will free its pages + } + + uint32_t queueFamilyIndex; + ChunkPagePool pool; +}; + struct CmdBufferRecordingInfo { + CmdBufferRecordingInfo(CmdPoolInfo &pool) : alloc(pool.pool) {} + CmdBufferRecordingInfo(const CmdBufferRecordingInfo &) = delete; + CmdBufferRecordingInfo(CmdBufferRecordingInfo &&) = delete; + CmdBufferRecordingInfo &operator=(const CmdBufferRecordingInfo &) = delete; ~CmdBufferRecordingInfo() { - if(alloc) - alloc->ResetPageSet(pageSet); + // nothing to do explicitly, the alloc destructor will clean up any pages it holds } VkDevice device; VkCommandBufferAllocateInfo allocInfo; - ChunkAllocator *alloc = NULL; - rdcarray pageSet; + ChunkAllocator alloc; VkResourceRecord *framebuffer = NULL; VkResourceRecord *allocRecord = NULL; @@ -1076,17 +1092,6 @@ struct DescPoolInfo rdcarray freelist; }; -struct CmdPoolInfo -{ - CmdPoolInfo(uint32_t allocPageSize, bool allowReset) - : alloc(allocPageSize), allowCmdBufReset(allowReset) - { - } - uint32_t queueFamilyIndex; - bool allowCmdBufReset; - ChunkAllocator alloc; -}; - struct MemMapState { VkBuffer wholeMemBuf = VK_NULL_HANDLE; @@ -2129,6 +2134,7 @@ public: { RDCASSERT(cmdInfo); SwapChunks(bakedCommands); + cmdInfo->alloc.swap(bakedCommands->cmdInfo->alloc); cmdInfo->boundDescSets.swap(bakedCommands->cmdInfo->boundDescSets); cmdInfo->subcmds.swap(bakedCommands->cmdInfo->subcmds); cmdInfo->sparse.swap(bakedCommands->cmdInfo->sparse); diff --git a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp index 2fac11625..b20c2477b 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_cmd_funcs.cpp @@ -523,14 +523,12 @@ VkResult WrappedVulkan::vkCreateCommandPool(VkDevice device, chunk = scope.Get(); } - bool allowReset = (pCreateInfo->flags & VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT) != 0; - VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pCmdPool); // if we can reset command buffers we need to allocate smaller pages because command buffers // may be reset, so each page can only be allocated by at most one command buffer. // if not, we allocate bigger pages on the assumption that the application won't waste memory // by allocating lots of command pools that barely get used. - record->cmdPoolInfo = new CmdPoolInfo(allowReset ? 4 * 1024 : 128 * 1024, allowReset); + record->cmdPoolInfo = new CmdPoolInfo; record->cmdPoolInfo->queueFamilyIndex = pCreateInfo->queueFamilyIndex; record->AddChunk(chunk); } @@ -547,7 +545,7 @@ VkResult WrappedVulkan::vkResetCommandPool(VkDevice device, VkCommandPool cmdPoo VkCommandPoolResetFlags flags) { if(Atomic::CmpExch32(&m_ReuseEnabled, 1, 1) == 1) - GetRecord(cmdPool)->cmdPoolInfo->alloc.Reset(); + GetRecord(cmdPool)->cmdPoolInfo->pool.Reset(); return ObjDisp(device)->ResetCommandPool(Unwrap(device), Unwrap(cmdPool), flags); } @@ -555,7 +553,7 @@ VkResult WrappedVulkan::vkResetCommandPool(VkDevice device, VkCommandPool cmdPoo void WrappedVulkan::vkTrimCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolTrimFlags flags) { - GetRecord(commandPool)->cmdPoolInfo->alloc.Trim(); + GetRecord(commandPool)->cmdPoolInfo->pool.Trim(); return ObjDisp(device)->TrimCommandPool(Unwrap(device), Unwrap(commandPool), flags); } @@ -687,7 +685,7 @@ VkResult WrappedVulkan::vkAllocateCommandBuffers(VkDevice device, // we don't support any extensions on VkCommandBufferCreateInfo anyway RDCASSERT(pAllocateInfo->pNext == NULL); - record->cmdInfo = new CmdBufferRecordingInfo(); + record->cmdInfo = new CmdBufferRecordingInfo(*record->pool->cmdPoolInfo); record->cmdInfo->device = device; record->cmdInfo->allocInfo = *pAllocateInfo; @@ -696,7 +694,6 @@ VkResult WrappedVulkan::vkAllocateCommandBuffers(VkDevice device, record->cmdInfo->present = false; record->cmdInfo->beginCapture = false; record->cmdInfo->endCapture = false; - record->cmdInfo->alloc = &record->pool->cmdPoolInfo->alloc; } else { @@ -1028,10 +1025,9 @@ VkResult WrappedVulkan::vkBeginCommandBuffer(VkCommandBuffer commandBuffer, record->bakedCommands->DisableChunkLocking(); record->bakedCommands->InternalResource = true; record->bakedCommands->Resource = (WrappedVkRes *)commandBuffer; - record->bakedCommands->cmdInfo = new CmdBufferRecordingInfo(); + record->bakedCommands->cmdInfo = new CmdBufferRecordingInfo(*record->pool->cmdPoolInfo); record->bakedCommands->cmdInfo->device = record->cmdInfo->device; - record->bakedCommands->cmdInfo->alloc = record->cmdInfo->alloc; record->bakedCommands->cmdInfo->allocInfo = record->cmdInfo->allocInfo; record->bakedCommands->cmdInfo->present = false; record->bakedCommands->cmdInfo->beginCapture = false; @@ -1043,7 +1039,7 @@ VkResult WrappedVulkan::vkBeginCommandBuffer(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkBeginCommandBuffer); Serialise_vkBeginCommandBuffer(ser, commandBuffer, pBeginInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } if(pBeginInfo->pInheritanceInfo) @@ -1242,13 +1238,9 @@ VkResult WrappedVulkan::vkEndCommandBuffer(VkCommandBuffer commandBuffer) SCOPED_SERIALISE_CHUNK(VulkanChunk::vkEndCommandBuffer); Serialise_vkEndCommandBuffer(ser, commandBuffer); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } - // if we can't reset command buffers there's no need to claim a set of pages - if(record->pool->cmdPoolInfo->allowCmdBufReset) - record->bakedCommands->cmdInfo->pageSet = record->cmdInfo->alloc->GetPageSet(); - record->Bake(); } @@ -1598,7 +1590,7 @@ void WrappedVulkan::vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginRenderPass); Serialise_vkCmdBeginRenderPass(ser, commandBuffer, pRenderPassBegin, contents); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(pRenderPassBegin->renderPass), eFrameRef_Read); VkResourceRecord *fb = GetRecord(pRenderPassBegin->framebuffer); @@ -1764,7 +1756,7 @@ void WrappedVulkan::vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassCon SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdNextSubpass); Serialise_vkCmdNextSubpass(ser, commandBuffer, contents); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1896,7 +1888,7 @@ void WrappedVulkan::vkCmdEndRenderPass(VkCommandBuffer commandBuffer) SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndRenderPass); Serialise_vkCmdEndRenderPass(ser, commandBuffer); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); const rdcarray &barriers = record->cmdInfo->rpbarriers; @@ -2209,7 +2201,7 @@ void WrappedVulkan::vkCmdBeginRenderPass2(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginRenderPass2); Serialise_vkCmdBeginRenderPass2(ser, commandBuffer, pRenderPassBegin, pSubpassBeginInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(pRenderPassBegin->renderPass), eFrameRef_Read); VkResourceRecord *fb = GetRecord(pRenderPassBegin->framebuffer); @@ -2401,7 +2393,7 @@ void WrappedVulkan::vkCmdNextSubpass2(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdNextSubpass2); Serialise_vkCmdNextSubpass2(ser, commandBuffer, pSubpassBeginInfo, pSubpassEndInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -2539,7 +2531,7 @@ void WrappedVulkan::vkCmdEndRenderPass2(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndRenderPass2); Serialise_vkCmdEndRenderPass2(ser, commandBuffer, pSubpassEndInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); const rdcarray &barriers = record->cmdInfo->rpbarriers; @@ -2766,7 +2758,7 @@ void WrappedVulkan::vkCmdBindPipeline(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBindPipeline); Serialise_vkCmdBindPipeline(ser, commandBuffer, pipelineBindPoint, pipeline); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(pipeline), eFrameRef_Read); } } @@ -2925,7 +2917,7 @@ void WrappedVulkan::vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, Serialise_vkCmdBindDescriptorSets(ser, commandBuffer, pipelineBindPoint, layout, firstSet, setCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(layout), eFrameRef_Read); record->cmdInfo->boundDescSets.insert(pDescriptorSets, pDescriptorSets + setCount); } @@ -3014,7 +3006,7 @@ void WrappedVulkan::vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32 Serialise_vkCmdBindVertexBuffers(ser, commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < bindingCount; i++) { // binding NULL is legal with robustness2 @@ -3118,7 +3110,7 @@ void WrappedVulkan::vkCmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer, ui Serialise_vkCmdBindVertexBuffers2EXT(ser, commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets, pSizes, pStrides); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < bindingCount; i++) { // binding NULL is legal with robustness2 @@ -3207,7 +3199,7 @@ void WrappedVulkan::vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBindIndexBuffer); Serialise_vkCmdBindIndexBuffer(ser, commandBuffer, buffer, offset, indexType); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(buffer), 0, VK_WHOLE_SIZE, eFrameRef_Read); } } @@ -3271,7 +3263,7 @@ void WrappedVulkan::vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer de SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdUpdateBuffer); Serialise_vkCmdUpdateBuffer(ser, commandBuffer, destBuffer, destOffset, dataSize, pData); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(destBuffer), destOffset, dataSize, eFrameRef_CompleteWrite); @@ -3348,7 +3340,7 @@ void WrappedVulkan::vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipeline SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdPushConstants); Serialise_vkCmdPushConstants(ser, commandBuffer, layout, stageFlags, start, length, values); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(layout), eFrameRef_Read); } } @@ -3544,7 +3536,7 @@ void WrappedVulkan::vkCmdPipelineBarrier( pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); if(imageMemoryBarrierCount > 0) { @@ -3610,7 +3602,7 @@ void WrappedVulkan::vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdWriteTimestamp); Serialise_vkCmdWriteTimestamp(ser, commandBuffer, pipelineStage, queryPool, query); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(queryPool), eFrameRef_Read); } @@ -3680,7 +3672,7 @@ void WrappedVulkan::vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQ Serialise_vkCmdCopyQueryPoolResults(ser, commandBuffer, queryPool, firstQuery, queryCount, destBuffer, destOffset, destStride, flags); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(queryPool), eFrameRef_Read); @@ -3744,7 +3736,7 @@ void WrappedVulkan::vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool q SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginQuery); Serialise_vkCmdBeginQuery(ser, commandBuffer, queryPool, query, flags); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(queryPool), eFrameRef_Read); } } @@ -3796,7 +3788,7 @@ void WrappedVulkan::vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool que SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndQuery); Serialise_vkCmdEndQuery(ser, commandBuffer, queryPool, query); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(queryPool), eFrameRef_Read); } } @@ -3857,7 +3849,7 @@ void WrappedVulkan::vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPo SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdResetQueryPool); Serialise_vkCmdResetQueryPool(ser, commandBuffer, queryPool, firstQuery, queryCount); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(queryPool), eFrameRef_Read); } } @@ -4189,7 +4181,7 @@ void WrappedVulkan::vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdExecuteCommands); Serialise_vkCmdExecuteCommands(ser, commandBuffer, commandBufferCount, pCommandBuffers); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < commandBufferCount; i++) { @@ -4274,7 +4266,7 @@ void WrappedVulkan::vkCmdDebugMarkerBeginEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDebugMarkerBeginEXT); Serialise_vkCmdDebugMarkerBeginEXT(ser, commandBuffer, pMarker); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -4347,7 +4339,7 @@ void WrappedVulkan::vkCmdDebugMarkerEndEXT(VkCommandBuffer commandBuffer) SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDebugMarkerEndEXT); Serialise_vkCmdDebugMarkerEndEXT(ser, commandBuffer); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -4417,7 +4409,7 @@ void WrappedVulkan::vkCmdDebugMarkerInsertEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDebugMarkerInsertEXT); Serialise_vkCmdDebugMarkerInsertEXT(ser, commandBuffer, pMarker); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -4756,7 +4748,7 @@ void WrappedVulkan::vkCmdPushDescriptorSetKHR(VkCommandBuffer commandBuffer, Serialise_vkCmdPushDescriptorSetKHR(ser, commandBuffer, pipelineBindPoint, layout, set, descriptorWriteCount, pDescriptorWrites); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < descriptorWriteCount; i++) { const VkWriteDescriptorSet &write = pDescriptorWrites[i]; @@ -5040,7 +5032,7 @@ void WrappedVulkan::vkCmdPushDescriptorSetWithTemplateKHR( Serialise_vkCmdPushDescriptorSetWithTemplateKHR(ser, commandBuffer, descriptorUpdateTemplate, layout, set, pData); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(descriptorUpdateTemplate), eFrameRef_Read); for(size_t i = 0; i < frameRefs.size(); i++) record->MarkResourceFrameReferenced(frameRefs[i].first, frameRefs[i].second); @@ -5120,7 +5112,7 @@ void WrappedVulkan::vkCmdWriteBufferMarkerAMD(VkCommandBuffer commandBuffer, Serialise_vkCmdWriteBufferMarkerAMD(ser, commandBuffer, pipelineStage, dstBuffer, dstOffset, marker); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(dstBuffer), dstOffset, 4, eFrameRef_PartialWrite); } @@ -5192,7 +5184,7 @@ void WrappedVulkan::vkCmdBeginDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginDebugUtilsLabelEXT); Serialise_vkCmdBeginDebugUtilsLabelEXT(ser, commandBuffer, pLabelInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -5265,7 +5257,7 @@ void WrappedVulkan::vkCmdEndDebugUtilsLabelEXT(VkCommandBuffer commandBuffer) SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndDebugUtilsLabelEXT); Serialise_vkCmdEndDebugUtilsLabelEXT(ser, commandBuffer); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -5335,7 +5327,7 @@ void WrappedVulkan::vkCmdInsertDebugUtilsLabelEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdInsertDebugUtilsLabelEXT); Serialise_vkCmdInsertDebugUtilsLabelEXT(ser, commandBuffer, pLabelInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -5386,7 +5378,7 @@ void WrappedVulkan::vkCmdSetDeviceMask(VkCommandBuffer commandBuffer, uint32_t d SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetDeviceMask); Serialise_vkCmdSetDeviceMask(ser, commandBuffer, deviceMask); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -5476,7 +5468,7 @@ void WrappedVulkan::vkCmdBindTransformFeedbackBuffersEXT(VkCommandBuffer command Serialise_vkCmdBindTransformFeedbackBuffersEXT(ser, commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets, pSizes); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < bindingCount; i++) { VkDeviceSize size = VK_WHOLE_SIZE; @@ -5572,7 +5564,7 @@ void WrappedVulkan::vkCmdBeginTransformFeedbackEXT(VkCommandBuffer commandBuffer Serialise_vkCmdBeginTransformFeedbackEXT(ser, commandBuffer, firstBuffer, bufferCount, pCounterBuffers, pCounterBufferOffsets); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < bufferCount; i++) { if(pCounterBuffers && pCounterBuffers[i] != VK_NULL_HANDLE) @@ -5660,7 +5652,7 @@ void WrappedVulkan::vkCmdEndTransformFeedbackEXT(VkCommandBuffer commandBuffer, Serialise_vkCmdEndTransformFeedbackEXT(ser, commandBuffer, firstBuffer, bufferCount, pCounterBuffers, pCounterBufferOffsets); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < bufferCount; i++) { if(pCounterBuffers && pCounterBuffers[i] != VK_NULL_HANDLE) @@ -5728,7 +5720,7 @@ void WrappedVulkan::vkCmdBeginQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQ SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginQueryIndexedEXT); Serialise_vkCmdBeginQueryIndexedEXT(ser, commandBuffer, queryPool, query, flags, index); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(queryPool), eFrameRef_Read); } } @@ -5786,7 +5778,7 @@ void WrappedVulkan::vkCmdEndQueryIndexedEXT(VkCommandBuffer commandBuffer, VkQue SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndQueryIndexedEXT); Serialise_vkCmdEndQueryIndexedEXT(ser, commandBuffer, queryPool, query, index); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(queryPool), eFrameRef_Read); } } @@ -5857,7 +5849,7 @@ void WrappedVulkan::vkCmdBeginConditionalRenderingEXT( SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBeginConditionalRenderingEXT); Serialise_vkCmdBeginConditionalRenderingEXT(ser, commandBuffer, pConditionalRenderingBegin); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); VkResourceRecord *buf = GetRecord(pConditionalRenderingBegin->buffer); @@ -5918,7 +5910,7 @@ void WrappedVulkan::vkCmdEndConditionalRenderingEXT(VkCommandBuffer commandBuffe SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdEndConditionalRenderingEXT); Serialise_vkCmdEndConditionalRenderingEXT(ser, commandBuffer); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp index 2e2a24ec0..d3d4ca416 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_draw_funcs.cpp @@ -274,7 +274,7 @@ void WrappedVulkan::vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCoun SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDraw); Serialise_vkCmdDraw(ser, commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -376,7 +376,7 @@ void WrappedVulkan::vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t ind Serialise_vkCmdDrawIndexed(ser, commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -792,7 +792,7 @@ void WrappedVulkan::vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer bu SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDrawIndirect); Serialise_vkCmdDrawIndirect(ser, commandBuffer, buffer, offset, count, stride); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); VkDeviceSize size = 0; if(count > 0) @@ -1178,7 +1178,7 @@ void WrappedVulkan::vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBu SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDrawIndexedIndirect); Serialise_vkCmdDrawIndexedIndirect(ser, commandBuffer, buffer, offset, count, stride); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); VkDeviceSize size = 0; if(count > 0) @@ -1262,7 +1262,7 @@ void WrappedVulkan::vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uin SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDispatch); Serialise_vkCmdDispatch(ser, commandBuffer, x, y, z); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1351,7 +1351,7 @@ void WrappedVulkan::vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffe SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdDispatchIndirect); Serialise_vkCmdDispatchIndirect(ser, commandBuffer, buffer, offset); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(buffer), offset, sizeof(VkDispatchIndirectCommand), eFrameRef_Read); @@ -1478,7 +1478,7 @@ void WrappedVulkan::vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcIma Serialise_vkCmdBlitImage(ser, commandBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions, filter); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < regionCount; i++) { @@ -1627,7 +1627,7 @@ void WrappedVulkan::vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage src Serialise_vkCmdResolveImage(ser, commandBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < regionCount; i++) { @@ -1765,7 +1765,7 @@ void WrappedVulkan::vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcIma Serialise_vkCmdCopyImage(ser, commandBuffer, srcImage, srcImageLayout, destImage, destImageLayout, regionCount, pRegions); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < regionCount; i++) { const VkImageCopy ®ion = pRegions[i]; @@ -1888,7 +1888,7 @@ void WrappedVulkan::vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuff Serialise_vkCmdCopyBufferToImage(ser, commandBuffer, srcBuffer, destImage, destImageLayout, regionCount, pRegions); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferImageCopyFrameReferenced(GetRecord(srcBuffer), GetRecord(destImage), regionCount, pRegions, eFrameRef_Read, eFrameRef_CompleteWrite); @@ -2001,7 +2001,7 @@ void WrappedVulkan::vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImag Serialise_vkCmdCopyImageToBuffer(ser, commandBuffer, srcImage, srcImageLayout, destBuffer, regionCount, pRegions); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferImageCopyFrameReferenced(GetRecord(destBuffer), GetRecord(srcImage), regionCount, pRegions, eFrameRef_CompleteWrite, eFrameRef_Read); @@ -2114,7 +2114,7 @@ void WrappedVulkan::vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcB SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdCopyBuffer); Serialise_vkCmdCopyBuffer(ser, commandBuffer, srcBuffer, destBuffer, regionCount, pRegions); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < regionCount; i++) { record->MarkBufferFrameReferenced(GetRecord(srcBuffer), pRegions[i].srcOffset, @@ -2211,7 +2211,7 @@ void WrappedVulkan::vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dest SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdFillBuffer); Serialise_vkCmdFillBuffer(ser, commandBuffer, destBuffer, destOffset, fillSize, data); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(destBuffer), destOffset, fillSize, eFrameRef_CompleteWrite); @@ -2320,7 +2320,7 @@ void WrappedVulkan::vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage Serialise_vkCmdClearColorImage(ser, commandBuffer, image, imageLayout, pColor, rangeCount, pRanges); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetRecord(image)->baseResource, eFrameRef_Read); VkResourceRecord *imageRecord = GetRecord(image); if(imageRecord->resInfo && imageRecord->resInfo->IsSparse()) @@ -2437,7 +2437,7 @@ void WrappedVulkan::vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, V Serialise_vkCmdClearDepthStencilImage(ser, commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(image), eFrameRef_PartialWrite); record->MarkResourceFrameReferenced(GetRecord(image)->baseResource, eFrameRef_Read); VkResourceRecord *imageRecord = GetRecord(image); @@ -2591,7 +2591,7 @@ void WrappedVulkan::vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_ Serialise_vkCmdClearAttachments(ser, commandBuffer, attachmentCount, pAttachments, rectCount, pRects); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); // image/attachments are referenced when the render pass is started and the framebuffer is // bound. @@ -2691,7 +2691,7 @@ void WrappedVulkan::vkCmdDispatchBase(VkCommandBuffer commandBuffer, uint32_t ba Serialise_vkCmdDispatchBase(ser, commandBuffer, baseGroupX, baseGroupY, baseGroupZ, groupCountX, groupCountY, groupCountZ); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -3002,7 +3002,7 @@ void WrappedVulkan::vkCmdDrawIndirectCount(VkCommandBuffer commandBuffer, VkBuff Serialise_vkCmdDrawIndirectCount(ser, commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(buffer), offset, stride * (maxDrawCount - 1) + sizeof(VkDrawIndirectCommand), @@ -3365,7 +3365,7 @@ void WrappedVulkan::vkCmdDrawIndexedIndirectCount(VkCommandBuffer commandBuffer, Serialise_vkCmdDrawIndexedIndirectCount(ser, commandBuffer, buffer, offset, countBuffer, countBufferOffset, maxDrawCount, stride); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(buffer), offset, stride * (maxDrawCount - 1) + sizeof(VkDrawIndirectCommand), @@ -3493,7 +3493,7 @@ void WrappedVulkan::vkCmdDrawIndirectByteCountEXT(VkCommandBuffer commandBuffer, counterBuffer, counterBufferOffset, counterOffset, vertexStride); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkBufferFrameReferenced(GetRecord(counterBuffer), counterBufferOffset, 4, eFrameRef_Read); @@ -3612,7 +3612,7 @@ void WrappedVulkan::vkCmdCopyBuffer2KHR(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdCopyBuffer2KHR); Serialise_vkCmdCopyBuffer2KHR(ser, commandBuffer, pCopyBufferInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < pCopyBufferInfo->regionCount; i++) { @@ -3735,7 +3735,7 @@ void WrappedVulkan::vkCmdCopyImage2KHR(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdCopyImage2KHR); Serialise_vkCmdCopyImage2KHR(ser, commandBuffer, pCopyImageInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < pCopyImageInfo->regionCount; i++) { @@ -3865,7 +3865,7 @@ void WrappedVulkan::vkCmdCopyBufferToImage2KHR(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdCopyBufferToImage2KHR); Serialise_vkCmdCopyBufferToImage2KHR(ser, commandBuffer, pCopyBufferToImageInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); // downcast the VkBufferImageCopy2KHR to VkBufferImageCopy for ease of use, as we don't need // anything in the next chains here @@ -3998,7 +3998,7 @@ void WrappedVulkan::vkCmdCopyImageToBuffer2KHR(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdCopyImageToBuffer2KHR); Serialise_vkCmdCopyImageToBuffer2KHR(ser, commandBuffer, pCopyImageToBufferInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); // downcast the VkBufferImageCopy2KHR to VkBufferImageCopy for ease of use, as we don't need // anything in the next chains here @@ -4133,7 +4133,7 @@ void WrappedVulkan::vkCmdBlitImage2KHR(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdBlitImage2KHR); Serialise_vkCmdBlitImage2KHR(ser, commandBuffer, pBlitImageInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < pBlitImageInfo->regionCount; i++) { @@ -4278,7 +4278,7 @@ void WrappedVulkan::vkCmdResolveImage2KHR(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdResolveImage2KHR); Serialise_vkCmdResolveImage2KHR(ser, commandBuffer, pResolveImageInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < pResolveImageInfo->regionCount; i++) { diff --git a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp index 6b83ad441..c829570f8 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_dynamic_funcs.cpp @@ -89,7 +89,7 @@ void WrappedVulkan::vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t fir SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetViewport); Serialise_vkCmdSetViewport(ser, commandBuffer, firstViewport, viewportCount, pViewports); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -153,7 +153,7 @@ void WrappedVulkan::vkCmdSetViewportWithCountEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetViewportWithCountEXT); Serialise_vkCmdSetViewportWithCountEXT(ser, commandBuffer, viewportCount, pViewports); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -221,7 +221,7 @@ void WrappedVulkan::vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firs SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetScissor); Serialise_vkCmdSetScissor(ser, commandBuffer, firstScissor, scissorCount, pScissors); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -284,7 +284,7 @@ void WrappedVulkan::vkCmdSetScissorWithCountEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetScissorWithCountEXT); Serialise_vkCmdSetScissorWithCountEXT(ser, commandBuffer, scissorCount, pScissors); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -341,7 +341,7 @@ void WrappedVulkan::vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineW SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetLineWidth); Serialise_vkCmdSetLineWidth(ser, commandBuffer, lineWidth); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -408,7 +408,7 @@ void WrappedVulkan::vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depth SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetDepthBias); Serialise_vkCmdSetDepthBias(ser, commandBuffer, depthBias, depthBiasClamp, slopeScaledDepthBias); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -467,7 +467,7 @@ void WrappedVulkan::vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetBlendConstants); Serialise_vkCmdSetBlendConstants(ser, commandBuffer, blendConst); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -529,7 +529,7 @@ void WrappedVulkan::vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float min SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetDepthBounds); Serialise_vkCmdSetDepthBounds(ser, commandBuffer, minDepthBounds, maxDepthBounds); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -595,7 +595,7 @@ void WrappedVulkan::vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetStencilCompareMask); Serialise_vkCmdSetStencilCompareMask(ser, commandBuffer, faceMask, compareMask); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -661,7 +661,7 @@ void WrappedVulkan::vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetStencilWriteMask); Serialise_vkCmdSetStencilWriteMask(ser, commandBuffer, faceMask, writeMask); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -727,7 +727,7 @@ void WrappedVulkan::vkCmdSetStencilReference(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetStencilReference); Serialise_vkCmdSetStencilReference(ser, commandBuffer, faceMask, reference); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -791,7 +791,7 @@ void WrappedVulkan::vkCmdSetSampleLocationsEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetSampleLocationsEXT); Serialise_vkCmdSetSampleLocationsEXT(ser, commandBuffer, pSampleLocationsInfo); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -866,7 +866,7 @@ void WrappedVulkan::vkCmdSetDiscardRectangleEXT(VkCommandBuffer commandBuffer, Serialise_vkCmdSetDiscardRectangleEXT(ser, commandBuffer, firstDiscardRectangle, discardRectangleCount, pDiscardRectangles); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -932,7 +932,7 @@ void WrappedVulkan::vkCmdSetLineStippleEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetLineStippleEXT); Serialise_vkCmdSetLineStippleEXT(ser, commandBuffer, lineStippleFactor, lineStipplePattern); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -990,7 +990,7 @@ void WrappedVulkan::vkCmdSetCullModeEXT(VkCommandBuffer commandBuffer, VkCullMod SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetCullModeEXT); Serialise_vkCmdSetCullModeEXT(ser, commandBuffer, cullMode); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1048,7 +1048,7 @@ void WrappedVulkan::vkCmdSetFrontFaceEXT(VkCommandBuffer commandBuffer, VkFrontF SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetFrontFaceEXT); Serialise_vkCmdSetFrontFaceEXT(ser, commandBuffer, frontFace); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1113,7 +1113,7 @@ void WrappedVulkan::vkCmdSetPrimitiveTopologyEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetPrimitiveTopologyEXT); Serialise_vkCmdSetPrimitiveTopologyEXT(ser, commandBuffer, primitiveTopology); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1173,7 +1173,7 @@ void WrappedVulkan::vkCmdSetDepthTestEnableEXT(VkCommandBuffer commandBuffer, Vk SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetDepthTestEnableEXT); Serialise_vkCmdSetDepthTestEnableEXT(ser, commandBuffer, depthTestEnable); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1234,7 +1234,7 @@ void WrappedVulkan::vkCmdSetDepthWriteEnableEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetDepthWriteEnableEXT); Serialise_vkCmdSetDepthWriteEnableEXT(ser, commandBuffer, depthWriteEnable); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1295,7 +1295,7 @@ void WrappedVulkan::vkCmdSetDepthCompareOpEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetDepthCompareOpEXT); Serialise_vkCmdSetDepthCompareOpEXT(ser, commandBuffer, depthCompareOp); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1357,7 +1357,7 @@ void WrappedVulkan::vkCmdSetDepthBoundsTestEnableEXT(VkCommandBuffer commandBuff SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetDepthBoundsTestEnableEXT); Serialise_vkCmdSetDepthBoundsTestEnableEXT(ser, commandBuffer, depthBoundsTestEnable); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1418,7 +1418,7 @@ void WrappedVulkan::vkCmdSetStencilTestEnableEXT(VkCommandBuffer commandBuffer, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetStencilTestEnableEXT); Serialise_vkCmdSetStencilTestEnableEXT(ser, commandBuffer, stencilTestEnable); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } @@ -1502,7 +1502,7 @@ void WrappedVulkan::vkCmdSetStencilOpEXT(VkCommandBuffer commandBuffer, VkStenci Serialise_vkCmdSetStencilOpEXT(ser, commandBuffer, faceMask, failOp, passOp, depthFailOp, compareOp); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp index 6db3cbe07..9741610fa 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_sync_funcs.cpp @@ -686,7 +686,7 @@ void WrappedVulkan::vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdSetEvent); Serialise_vkCmdSetEvent(ser, commandBuffer, event, stageMask); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(event), eFrameRef_Read); } } @@ -743,7 +743,7 @@ void WrappedVulkan::vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event SCOPED_SERIALISE_CHUNK(VulkanChunk::vkCmdResetEvent); Serialise_vkCmdResetEvent(ser, commandBuffer, event, stageMask); - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); record->MarkResourceFrameReferenced(GetResID(event), eFrameRef_Read); } } @@ -948,7 +948,7 @@ void WrappedVulkan::vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t even imageMemoryBarrierCount, pImageMemoryBarriers); } - record->AddChunk(scope.Get(record->cmdInfo->alloc)); + record->AddChunk(scope.Get(&record->cmdInfo->alloc)); for(uint32_t i = 0; i < eventCount; i++) record->MarkResourceFrameReferenced(GetResID(pEvents[i]), eFrameRef_Read); } diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index a89eaecaf..1b896f0e7 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -1046,21 +1046,116 @@ Chunk *Chunk::Create(Serialiser &ser, uint16_t chunkTyp return ret; } -ChunkAllocator::~ChunkAllocator() +ChunkPagePool::~ChunkPagePool() { - for(Page &p : freePages) + // all allocated pages are in precisely one list, so just free the contents of both lists + for(ChunkPage &p : freePages) { FreeAlignedBuffer(p.chunkBase); FreeAlignedBuffer(p.bufferBase); } - for(Page &p : fullPages) + for(ChunkPage &p : allocatedPages) { FreeAlignedBuffer(p.chunkBase); FreeAlignedBuffer(p.bufferBase); } } +ChunkPage ChunkPagePool::AllocPage() +{ + if(!freePages.empty()) + { + // if there's a free page, move it to the allocated list and return it + ChunkPage free = freePages.back(); + freePages.pop_back(); + allocatedPages.push_back(free); + } + else + { + // otherwise allocate a new one straight into the allocated list + byte *buffers = ::AllocAlignedBuffer(BufferPageSize); + byte *chunks = ::AllocAlignedBuffer(ChunkPageSize); + allocatedPages.push_back({m_ID++, buffers, buffers, chunks, chunks}); + } + + return allocatedPages.back(); +} + +void ChunkPagePool::Trim() +{ + // truly release any currently free pages back to the system + for(ChunkPage &p : freePages) + { + FreeAlignedBuffer(p.chunkBase); + FreeAlignedBuffer(p.bufferBase); + } + + freePages.clear(); +} + +void ChunkPagePool::Reset() +{ + // forcibly move all allocated pages into the free list + freePages.append(allocatedPages); + allocatedPages.clear(); + + for(ChunkPage &p : freePages) + { + // reset head pointers + p.bufferHead = p.bufferBase; + p.chunkHead = p.chunkBase; + + // assign a new ID so these pages can't get reset again by any allocator currently holding them + p.ID = m_ID++; + } +} + +void ChunkPagePool::ResetPageSet(const rdcarray &pages) +{ + // iterate over each page being freed + for(const ChunkPage &p : pages) + { + // try to find it in the allocated page list. This compares by ID, so if the page was already + // freed with a pool reset we won't find it at all because it will have a new ID - that's fine. + int32_t idx = allocatedPages.indexOf(p); + if(idx >= 0) + { + ChunkPage &alloc = allocatedPages[idx]; + // give a new ID to be safe + alloc.ID = m_ID++; + // reset head pointers + alloc.bufferHead = alloc.bufferBase; + alloc.chunkHead = alloc.chunkBase; + // move to free list + freePages.push_back(alloc); + allocatedPages.erase(idx); + continue; + } + } +} + +ChunkAllocator::~ChunkAllocator() +{ + // move any pages we have back to the pool on destruction + Reset(); +} + +void ChunkAllocator::swap(ChunkAllocator &alloc) +{ + if(&m_Pool != &alloc.m_Pool) + { + RDCERR( + "Allocator swap with allocator from another pool! Losing all pages to leak instead of " + "crashing"); + pages.clear(); + alloc.pages.clear(); + return; + } + + pages.swap(alloc.pages); +} + byte *ChunkAllocator::AllocAlignedBuffer(uint64_t size) { // always allocate 64-bytes at a time even if the size is smaller @@ -1073,102 +1168,25 @@ byte *ChunkAllocator::AllocChunk() return AllocateFromPages(true, sizeof(Chunk)); } -void ChunkAllocator::Trim() -{ - for(Page &p : freePages) - { - FreeAlignedBuffer(p.chunkBase); - FreeAlignedBuffer(p.bufferBase); - } - - freePages.clear(); -} - void ChunkAllocator::Reset() { - freePages.append(fullPages); - fullPages.clear(); - - for(Page &p : freePages) - { - p.bufferHead = p.bufferBase; - p.chunkHead = p.chunkBase; - } -} - -void ChunkAllocator::ResetPageSet(const rdcarray &pages) -{ - // any full pages in this set go back into the free pages list - for(size_t i = 0; i < fullPages.size();) - { - Page &p = fullPages[i]; - if(pages.contains(p.ID)) - { - p.bufferHead = p.bufferBase; - p.chunkHead = p.chunkBase; - freePages.push_back(p); - fullPages.erase(i); - continue; - } - i++; - } -} - -rdcarray ChunkAllocator::GetPageSet() -{ - // see if the last free page has been partially used - if(!freePages.empty()) - { - Page &p = freePages.back(); - - if(p.bufferBase != p.bufferHead || p.chunkBase != p.chunkHead) - { - usedPages.push_back(freePages.back().ID); - - fullPages.push_back(freePages.back()); - freePages.pop_back(); - } - } - - rdcarray ret; - ret.swap(usedPages); - return ret; + m_Pool.ResetPageSet(pages); + pages.clear(); } byte *ChunkAllocator::AllocateFromPages(bool chunkAlloc, size_t size) { // if the size can't be satisfied in a page, return NULL and we'll force a full allocation which // will be freed on its own - if(size > BufferPageSize) + if(size > m_Pool.GetBufferPageSize()) return NULL; - while(!freePages.empty()) - { - // if the last free page can satisfy this allocation, stop iterating as we'll use it. - if(GetRemainingBytes(chunkAlloc, freePages.back()) >= size) - break; + // if we don't have a current page, or it can't satisfy the allocation, get a new page from the + // pool + if(pages.empty() || GetRemainingBytes(chunkAlloc, pages.back()) < size) + pages.push_back(m_Pool.AllocPage()); - // otherwise the last page doesn't have enough free, so remove it from the free list - - // mark this page as used in the current set - usedPages.push_back(freePages.back().ID); - - fullPages.push_back(freePages.back()); - freePages.pop_back(); - } - - // if there are no free pages, allocate a new one - if(freePages.empty()) - { - // the first free ID is the sum of the free and full lists, because all pages are in one or the - // other - uint32_t ID = uint32_t(freePages.size() + fullPages.size()); - byte *buffers = ::AllocAlignedBuffer(BufferPageSize); - byte *chunks = ::AllocAlignedBuffer(ChunkPageSize); - freePages.push_back({ID, buffers, buffers, chunks, chunks}); - } - - Page &p = freePages.back(); + ChunkPage &p = pages.back(); byte *ret = NULL; diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index a64bb95d0..5c9af0c17 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -1522,16 +1522,42 @@ DECLARE_STRINGISE_TYPE(SDObject *); class ScopedChunk; -class ChunkAllocator +struct ChunkPage +{ + // compare just with the ID, so that old pages w hich have been reset in the pool don't get reset + // again if an allocator subsequently tries to free them + bool operator==(const ChunkPage &o) { return ID == o.ID; } + size_t ID; + + // we allocate at two granularities, chunks are 16 bytes, buffers are multiples of 64-bytes + // to keep things simple we allocate the chunk memory as 16/64 = a quarter the size of the + // buffer memory. This will waste a bit of memory because we expect buffers to be on average + // larger than 64 bytes. + + // base of the buffer + byte *bufferBase; + // head of the buffer + byte *bufferHead; + + byte *chunkBase; + byte *chunkHead; +}; + +// this is the first level, it allocates whole pages and returns them to allocators for finer +// grained allocation, and those allocators can return whole pages back. This is necessary because +// when fine-grained resetting is allowed we need to associate whole pages with objects and if those +// objects are allocating interleaved we need to immediately associate pages with them. +class ChunkPagePool { public: - ChunkAllocator(size_t PageSize) : BufferPageSize(PageSize), ChunkPageSize(PageSize / 4) {} - ChunkAllocator(const ChunkAllocator &) = delete; - ChunkAllocator(ChunkAllocator &&) = delete; - ChunkAllocator &operator=(const ChunkAllocator &) = delete; - ~ChunkAllocator(); - byte *AllocAlignedBuffer(uint64_t size); - byte *AllocChunk(); + ChunkPagePool(size_t PageSize) : BufferPageSize(PageSize), ChunkPageSize(PageSize / 32) {} + ChunkPagePool(const ChunkPagePool &) = delete; + ChunkPagePool(ChunkPagePool &&) = delete; + ChunkPagePool &operator=(const ChunkPagePool &) = delete; + ~ChunkPagePool(); + + // Allocate a page + ChunkPage AllocPage(); // really free any unused pages void Trim(); @@ -1540,63 +1566,64 @@ public: void Reset(); // reset a page set, other pages will remain in use - void ResetPageSet(const rdcarray &pages); - - // get the pages that have been used since the last reset, or call to GetPageSet. - // these can then be freed later without affecting any other pages. - // note that not all pages will be full (e.g. even if only one 64-bit chunk is used in the last - // page it will be marked as full so it can be freed without another allocation overlapping). - rdcarray GetPageSet(); + void ResetPageSet(const rdcarray &pages); + size_t GetBufferPageSize() { return BufferPageSize; } + size_t GetChunkPageSize() { return ChunkPageSize; } private: size_t BufferPageSize; size_t ChunkPageSize; - struct Page + size_t m_ID = 1; + + // a page is in precisely ONE of these arrays at any time. + // Reset() will move all allocated pages back to free pages and reclaim all that memory + // ResetPageSet() will move any referenced pages from allocatedPages back to freePages + rdcarray freePages; + rdcarray allocatedPages; +}; + +// this is the second level, it should only be used by one object (or a group of objects that are +// always reset together). It pulls pages from the pool and allocates from them, and can then +// release those pages back again with a reset operation. +class ChunkAllocator +{ +public: + ChunkAllocator(ChunkPagePool &pool) : m_Pool(pool) {} + ChunkAllocator(const ChunkAllocator &) = delete; + ChunkAllocator(ChunkAllocator &&) = delete; + ChunkAllocator &operator=(const ChunkAllocator &) = delete; + ~ChunkAllocator(); + + // swap with another chunk allocator - must be from the same pool + void swap(ChunkAllocator &alloc); + + byte *AllocAlignedBuffer(uint64_t size); + byte *AllocChunk(); + + void Reset(); + +private: + ChunkPagePool &m_Pool; + + // as we're recording each new page we start gets added here. The last page is the one we're + // currently allocating from. + rdcarray pages; + + // given a page and the known page size, how much is left + inline size_t GetRemainingBufferBytes(const ChunkPage &p) { - // this is an ID we can use to find this page in a pageset - uint32_t ID; - - // we allocate at two granularities, chunks are 16 bytes, buffers are multiples of 64-bytes - // to keep things simple we allocate the chunk memory as 16/64 = a quarter the size of the - // buffer memory. This will waste a bit of memory because we expect buffers to be on average - // larger than 64 bytes. - - // base of the buffer - byte *bufferBase; - // head of the buffer - byte *bufferHead; - - byte *chunkBase; - byte *chunkHead; - }; - - // a page is in precisely ONE of these arrays at any time, either it's free (and the last free - // page may be partially used) or it's "full". - // Reset() will move all full pages back to free pages and reclaim all that memory - // ResetPageSet() will move any referenced pages from fullPages back to freePages - rdcarray freePages; - rdcarray fullPages; - - // as we're recording each new page we start gets added here. If the user calls GetPageSet we - // return this and the user can then free it later without freeing all pages. - // note, the *current* page (freePages.back) isn't in this list, we only append to this list when - // we retire a full page. That means GetPageSet checks if the last page has been used at all and - // includes it there - rdcarray usedPages; - - inline size_t GetRemainingBufferBytes(const Page &p) - { - return BufferPageSize - (p.bufferHead - p.bufferBase); + return m_Pool.GetBufferPageSize() - (p.bufferHead - p.bufferBase); } - inline size_t GetRemainingChunkBytes(const Page &p) + inline size_t GetRemainingChunkBytes(const ChunkPage &p) { - return ChunkPageSize - (p.chunkHead - p.chunkBase); + return m_Pool.GetChunkPageSize() - (p.chunkHead - p.chunkBase); } - inline size_t GetRemainingBytes(bool chunkAlloc, const Page &p) + inline size_t GetRemainingBytes(bool chunkAlloc, const ChunkPage &p) { return chunkAlloc ? GetRemainingChunkBytes(p) : GetRemainingBufferBytes(p); } + byte *AllocateFromPages(bool chunkAlloc, size_t size); };