diff --git a/renderdoc/driver/d3d11/d3d11_device.cpp b/renderdoc/driver/d3d11/d3d11_device.cpp index 5c438d941..bbf050211 100644 --- a/renderdoc/driver/d3d11/d3d11_device.cpp +++ b/renderdoc/driver/d3d11/d3d11_device.cpp @@ -1001,8 +1001,7 @@ void WrappedID3D11Device::Serialise_CaptureScope(uint64_t offset) void WrappedID3D11Device::ReadLogInitialisation() { - uint64_t lastFrame = 0; - uint64_t firstFrame = 0; + uint64_t frameOffset = 0; LazyInit(); @@ -1010,28 +1009,6 @@ void WrappedID3D11Device::ReadLogInitialisation() m_pSerialiser->Rewind(); - uint32_t captureChunkIdx = 0; - - while(!m_pSerialiser->AtEnd()) - { - m_pSerialiser->SkipToChunk(CAPTURE_SCOPE, &captureChunkIdx); - - // found a capture chunk - if(!m_pSerialiser->AtEnd()) - { - lastFrame = m_pSerialiser->GetOffset(); - if(firstFrame == 0) - firstFrame = m_pSerialiser->GetOffset(); - - // skip this chunk - m_pSerialiser->PushContext(NULL, CAPTURE_SCOPE, false); - m_pSerialiser->SkipCurrentChunk(); - m_pSerialiser->PopContext(NULL, CAPTURE_SCOPE); - } - } - - m_pSerialiser->Rewind(); - int chunkIdx = 0; struct chunkinfo @@ -1053,6 +1030,12 @@ void WrappedID3D11Device::ReadLogInitialisation() uint64_t offset = m_pSerialiser->GetOffset(); D3D11ChunkType context = (D3D11ChunkType)m_pSerialiser->PushContext(NULL, 1, false); + + if(context == CAPTURE_SCOPE) + { + // immediately read rest of log into memory + m_pSerialiser->SetPersistentBlock(offset); + } chunkIdx++; @@ -1060,10 +1043,12 @@ void WrappedID3D11Device::ReadLogInitialisation() m_pSerialiser->PopContext(NULL, context); - RenderDoc::Inst().SetProgress(FileInitialRead, float(chunkIdx)/float(captureChunkIdx)); + RenderDoc::Inst().SetProgress(FileInitialRead, float(offset)/float(m_pSerialiser->GetSize())); if(context == CAPTURE_SCOPE) { + frameOffset = offset; + GetResourceManager()->ApplyInitialContents(); m_pImmediateContext->ReplayLog(READING, 0, 0, false); @@ -1076,15 +1061,10 @@ void WrappedID3D11Device::ReadLogInitialisation() chunkInfos[context].count++; if(context == CAPTURE_SCOPE) - { - if(m_pSerialiser->GetOffset() > lastFrame) - break; - } + break; if(m_pSerialiser->AtEnd()) - { break; - } } for(auto it=chunkInfos.begin(); it != chunkInfos.end(); ++it) @@ -1100,11 +1080,9 @@ void WrappedID3D11Device::ReadLogInitialisation() ); } - RDCDEBUG("Allocating %llu persistant bytes of memory for the log.", m_pSerialiser->GetSize() - firstFrame); + RDCDEBUG("Allocating %llu persistant bytes of memory for the log.", m_pSerialiser->GetSize() - frameOffset); m_pSerialiser->SetDebugText(false); - - m_pSerialiser->SetPersistentBlock(firstFrame); } bool WrappedID3D11Device::Prepare_InitialState(ID3D11DeviceChild *res) diff --git a/renderdoc/driver/gl/gl_driver.cpp b/renderdoc/driver/gl/gl_driver.cpp index a5f6013ac..dc8625418 100644 --- a/renderdoc/driver/gl/gl_driver.cpp +++ b/renderdoc/driver/gl/gl_driver.cpp @@ -2850,35 +2850,12 @@ void WrappedOpenGL::DebugSnoop(GLenum source, GLenum type, GLuint id, GLenum sev void WrappedOpenGL::ReadLogInitialisation() { - uint64_t lastFrame = 0; - uint64_t firstFrame = 0; + uint64_t frameOffset = 0; m_pSerialiser->SetDebugText(true); m_pSerialiser->Rewind(); - uint32_t captureChunkIdx = 0; - - while(!m_pSerialiser->AtEnd()) - { - m_pSerialiser->SkipToChunk(CAPTURE_SCOPE, &captureChunkIdx); - - // found a capture chunk - if(!m_pSerialiser->AtEnd()) - { - lastFrame = m_pSerialiser->GetOffset(); - if(firstFrame == 0) - firstFrame = m_pSerialiser->GetOffset(); - - // skip this chunk - m_pSerialiser->PushContext(NULL, CAPTURE_SCOPE, false); - m_pSerialiser->SkipCurrentChunk(); - m_pSerialiser->PopContext(NULL, CAPTURE_SCOPE); - } - } - - m_pSerialiser->Rewind(); - int chunkIdx = 0; struct chunkinfo @@ -2900,6 +2877,12 @@ void WrappedOpenGL::ReadLogInitialisation() uint64_t offset = m_pSerialiser->GetOffset(); GLChunkType context = (GLChunkType)m_pSerialiser->PushContext(NULL, 1, false); + + if(context == CAPTURE_SCOPE) + { + // immediately read rest of log into memory + m_pSerialiser->SetPersistentBlock(offset); + } chunkIdx++; @@ -2907,10 +2890,12 @@ void WrappedOpenGL::ReadLogInitialisation() m_pSerialiser->PopContext(NULL, context); - RenderDoc::Inst().SetProgress(FileInitialRead, float(chunkIdx)/float(captureChunkIdx)); + RenderDoc::Inst().SetProgress(FileInitialRead, float(offset)/float(m_pSerialiser->GetSize())); if(context == CAPTURE_SCOPE) { + frameOffset = offset; + GetResourceManager()->ApplyInitialContents(); ContextReplayLog(READING, 0, 0, false); @@ -2923,15 +2908,10 @@ void WrappedOpenGL::ReadLogInitialisation() chunkInfos[context].count++; if(context == CAPTURE_SCOPE) - { - if(m_pSerialiser->GetOffset() > lastFrame) - break; - } + break; if(m_pSerialiser->AtEnd()) - { break; - } } for(auto it=chunkInfos.begin(); it != chunkInfos.end(); ++it) @@ -2947,11 +2927,9 @@ void WrappedOpenGL::ReadLogInitialisation() ); } - RDCDEBUG("Allocating %llu persistant bytes of memory for the log.", m_pSerialiser->GetSize() - firstFrame); + RDCDEBUG("Allocating %llu persistant bytes of memory for the log.", m_pSerialiser->GetSize() - frameOffset); m_pSerialiser->SetDebugText(false); - - m_pSerialiser->SetPersistentBlock(firstFrame); } void WrappedOpenGL::ProcessChunk(uint64_t offset, GLChunkType context) diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index 2b86260a9..9904662ee 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -1116,37 +1116,50 @@ void Serialiser::FreeAlignedBuffer(byte *buf) void Serialiser::SetPersistentBlock(uint64_t offs) { + // as long as this is called immediately after pushing the chunk context at the + // offset, we will always have the start in memory, as we keep 64 bytes of + // a backwards window even if we had to shift the currently in-memory bytes + // while reading the chunk header + RDCASSERT(m_ReadOffset <= offs); + + // also can't persistent block ahead of where we are + RDCASSERT(offs < (m_BufferHead - m_Buffer) + m_ReadOffset); + + // ensure sane offset + RDCASSERT(offs < m_BufferSize); + + size_t persistentSize = (size_t)(m_BufferSize - offs); + + // allocate our persistent buffer + byte *newBuf = AllocAlignedBuffer(persistentSize); + + // save where buffer head was as file-offset + uint64_t prevOffs = uint64_t(m_BufferHead - m_Buffer) + m_ReadOffset; + + // find the range of the persistent block that we have in memory + byte *persistentBase = m_Buffer + (offs - m_ReadOffset); + size_t persistentInMemory = RDCMIN(persistentSize, size_t(m_CurrentBufferSize - (offs - m_ReadOffset))); + + memcpy(newBuf, persistentBase, persistentInMemory); + FreeAlignedBuffer(m_Buffer); - - RDCASSERT(m_BufferSize - offs < 0xffffffff); - - m_CurrentBufferSize = (size_t)(m_BufferSize - offs); - m_BufferHead = m_Buffer = AllocAlignedBuffer(m_CurrentBufferSize); + + m_CurrentBufferSize = persistentSize; + m_Buffer = newBuf; m_ReadOffset = offs; + // set the head back to where it was + m_BufferHead = m_Buffer + (prevOffs - offs); + + // if we didn't read everything, read the rest + if(persistentInMemory < persistentSize) + { + ReadFromFile(persistentInMemory, persistentSize - persistentInMemory); + } + RDCASSERT(m_ReadFileHandle); - Section *s = m_KnownSections[eSectionType_FrameCapture]; - RDCASSERT(s); - FileIO::fseek64(m_ReadFileHandle, s->fileoffset, SEEK_SET); - - if(s->flags & eSectionFlag_LZ4Compressed) - { - RDCASSERT(s->compressedReader); - s->compressedReader->Reset(); - } - - // can't seek arbitrarily in the stream, need to read through the rest - while(offs > 0) - { - // read at most buffer size at a time. - size_t chunkSize = RDCMIN(m_CurrentBufferSize, (size_t)offs); - ReadFromFile(0, chunkSize); - offs -= chunkSize; - } - - // now read the rest - ReadFromFile(0, m_CurrentBufferSize); + // close the file handle FileIO::fclose(m_ReadFileHandle); m_ReadFileHandle = 0; }