diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index fc789c300..7fb416a32 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -327,6 +327,7 @@ class ResourceManager : public ResourceRecordHandler InitialContentData GetInitialContents(ResourceId id); void SetInitialContents(ResourceId id, InitialContentData contents); + void SetInitialChunk(ResourceId id, Chunk *chunk); // generate chunks for initial contents and insert. void InsertInitialContentsChunks(Serialiser *fileSer); @@ -418,6 +419,9 @@ class ResourceManager : public ResourceRecordHandler // used during capture or replay - holds initial contents map m_InitialContents; + // on capture, if a chunk was prepared in Prepare_InitialContents and added, don't re-serialise. + // Some initial contents may not need the delayed readback. + map m_InitialChunks; // used during capture or replay - map of resources currently alive with their real IDs, used in capture and replay. map m_CurrentResourceMap; @@ -471,7 +475,7 @@ void ResourceManager::Shutdown() { auto it = m_InitialContents.begin(); ResourceTypeRelease(it->second.resource); - SAFE_DELETE_ARRAY(it->second.blob); + Serialiser::FreeAlignedBuffer(it->second.blob); if(!m_InitialContents.empty()) m_InitialContents.erase(m_InitialContents.begin()); } @@ -626,13 +630,34 @@ void ResourceManager::SetInitialContents(ResourceId id if(it != m_InitialContents.end()) { ResourceTypeRelease(it->second.resource); - SAFE_DELETE_ARRAY(it->second.blob); + Serialiser::FreeAlignedBuffer(it->second.blob); m_InitialContents.erase(it); } m_InitialContents[id] = contents; } +template +void ResourceManager::SetInitialChunk(ResourceId id, Chunk *chunk) +{ + SCOPED_LOCK(m_Lock); + + RDCASSERT(id != ResourceId()); + + auto it = m_InitialChunks.find(id); + + RDCASSERT(chunk->GetChunkType() == INITIAL_CONTENTS); + + if(it != m_InitialChunks.end()) + { + RDCERR("Initial chunk set for ID %llu twice", id); + delete chunk; + return; + } + + m_InitialChunks[id] = chunk; +} + template typename ResourceManager::InitialContentData ResourceManager::GetInitialContents(ResourceId id) { @@ -721,7 +746,7 @@ void ResourceManager::CreateInitialContents() if(neededInitials.find(id) == neededInitials.end()) { ResourceTypeRelease(it->second.resource); - SAFE_DELETE_ARRAY(it->second.blob); + Serialiser::FreeAlignedBuffer(it->second.blob); ++it; m_InitialContents.erase(id); } @@ -865,11 +890,20 @@ void ResourceManager::InsertInitialContentsChunks(Seri continue; } - ScopedContext scope(m_pSerialiser, NULL, "Initial Contents", "Initial Contents", INITIAL_CONTENTS, false); + auto preparedChunk = m_InitialChunks.find(id); + if(preparedChunk != m_InitialChunks.end()) + { + fileSerialiser->Insert(preparedChunk->second); + m_InitialChunks.erase(preparedChunk); + } + else + { + ScopedContext scope(m_pSerialiser, NULL, "Initial Contents", "Initial Contents", INITIAL_CONTENTS, false); - Serialise_InitialState(res); + Serialise_InitialState(res); - fileSerialiser->Insert(scope.Get(true)); + fileSerialiser->Insert(scope.Get(true)); + } } for(auto it=m_CurrentResourceMap.begin(); it != m_CurrentResourceMap.end(); ++it) @@ -878,13 +912,29 @@ void ResourceManager::InsertInitialContentsChunks(Seri if(Force_InitialState(it->second)) { - ScopedContext scope(m_pSerialiser, NULL, "Initial Contents", "Initial Contents", INITIAL_CONTENTS, false); + auto preparedChunk = m_InitialChunks.find(it->first); + if(preparedChunk != m_InitialChunks.end()) + { + fileSerialiser->Insert(preparedChunk->second); + m_InitialChunks.erase(preparedChunk); + } + else + { + ScopedContext scope(m_pSerialiser, NULL, "Initial Contents", "Initial Contents", INITIAL_CONTENTS, false); - Serialise_InitialState(it->second); + Serialise_InitialState(it->second); - fileSerialiser->Insert(scope.Get(true)); + fileSerialiser->Insert(scope.Get(true)); + } } } + + // delete/cleanup any chunks that weren't used (maybe the resource was not + // referenced). + for(auto it=m_InitialChunks.begin(); it != m_InitialChunks.end(); ++it) + delete it->second; + + m_InitialChunks.clear(); } template diff --git a/renderdoc/driver/gl/gl_manager.cpp b/renderdoc/driver/gl/gl_manager.cpp index 70c0496c3..4ffb4c53f 100644 --- a/renderdoc/driver/gl/gl_manager.cpp +++ b/renderdoc/driver/gl/gl_manager.cpp @@ -148,7 +148,7 @@ bool GLResourceManager::Prepare_InitialState(GLResource res) gl.glBindVertexArray(res.name); - VertexArrayInitialData *data = (VertexArrayInitialData *)new byte[sizeof(VertexArrayInitialData)*16]; + VertexArrayInitialData *data = (VertexArrayInitialData *)Serialiser::AllocAlignedBuffer(sizeof(VertexArrayInitialData)*16); for(GLuint i=0; i < 16; i++) { @@ -565,7 +565,7 @@ bool GLResourceManager::Serialise_InitialState(GLResource res) if(m_State < WRITING) { - byte *blob = new byte[sizeof(data)]; + byte *blob = Serialiser::AllocAlignedBuffer(sizeof(data)); memcpy(blob, data, sizeof(data)); SetInitialContents(Id, InitialContentData(GLResource(MakeNullResource), 0, blob)); diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index c03008bcd..1396bd58c 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -367,6 +367,8 @@ byte *Serialiser::AllocAlignedBuffer(size_t size) void Serialiser::FreeAlignedBuffer(byte *buf) { + if(buf == NULL) return; + byte **realPointer = (byte **)buf; byte *rawAlloc = realPointer[-1];