diff --git a/renderdoc/core/resource_manager.cpp b/renderdoc/core/resource_manager.cpp index 730c08b2f..558a20f88 100644 --- a/renderdoc/core/resource_manager.cpp +++ b/renderdoc/core/resource_manager.cpp @@ -132,28 +132,6 @@ bool IsDirtyFrameRef(FrameRefType refType) return (refType != eFrameRef_None && refType != eFrameRef_Read); } -bool MarkReferenced(std::map &refs, ResourceId id, FrameRefType refType) -{ - auto refit = refs.find(id); - if(refit == refs.end()) - { - refs[id] = refType; - return true; - } - else - { - refit->second = ComposeFrameRefs(refit->second, refType); - } - return false; -} - -bool ResourceRecord::MarkResourceFrameReferenced(ResourceId id, FrameRefType refType) -{ - if(id == ResourceId()) - return false; - return MarkReferenced(m_FrameRefs, id, refType); -} - void ResourceRecord::AddResourceReferences(ResourceRecordHandler *mgr) { for(auto it = m_FrameRefs.begin(); it != m_FrameRefs.end(); ++it) diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index ecdc48eba..48d6c1261 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -158,7 +158,28 @@ inline InitReqType InitReq(FrameRefType refType) } // handle marking a resource referenced for read or write and storing RAW access etc. -bool MarkReferenced(std::map &refs, ResourceId id, FrameRefType refType); +template +bool MarkReferenced(std::map &refs, ResourceId id, FrameRefType refType, + Compose comp) +{ + auto refit = refs.find(id); + if(refit == refs.end()) + { + refs[id] = refType; + return true; + } + else + { + refit->second = comp(refit->second, refType); + } + return false; +} + +inline bool MarkReferenced(std::map &refs, ResourceId id, + FrameRefType refType) +{ + return MarkReferenced(refs, id, refType, ComposeFrameRefs); +} // verbose prints with IDs of each dirty resource and whether it was prepared, // and whether it was serialised. @@ -353,7 +374,12 @@ struct ResourceRecord bool HasDataPtr() { return DataPtr != NULL; } void SetDataOffset(uint64_t offs) { DataOffset = offs; } void SetDataPtr(byte *ptr) { DataPtr = ptr; } - bool MarkResourceFrameReferenced(ResourceId id, FrameRefType refType); + template + bool MarkResourceFrameReferenced(ResourceId id, FrameRefType refType, Compose comp); + inline bool MarkResourceFrameReferenced(ResourceId id, FrameRefType refType) + { + return MarkResourceFrameReferenced(id, refType, ComposeFrameRefs); + } void AddResourceReferences(ResourceRecordHandler *mgr); void AddReferencedIDs(std::set &ids) { @@ -400,6 +426,14 @@ protected: map m_FrameRefs; }; +template +bool ResourceRecord::MarkResourceFrameReferenced(ResourceId id, FrameRefType refType, Compose comp) +{ + if(id == ResourceId()) + return false; + return MarkReferenced(m_FrameRefs, id, refType, comp); +} + // the resource manager is a utility class that's not required but is likely wanted by any API // implementation. // It keeps track of resource records, which resources are alive and allows you to query for them by @@ -488,6 +522,9 @@ public: // mark resource referenced somewhere in the main frame-affecting calls. // That means this resource should be included in the final serialise out + template + void MarkResourceFrameReferenced(ResourceId id, FrameRefType refType, Compose comp); + inline void MarkResourceFrameReferenced(ResourceId id, FrameRefType refType); /////////////////////////////////////////// @@ -626,14 +663,16 @@ ResourceManager::~ResourceManager() } template -void ResourceManager::MarkResourceFrameReferenced(ResourceId id, FrameRefType refType) +template +void ResourceManager::MarkResourceFrameReferenced(ResourceId id, + FrameRefType refType, Compose comp) { SCOPED_LOCK(m_Lock); if(id == ResourceId()) return; - bool newRef = MarkReferenced(m_FrameReferencedResources, id, refType); + bool newRef = MarkReferenced(m_FrameReferencedResources, id, refType, comp); if(newRef) { @@ -644,6 +683,12 @@ void ResourceManager::MarkResourceFrameReferenced(ResourceId id, } } +template +void ResourceManager::MarkResourceFrameReferenced(ResourceId id, FrameRefType refType) +{ + return MarkResourceFrameReferenced(id, refType, ComposeFrameRefs); +} + template void ResourceManager::MarkDirtyResource(ResourceId res) { diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index 62eec3734..fa8132e96 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -837,10 +837,12 @@ void DescriptorSetSlot::AddBindRefs(VkResourceRecord *record, FrameRefType ref) { if(texelBufferView != VK_NULL_HANDLE) { - record->AddBindFrameRef(GetResID(texelBufferView), eFrameRef_Read, - GetRecord(texelBufferView)->resInfo != NULL); - if(GetRecord(texelBufferView)->baseResource != ResourceId()) - record->AddBindFrameRef(GetRecord(texelBufferView)->baseResource, ref); + VkResourceRecord *bufView = GetRecord(texelBufferView); + record->AddBindFrameRef(bufView->GetResourceID(), eFrameRef_Read, bufView->resInfo != NULL); + if(bufView->baseResource != ResourceId()) + record->AddBindFrameRef(bufView->baseResource, eFrameRef_Read); + if(bufView->baseResourceMem != ResourceId()) + record->AddMemFrameRef(bufView->baseResourceMem, bufView->memOffset, bufView->memSize, ref); } if(imageInfo.imageView != VK_NULL_HANDLE) { @@ -856,9 +858,9 @@ void DescriptorSetSlot::AddBindRefs(VkResourceRecord *record, FrameRefType ref) } if(bufferInfo.buffer != VK_NULL_HANDLE) { - record->AddBindFrameRef(GetResID(bufferInfo.buffer), eFrameRef_Read, - GetRecord(bufferInfo.buffer)->resInfo != NULL); - if(GetRecord(bufferInfo.buffer)->baseResource != ResourceId()) - record->AddBindFrameRef(GetRecord(bufferInfo.buffer)->baseResource, ref); + VkResourceRecord *buf = GetRecord(bufferInfo.buffer); + record->AddBindFrameRef(GetResID(bufferInfo.buffer), eFrameRef_Read, buf->resInfo != NULL); + if(buf->baseResource != ResourceId()) + record->AddMemFrameRef(buf->baseResource, buf->memOffset, buf->memSize, ref); } } diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 2a9895ef0..9065133ca 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -1301,6 +1301,7 @@ void WrappedVulkan::StartFrameCapture(void *dev, void *wnd) m_CapturedFrames.push_back(frame); GetResourceManager()->ClearReferencedResources(); + GetResourceManager()->ClearReferencedMemory(); GetResourceManager()->MarkResourceFrameReferenced(GetResID(m_Instance), eFrameRef_Read); GetResourceManager()->MarkResourceFrameReferenced(GetResID(m_Device), eFrameRef_Read); @@ -1751,6 +1752,8 @@ bool WrappedVulkan::EndFrameCapture(void *dev, void *wnd) GetResourceManager()->MarkUnwrittenResources(); + GetResourceManager()->ClearReferencedMemory(); + GetResourceManager()->ClearReferencedResources(); GetResourceManager()->FreeInitialContents(); diff --git a/renderdoc/driver/vulkan/vk_manager.cpp b/renderdoc/driver/vulkan/vk_manager.cpp index 704c13813..30369fc2b 100644 --- a/renderdoc/driver/vulkan/vk_manager.cpp +++ b/renderdoc/driver/vulkan/vk_manager.cpp @@ -610,7 +610,26 @@ ResourceId VulkanResourceManager::GetFirstIDForHandle(uint64_t handle) void VulkanResourceManager::MarkMemoryFrameReferenced(ResourceId mem, VkDeviceSize offset, VkDeviceSize size, FrameRefType refType) { - MarkResourceFrameReferenced(mem, refType); + FrameRefType maxRef = MarkMemoryReferenced(m_MemFrameRefs, mem, offset, size, refType); + MarkResourceFrameReferenced( + mem, maxRef, [](FrameRefType x, FrameRefType y) -> FrameRefType { return std::max(x, y); }); +} + +void VulkanResourceManager::MergeReferencedMemory(std::map &memRefs) +{ + for(auto j = memRefs.begin(); j != memRefs.end(); j++) + { + auto i = m_MemFrameRefs.find(j->first); + if(i == m_MemFrameRefs.end()) + m_MemFrameRefs.insert(*j); + else + i->second.Merge(j->second); + } +} + +void VulkanResourceManager::ClearReferencedMemory() +{ + m_MemFrameRefs.clear(); } bool VulkanResourceManager::Force_InitialState(WrappedVkRes *res, bool prepare) diff --git a/renderdoc/driver/vulkan/vk_manager.h b/renderdoc/driver/vulkan/vk_manager.h index b5ec9ee3a..81166e107 100644 --- a/renderdoc/driver/vulkan/vk_manager.h +++ b/renderdoc/driver/vulkan/vk_manager.h @@ -413,6 +413,9 @@ public: void MarkMemoryFrameReferenced(ResourceId mem, VkDeviceSize start, VkDeviceSize end, FrameRefType refType); + void MergeReferencedMemory(std::map &memRefs); + void ClearReferencedMemory(); + private: bool ResourceTypeRelease(WrappedVkRes *res); @@ -428,4 +431,5 @@ private: CaptureState m_State; WrappedVulkan *m_Core; + std::map m_MemFrameRefs; }; diff --git a/renderdoc/driver/vulkan/vk_resources.cpp b/renderdoc/driver/vulkan/vk_resources.cpp index 58dcccdda..de965edee 100644 --- a/renderdoc/driver/vulkan/vk_resources.cpp +++ b/renderdoc/driver/vulkan/vk_resources.cpp @@ -3033,7 +3033,11 @@ VkResourceRecord::~VkResourceRecord() void VkResourceRecord::MarkMemoryFrameReferenced(ResourceId mem, VkDeviceSize offset, VkDeviceSize size, FrameRefType refType) { - MarkResourceFrameReferenced(mem, refType); + if(refType != eFrameRef_Read && refType != eFrameRef_None) + cmdInfo->dirtied.insert(mem); + FrameRefType maxRef = MarkMemoryReferenced(cmdInfo->memFrameRefs, mem, offset, size, refType); + MarkResourceFrameReferenced( + mem, maxRef, [](FrameRefType x, FrameRefType y) -> FrameRefType { return std::max(x, y); }); } void VkResourceRecord::MarkBufferFrameReferenced(VkResourceRecord *buf, VkDeviceSize offset, diff --git a/renderdoc/driver/vulkan/vk_resources.h b/renderdoc/driver/vulkan/vk_resources.h index a6c3ebae6..08151d882 100644 --- a/renderdoc/driver/vulkan/vk_resources.h +++ b/renderdoc/driver/vulkan/vk_resources.h @@ -25,6 +25,7 @@ #pragma once #include "common/wrapped_pool.h" +#include "core/intervals.h" #include "core/resource_manager.h" #include "vk_common.h" #include "vk_hookset_defs.h" @@ -906,6 +907,8 @@ struct ResourceInfo void Update(uint32_t numBindings, const VkSparseImageMemoryBind *pBindings); }; +struct MemRefs; + struct CmdBufferRecordingInfo { VkDevice device; @@ -930,6 +933,8 @@ struct CmdBufferRecordingInfo vector subcmds; + std::map memFrameRefs; + // AdvanceFrame/Present should be called after this buffer is submitted bool present; }; @@ -959,6 +964,7 @@ struct DescriptorSetData // mapping information static const uint32_t SPARSE_REF_BIT = 0x80000000; map > bindFrameRefs; + map bindMemRefs; }; struct PipelineLayoutData @@ -997,6 +1003,77 @@ struct AttachmentInfo VkImageMemoryBarrier barrier; }; +struct MemRefs +{ + Intervals rangeRefs; + inline MemRefs() {} + inline MemRefs(VkDeviceSize offset, VkDeviceSize size, FrameRefType refType) + { + rangeRefs.update(offset, offset + size, refType, ComposeFrameRefs); + } + template + FrameRefType Update(VkDeviceSize offset, VkDeviceSize size, FrameRefType refType, Compose comp); + inline FrameRefType Update(VkDeviceSize offset, VkDeviceSize size, FrameRefType refType) + { + return Update(offset, size, refType, ComposeFrameRefs); + } + template + FrameRefType Merge(MemRefs &other, Compose comp); + inline FrameRefType Merge(MemRefs &other) { return Merge(other, ComposeFrameRefs); } +}; + +template +FrameRefType MemRefs::Update(VkDeviceSize offset, VkDeviceSize size, FrameRefType refType, + Compose comp) +{ + FrameRefType maxRefType = eFrameRef_None; + rangeRefs.update(offset, offset + size, refType, + [&maxRefType, comp](FrameRefType oldRef, FrameRefType newRef) -> FrameRefType { + FrameRefType ref = comp(oldRef, newRef); + maxRefType = std::max(maxRefType, ref); + return ref; + }); + return maxRefType; +} + +template +FrameRefType MemRefs::Merge(MemRefs &other, Compose comp) +{ + FrameRefType maxRefType = eFrameRef_None; + rangeRefs.merge(other.rangeRefs, + [&maxRefType, comp](FrameRefType oldRef, FrameRefType newRef) -> FrameRefType { + FrameRefType ref = comp(oldRef, newRef); + maxRefType = std::max(maxRefType, ref); + return ref; + }); + return maxRefType; +} + +template +FrameRefType MarkMemoryReferenced(std::map &memRefs, ResourceId mem, + VkDeviceSize offset, VkDeviceSize size, FrameRefType refType, + Compose comp) +{ + if(refType == eFrameRef_None) + return refType; + auto refs = memRefs.find(mem); + if(refs == memRefs.end()) + { + memRefs.insert(std::make_pair(mem, MemRefs(offset, size, refType))); + return refType; + } + else + { + return refs->second.Update(offset, size, refType, comp); + } +} + +inline FrameRefType MarkMemoryReferenced(std::map &memRefs, ResourceId mem, + VkDeviceSize offset, VkDeviceSize size, FrameRefType refType) +{ + return MarkMemoryReferenced(memRefs, mem, offset, size, refType, ComposeFrameRefs); +} + struct DescUpdateTemplate; struct VkResourceRecord : public ResourceRecord @@ -1030,6 +1107,7 @@ public: cmdInfo->imgbarriers.swap(bakedCommands->cmdInfo->imgbarriers); cmdInfo->subcmds.swap(bakedCommands->cmdInfo->subcmds); cmdInfo->sparse.swap(bakedCommands->cmdInfo->sparse); + cmdInfo->memFrameRefs.swap(bakedCommands->cmdInfo->memFrameRefs); } void AddBindFrameRef(ResourceId id, FrameRefType ref, bool hasSparse = false) @@ -1054,6 +1132,29 @@ public: } } + void AddMemFrameRef(ResourceId mem, VkDeviceSize offset, VkDeviceSize size, FrameRefType refType) + { + if(mem == ResourceId()) + { + RDCERR("Unexpected NULL resource ID being added as a bind frame ref"); + return; + } + pair &p = descInfo->bindFrameRefs[mem]; + if((p.first & ~DescriptorSetData::SPARSE_REF_BIT) == 0) + { + descInfo->bindMemRefs.erase(mem); + p.first = 1; + p.second = eFrameRef_None; + } + else + { + p.first++; + } + FrameRefType maxRef = MarkMemoryReferenced(descInfo->bindMemRefs, mem, offset, size, refType, + ComposeFrameRefsUnordered); + p.second = std::max(p.second, maxRef); + } + void RemoveBindFrameRef(ResourceId id) { // ignore any NULL IDs - probably an object that was diff --git a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp index 9f14328c0..6b235a1f3 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_queue_funcs.cpp @@ -857,6 +857,7 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, GetResourceManager()->MarkSparseMapReferenced(sparserecord->resInfo); } } + GetResourceManager()->MergeReferencedMemory(setrecord->descInfo->bindMemRefs); } for(auto it = record->bakedCommands->cmdInfo->sparse.begin(); @@ -867,6 +868,8 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, record->bakedCommands->AddResourceReferences(GetResourceManager()); record->bakedCommands->AddReferencedIDs(refdIDs); + GetResourceManager()->MergeReferencedMemory(record->bakedCommands->cmdInfo->memFrameRefs); + // ref the parent command buffer's alloc record, this will pull in the cmd buffer pool GetResourceManager()->MarkResourceFrameReferenced( record->cmdInfo->allocRecord->GetResourceID(), eFrameRef_Read); @@ -876,6 +879,8 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount, record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddResourceReferences( GetResourceManager()); record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->AddReferencedIDs(refdIDs); + GetResourceManager()->MergeReferencedMemory( + record->bakedCommands->cmdInfo->subcmds[sub]->bakedCommands->cmdInfo->memFrameRefs); GetResourceManager()->MarkResourceFrameReferenced( record->bakedCommands->cmdInfo->subcmds[sub]->cmdInfo->allocRecord->GetResourceID(), eFrameRef_Read);