Add (slightly hacky) clearing of init contents after capture

* This eliminates most of the leaking on capture - other than this it's
  mostly the leaking serialisation which isn't a huge deal (this could
  be ~900MB-1GB a capture.
This commit is contained in:
baldurk
2015-10-21 13:11:57 +02:00
parent ff26fabc7f
commit 04a2e2ad2a
4 changed files with 30 additions and 13 deletions
-1
View File
@@ -31,7 +31,6 @@ On capture:
* Memory maps are not intercepted, so any modifications are saved by reading back from the mapped pointer, even if it is uncached/write combined.
* Image contents are saved out by copying aliasing their backing memory to a buffer, so will not be GPU-portable.
* Captures will not be GPU-portable where memory indices etc change.
* Memory leaks each time a new capture is created.
* Unsupported or untested features:
* Subpasses
* Nested command buffer execution
+18 -11
View File
@@ -406,6 +406,9 @@ class ResourceManager : public ResourceRecordHandler
// Serialise in which resources need initial contents and set them up.
void CreateInitialContents();
// Free any initial contents that are prepared (for after capture is complete)
void FreeInitialContents();
// Apply the initial contents for the resources that need them, used at the start of a frame
void ApplyInitialContents();
@@ -509,15 +512,8 @@ void ResourceManager<WrappedResourceType, RealResourceType, RecordType>::Shutdow
if(!m_InframeResourceMap.empty())
m_InframeResourceMap.erase(m_InframeResourceMap.begin());
}
while(!m_InitialContents.empty())
{
auto it = m_InitialContents.begin();
ResourceTypeRelease(it->second.resource);
Serialiser::FreeAlignedBuffer(it->second.blob);
if(!m_InitialContents.empty())
m_InitialContents.erase(m_InitialContents.begin());
}
FreeInitialContents();
RDCASSERT(m_ResourceRecords.empty());
}
@@ -762,6 +758,19 @@ void ResourceManager<WrappedResourceType, RealResourceType, RecordType>::Seriali
}
}
template<typename WrappedResourceType, typename RealResourceType, typename RecordType>
void ResourceManager<WrappedResourceType, RealResourceType, RecordType>::FreeInitialContents()
{
while(!m_InitialContents.empty())
{
auto it = m_InitialContents.begin();
ResourceTypeRelease(it->second.resource);
Serialiser::FreeAlignedBuffer(it->second.blob);
if(!m_InitialContents.empty())
m_InitialContents.erase(m_InitialContents.begin());
}
}
template<typename WrappedResourceType, typename RealResourceType, typename RecordType>
void ResourceManager<WrappedResourceType, RealResourceType, RecordType>::CreateInitialContents()
{
@@ -1285,5 +1294,3 @@ ResourceId ResourceManager<WrappedResourceType, RealResourceType, RecordType>::G
RDCASSERT(m_LiveIDs.find(id) != m_LiveIDs.end());
return m_LiveIDs[id];
}
@@ -91,6 +91,9 @@ void WrappedVulkan::vkDestroyCommandBuffer(VkDevice device, VkCmdBuffer obj)
ObjDisp(device)->DestroyCommandBuffer(Unwrap(device), unwrapped);
}
// VKTODOHIGH huge hack, see WrappedVulkan::vkQueuePresentKHR
bool releasingInitContents = false;
bool WrappedVulkan::ReleaseResource(WrappedVkRes *res)
{
if(res == NULL) return true;
@@ -98,7 +101,7 @@ bool WrappedVulkan::ReleaseResource(WrappedVkRes *res)
// VKTODOHIGH: Device-associated resources must be released before the device is
// shutdown. This needs a rethink while writing - really everything should be cleaned
// up explicitly by us or the app.
if(m_State >= WRITING) return true;
if(m_State >= WRITING && !releasingInitContents) return true;
// VKTODOHIGH: release resource with device from resource record
@@ -959,6 +959,14 @@ VkResult WrappedVulkan::vkQueuePresentKHR(
GetResourceManager()->ClearReferencedResources();
// VKTODOHIGH This is a huuuge hack while the shutdown order is all
// messed up and normal calls to WrappedVulkan::ReleaseResource are
// ignored while WRITING to avoid shutdown problems.
extern bool releasingInitContents;
releasingInitContents = true;
GetResourceManager()->FreeInitialContents();
releasingInitContents = false;
GetResourceManager()->FlushPendingDirty();
}
}