From efd2c034304332de73ddc9bee92f9e4976d51f5a Mon Sep 17 00:00:00 2001 From: baldurk Date: Fri, 7 Aug 2020 12:21:05 +0100 Subject: [PATCH] Items in initial contents list don't need to be added as written records * Resources which aren't referenced in the frame don't need initial states unless we have 'Ref All Resources' enabled. These initial states can be stripped on replay as they aren't needed. * We also renamed the WrittenRecords to more explicitly list that this is the list of resources needing initial contents, whether because they were dirty (and so had initial contents) or because they were written mid-frame and so need to be reset. --- renderdoc/core/resource_manager.h | 43 ++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index 94f1e4c44..a2c87df7f 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -1035,10 +1035,13 @@ void ResourceManager::Serialise_InitialContentsNeeded(WriteSerial SCOPED_LOCK(m_Lock); - rdcarray WrittenRecords; + // which resources need initial contents? either those which we didn't have proper initialisation + // for (because they were dirty one way or another) or resources that are written mid-frame and so + // need to be reset. + rdcarray NeededInitials; // reasonable estimate, and these records are small - WrittenRecords.reserve(m_FrameReferencedResources.size() + m_InitialContents.size()); + NeededInitials.reserve(m_FrameReferencedResources.size() + m_InitialContents.size()); // all resources that were recorded as being modified should be included in the list of those // needing initial contents @@ -1049,27 +1052,34 @@ void ResourceManager::Serialise_InitialContentsNeeded(WriteSerial { WrittenRecord wr = {it->first, record ? record->DataInSerialiser : true}; - WrittenRecords.push_back(wr); + NeededInitials.push_back(wr); } } - // any resources that had initial contents generated should also be included + // any resources that had initial contents generated should also be included, even if they're only + // referenced read-only, as anything not in this list will have its initial contents freed on + // replay (see CreateInitialContents). However we only need to keep resources that are referenced + // (unless we have ref all resources on) for(auto it = m_InitialContents.begin(); it != m_InitialContents.end(); ++it) { + bool include = RenderDoc::Inst().GetCaptureOptions().refAllResources; + ResourceId id = it->first; - auto ref = m_FrameReferencedResources.find(id); - if(ref == m_FrameReferencedResources.end() || !IsDirtyFrameRef(ref->second)) + if(m_FrameReferencedResources.find(id) != m_FrameReferencedResources.end()) + include = true; + + if(include) { WrittenRecord wr = {id, true}; - WrittenRecords.push_back(wr); + NeededInitials.push_back(wr); } } - uint64_t chunkSize = uint64_t(WrittenRecords.size() * sizeof(WrittenRecord) + 16); + uint64_t chunkSize = uint64_t(NeededInitials.size() * sizeof(WrittenRecord) + 16); SCOPED_SERIALISE_CHUNK(SystemChunk::InitialContentsList, chunkSize); - SERIALISE_ELEMENT(WrittenRecords); + SERIALISE_ELEMENT(NeededInitials); } template @@ -1276,26 +1286,29 @@ void ResourceManager::CreateInitialContents(ReadSerialiser &ser) { using namespace ResourceManagerInternal; - std::set neededInitials; + std::set ids; - rdcarray WrittenRecords; - SERIALISE_ELEMENT(WrittenRecords); + rdcarray NeededInitials; + SERIALISE_ELEMENT(NeededInitials); - for(const WrittenRecord &wr : WrittenRecords) + for(const WrittenRecord &wr : NeededInitials) { ResourceId id = wr.id; - neededInitials.insert(id); + ids.insert(id); + // if this resource exists and we don't have initial contents for it serialised, create some for + // reset purposes. if(HasLiveResource(id) && m_InitialContents.find(id) == m_InitialContents.end()) Create_InitialState(id, GetLiveResource(id), wr.written); } + // any initial contents that we ended up with which we don't need can be freed now for(auto it = m_InitialContents.begin(); it != m_InitialContents.end();) { ResourceId id = it->first; - if(neededInitials.find(id) == neededInitials.end()) + if(ids.find(id) == ids.end()) { it->second.Free(this); ++it;