From ca2307e34c86a70a7df041611d48430dd10b3482 Mon Sep 17 00:00:00 2001 From: Alex Vakulenko Date: Mon, 6 May 2019 10:06:29 -0700 Subject: [PATCH] Make it possible to write chunks larger than 4 GB Added a special chunk flag indicating that chunk size is a 64 bit value. This allows to handle larger chunks (which heppens quite rarely) while still maintaining backward compatibility with the majority of traces. Bumped RDC file version of 0x101 (1.1) to make sure older version cannot read the new file format. --- renderdoc/api/replay/structured_data.h | 2 +- renderdoc/core/resource_manager.h | 8 ++-- renderdoc/driver/d3d11/d3d11_device.h | 2 +- renderdoc/driver/d3d11/d3d11_initstate.cpp | 12 ++--- renderdoc/driver/d3d11/d3d11_manager.cpp | 2 +- renderdoc/driver/d3d11/d3d11_manager.h | 2 +- renderdoc/driver/d3d12/d3d12_initstate.cpp | 7 ++- renderdoc/driver/d3d12/d3d12_manager.h | 2 +- renderdoc/driver/d3d8/d3d8_manager.cpp | 2 +- renderdoc/driver/d3d8/d3d8_manager.h | 2 +- renderdoc/driver/gl/gl_initstate.cpp | 11 ++--- renderdoc/driver/gl/gl_manager.h | 2 +- renderdoc/driver/vulkan/vk_core.cpp | 4 +- renderdoc/driver/vulkan/vk_core.h | 6 +-- renderdoc/driver/vulkan/vk_initstate.cpp | 4 +- renderdoc/driver/vulkan/vk_manager.cpp | 2 +- renderdoc/driver/vulkan/vk_manager.h | 2 +- .../driver/vulkan/vk_sparse_initstate.cpp | 10 ++-- renderdoc/serialise/rdcfile.cpp | 2 +- renderdoc/serialise/rdcfile.h | 3 +- renderdoc/serialise/serialiser.cpp | 46 ++++++++++++++----- renderdoc/serialise/serialiser.h | 7 +-- 22 files changed, 81 insertions(+), 59 deletions(-) diff --git a/renderdoc/api/replay/structured_data.h b/renderdoc/api/replay/structured_data.h index 148d23889..b0e4c8234 100644 --- a/renderdoc/api/replay/structured_data.h +++ b/renderdoc/api/replay/structured_data.h @@ -238,7 +238,7 @@ struct SDChunkMetaData DOCUMENT(R"(The length in bytes of this chunk - may be longer than the actual sum of the data if a conservative size estimate was used on creation to avoid seeking to fix-up the stored length. )"); - uint32_t length = 0; + uint64_t length = 0; DOCUMENT("The ID of the thread where this chunk was recorded."); uint64_t threadID = 0; diff --git a/renderdoc/core/resource_manager.h b/renderdoc/core/resource_manager.h index bc166e30e..9f1d3e4d3 100644 --- a/renderdoc/core/resource_manager.h +++ b/renderdoc/core/resource_manager.h @@ -573,7 +573,7 @@ protected: virtual bool AllowDeletedResource_InitialState() { return false; } virtual bool Need_InitialStateChunk(WrappedResourceType res) = 0; virtual bool Prepare_InitialState(WrappedResourceType res) = 0; - virtual uint32_t GetSize_InitialState(ResourceId id, WrappedResourceType res) = 0; + virtual uint64_t GetSize_InitialState(ResourceId id, WrappedResourceType res) = 0; virtual bool Serialise_InitialState(WriteSerialiser &ser, ResourceId id, WrappedResourceType res) = 0; virtual void Create_InitialState(ResourceId id, WrappedResourceType live, bool hasData) = 0; @@ -856,7 +856,7 @@ void ResourceManager::Serialise_InitialContentsNeeded(WriteSerial } } - uint32_t chunkSize = uint32_t(WrittenRecords.size() * sizeof(WrittenRecord) + 16); + uint64_t chunkSize = uint64_t(WrittenRecords.size() * sizeof(WrittenRecord) + 16); SCOPED_SERIALISE_CHUNK(SystemChunk::InitialContentsList, chunkSize); SERIALISE_ELEMENT(WrittenRecords); @@ -1146,7 +1146,7 @@ void ResourceManager::InsertInitialContentsChunks(WriteSerialiser } else { - uint32_t size = GetSize_InitialState(id, res); + uint64_t size = GetSize_InitialState(id, res); SCOPED_SERIALISE_CHUNK(SystemChunk::InitialContents, size); @@ -1175,7 +1175,7 @@ void ResourceManager::InsertInitialContentsChunks(WriteSerialiser } else { - uint32_t size = GetSize_InitialState(it->first, it->second); + uint64_t size = GetSize_InitialState(it->first, it->second); SCOPED_SERIALISE_CHUNK(SystemChunk::InitialContents, size); diff --git a/renderdoc/driver/d3d11/d3d11_device.h b/renderdoc/driver/d3d11/d3d11_device.h index 129096a90..dbb666989 100644 --- a/renderdoc/driver/d3d11/d3d11_device.h +++ b/renderdoc/driver/d3d11/d3d11_device.h @@ -494,7 +494,7 @@ public: // log replaying bool Prepare_InitialState(ID3D11DeviceChild *res); - uint32_t GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res); + uint64_t GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res); template bool Serialise_InitialState(SerialiserType &ser, ResourceId resid, ID3D11DeviceChild *res); diff --git a/renderdoc/driver/d3d11/d3d11_initstate.cpp b/renderdoc/driver/d3d11/d3d11_initstate.cpp index 3056f3a36..170a4b562 100644 --- a/renderdoc/driver/d3d11/d3d11_initstate.cpp +++ b/renderdoc/driver/d3d11/d3d11_initstate.cpp @@ -257,13 +257,13 @@ bool WrappedID3D11Device::Prepare_InitialState(ID3D11DeviceChild *res) return true; } -uint32_t WrappedID3D11Device::GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res) +uint64_t WrappedID3D11Device::GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res) { // This function provides an upper bound on how much data Serialise_InitialState will write, so // that the chunk can be pre-allocated and not require seeking to fix-up the length. // It can be an over-estimate as long as it's not *too* far over. - uint32_t ret = 128; // type, Id, plus breathing room + uint64_t ret = 128; // type, Id, plus breathing room ResourcePitch pitch = {}; @@ -283,7 +283,7 @@ uint32_t WrappedID3D11Device::GetSize_InitialState(ResourceId id, ID3D11DeviceCh // buffer width plus alignment ret += desc.ByteWidth; - ret += (uint32_t)WriteSerialiser::GetChunkAlignment(); + ret += WriteSerialiser::GetChunkAlignment(); } else if(type == Resource_Texture1D) { @@ -304,7 +304,7 @@ uint32_t WrappedID3D11Device::GetSize_InitialState(ResourceId id, ID3D11DeviceCh const UINT RowPitch = GetRowPitch(desc.Width, desc.Format, mip); ret += RowPitch; - ret += (uint32_t)WriteSerialiser::GetChunkAlignment(); + ret += WriteSerialiser::GetChunkAlignment(); } } else if(type == Resource_Texture2D) @@ -344,7 +344,7 @@ uint32_t WrappedID3D11Device::GetSize_InitialState(ResourceId id, ID3D11DeviceCh ret += pitch.m_RowPitch * numRows; } - ret += (uint32_t)WriteSerialiser::GetChunkAlignment(); + ret += WriteSerialiser::GetChunkAlignment(); } } } @@ -373,7 +373,7 @@ uint32_t WrappedID3D11Device::GetSize_InitialState(ResourceId id, ID3D11DeviceCh ret += pitch.m_DepthPitch * RDCMAX(1U, desc.Depth >> mip); } - ret += (uint32_t)WriteSerialiser::GetChunkAlignment(); + ret += WriteSerialiser::GetChunkAlignment(); } } else diff --git a/renderdoc/driver/d3d11/d3d11_manager.cpp b/renderdoc/driver/d3d11/d3d11_manager.cpp index 3d27c65df..b3d591504 100644 --- a/renderdoc/driver/d3d11/d3d11_manager.cpp +++ b/renderdoc/driver/d3d11/d3d11_manager.cpp @@ -87,7 +87,7 @@ bool D3D11ResourceManager::Prepare_InitialState(ID3D11DeviceChild *res) return m_Device->Prepare_InitialState(res); } -uint32_t D3D11ResourceManager::GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res) +uint64_t D3D11ResourceManager::GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res) { return m_Device->GetSize_InitialState(id, res); } diff --git a/renderdoc/driver/d3d11/d3d11_manager.h b/renderdoc/driver/d3d11/d3d11_manager.h index 7000422ed..dabe6803a 100644 --- a/renderdoc/driver/d3d11/d3d11_manager.h +++ b/renderdoc/driver/d3d11/d3d11_manager.h @@ -262,7 +262,7 @@ private: bool Force_InitialState(ID3D11DeviceChild *res, bool prepare); bool Need_InitialStateChunk(ID3D11DeviceChild *res); bool Prepare_InitialState(ID3D11DeviceChild *res); - uint32_t GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res); + uint64_t GetSize_InitialState(ResourceId id, ID3D11DeviceChild *res); bool Serialise_InitialState(WriteSerialiser &ser, ResourceId resid, ID3D11DeviceChild *res); void Create_InitialState(ResourceId id, ID3D11DeviceChild *live, bool hasData); void Apply_InitialState(ID3D11DeviceChild *live, D3D11InitialContents data); diff --git a/renderdoc/driver/d3d12/d3d12_initstate.cpp b/renderdoc/driver/d3d12/d3d12_initstate.cpp index 84e369a6c..35cdc7a45 100644 --- a/renderdoc/driver/d3d12/d3d12_initstate.cpp +++ b/renderdoc/driver/d3d12/d3d12_initstate.cpp @@ -347,7 +347,7 @@ bool D3D12ResourceManager::Prepare_InitialState(ID3D12DeviceChild *res) return false; } -uint32_t D3D12ResourceManager::GetSize_InitialState(ResourceId id, ID3D12DeviceChild *res) +uint64_t D3D12ResourceManager::GetSize_InitialState(ResourceId id, ID3D12DeviceChild *res) { D3D12ResourceRecord *record = GetResourceRecord(id); D3D12InitialContents initContents = GetInitialContents(id); @@ -355,7 +355,7 @@ uint32_t D3D12ResourceManager::GetSize_InitialState(ResourceId id, ID3D12DeviceC if(record->type == Resource_DescriptorHeap) { // the initial contents are just the descriptors. Estimate the serialise size here - const uint32_t descriptorSerSize = 40 + sizeof(D3D12_SAMPLER_DESC); + const uint64_t descriptorSerSize = 40 + sizeof(D3D12_SAMPLER_DESC); // add a little extra room for fixed overhead return 64 + initContents.numDescriptors * descriptorSerSize; @@ -369,8 +369,7 @@ uint32_t D3D12ResourceManager::GetSize_InitialState(ResourceId id, ID3D12DeviceC buf = (ID3D12Resource *)res; } - return (uint32_t)WriteSerialiser::GetChunkAlignment() + 16 + - uint32_t(buf ? buf->GetDesc().Width : 0); + return WriteSerialiser::GetChunkAlignment() + 16 + uint64_t(buf ? buf->GetDesc().Width : 0); } else { diff --git a/renderdoc/driver/d3d12/d3d12_manager.h b/renderdoc/driver/d3d12/d3d12_manager.h index 48c4959ff..49d9f99aa 100644 --- a/renderdoc/driver/d3d12/d3d12_manager.h +++ b/renderdoc/driver/d3d12/d3d12_manager.h @@ -716,7 +716,7 @@ private: bool Force_InitialState(ID3D12DeviceChild *res, bool prepare); bool Need_InitialStateChunk(ID3D12DeviceChild *res); bool Prepare_InitialState(ID3D12DeviceChild *res); - uint32_t GetSize_InitialState(ResourceId id, ID3D12DeviceChild *res); + uint64_t GetSize_InitialState(ResourceId id, ID3D12DeviceChild *res); bool Serialise_InitialState(WriteSerialiser &ser, ResourceId resid, ID3D12DeviceChild *res) { return Serialise_InitialState(ser, resid, res); diff --git a/renderdoc/driver/d3d8/d3d8_manager.cpp b/renderdoc/driver/d3d8/d3d8_manager.cpp index 96a41ce70..66420a6d6 100644 --- a/renderdoc/driver/d3d8/d3d8_manager.cpp +++ b/renderdoc/driver/d3d8/d3d8_manager.cpp @@ -61,7 +61,7 @@ bool D3D8ResourceManager::Prepare_InitialState(IUnknown *res) return false; } -uint32_t D3D8ResourceManager::GetSize_InitialState(ResourceId id, IUnknown *res) +uint64_t D3D8ResourceManager::GetSize_InitialState(ResourceId id, IUnknown *res) { // TODO return 128; diff --git a/renderdoc/driver/d3d8/d3d8_manager.h b/renderdoc/driver/d3d8/d3d8_manager.h index b8fd29583..2aca56d46 100644 --- a/renderdoc/driver/d3d8/d3d8_manager.h +++ b/renderdoc/driver/d3d8/d3d8_manager.h @@ -77,7 +77,7 @@ private: bool Force_InitialState(IUnknown *res, bool prepare); bool Need_InitialStateChunk(IUnknown *res); bool Prepare_InitialState(IUnknown *res); - uint32_t GetSize_InitialState(ResourceId id, IUnknown *res); + uint64_t GetSize_InitialState(ResourceId id, IUnknown *res); bool Serialise_InitialState(WriteSerialiser &ser, ResourceId resid, IUnknown *res); void Create_InitialState(ResourceId id, IUnknown *live, bool hasData); void Apply_InitialState(IUnknown *live, D3D8InitialContents data); diff --git a/renderdoc/driver/gl/gl_initstate.cpp b/renderdoc/driver/gl/gl_initstate.cpp index d056a319c..e2fad78f0 100644 --- a/renderdoc/driver/gl/gl_initstate.cpp +++ b/renderdoc/driver/gl/gl_initstate.cpp @@ -1037,13 +1037,12 @@ bool GLResourceManager::Force_InitialState(GLResource res, bool prepare) return false; } -uint32_t GLResourceManager::GetSize_InitialState(ResourceId resid, GLResource res) +uint64_t GLResourceManager::GetSize_InitialState(ResourceId resid, GLResource res) { if(res.Namespace == eResBuffer) { // buffers just have their contents, no metadata needed - return GetInitialContents(resid).bufferLength + (uint32_t)WriteSerialiser::GetChunkAlignment() + - 16; + return GetInitialContents(resid).bufferLength + WriteSerialiser::GetChunkAlignment() + 16; } else if(res.Namespace == eResProgram) { @@ -1061,11 +1060,11 @@ uint32_t GLResourceManager::GetSize_InitialState(ResourceId resid, GLResource re SerialiseProgramBindings(ser, CaptureState::ActiveCapturing, res.name); SerialiseProgramUniforms(ser, CaptureState::ActiveCapturing, res.name, NULL); - return (uint32_t)ser.GetWriter()->GetOffset() + 256; + return ser.GetWriter()->GetOffset() + 256; } else if(res.Namespace == eResTexture) { - uint32_t ret = 0; + uint64_t ret = 0; ret += sizeof(TextureStateInitialData) + 64; @@ -1112,7 +1111,7 @@ uint32_t GLResourceManager::GetSize_InitialState(ResourceId resid, GLResource re targetcount = 6; for(int t = 0; t < targetcount; t++) - ret += (uint32_t)WriteSerialiser::GetChunkAlignment() + size; + ret += WriteSerialiser::GetChunkAlignment() + size; } return ret; diff --git a/renderdoc/driver/gl/gl_manager.h b/renderdoc/driver/gl/gl_manager.h index 7929cd243..68b582c50 100644 --- a/renderdoc/driver/gl/gl_manager.h +++ b/renderdoc/driver/gl/gl_manager.h @@ -259,7 +259,7 @@ private: bool Force_InitialState(GLResource res, bool prepare); bool Need_InitialStateChunk(GLResource res); bool Prepare_InitialState(GLResource res); - uint32_t GetSize_InitialState(ResourceId resid, GLResource res); + uint64_t GetSize_InitialState(ResourceId resid, GLResource res); void CreateTextureImage(GLuint tex, GLenum internalFormat, GLenum internalFormatHint, GLenum textype, GLint dim, GLint width, GLint height, GLint depth, diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 9b525300d..3245af2c8 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -32,7 +32,7 @@ #include "stb/stb_image_write.h" -uint32_t VkInitParams::GetSerialiseSize() +uint64_t VkInitParams::GetSerialiseSize() { // misc bytes and fixed integer members size_t ret = 128; @@ -45,7 +45,7 @@ uint32_t VkInitParams::GetSerialiseSize() for(const std::string &s : Extensions) ret += 8 + s.size(); - return (uint32_t)ret; + return (uint64_t)ret; } void VkInitParams::Set(const VkInstanceCreateInfo *pCreateInfo, ResourceId inst) diff --git a/renderdoc/driver/vulkan/vk_core.h b/renderdoc/driver/vulkan/vk_core.h index 32395e274..f9b82fbf5 100644 --- a/renderdoc/driver/vulkan/vk_core.h +++ b/renderdoc/driver/vulkan/vk_core.h @@ -52,7 +52,7 @@ struct VkInitParams ResourceId InstanceID; // remember to update this function if you add more members - uint32_t GetSerialiseSize(); + uint64_t GetSerialiseSize(); // check if a frame capture section version is supported static const uint64_t CurrentVersion = 0xF; @@ -916,8 +916,8 @@ public: VulkanReplay *GetReplay() { return &m_Replay; } // replay interface bool Prepare_InitialState(WrappedVkRes *res); - uint32_t GetSize_InitialState(ResourceId id, WrappedVkRes *res); - uint32_t GetSize_SparseInitialState(ResourceId id, WrappedVkRes *res); + uint64_t GetSize_InitialState(ResourceId id, WrappedVkRes *res); + uint64_t GetSize_SparseInitialState(ResourceId id, WrappedVkRes *res); template bool Serialise_InitialState(SerialiserType &ser, ResourceId resid, WrappedVkRes *res); void Create_InitialState(ResourceId id, WrappedVkRes *live, bool hasData); diff --git a/renderdoc/driver/vulkan/vk_initstate.cpp b/renderdoc/driver/vulkan/vk_initstate.cpp index 244427271..8e171070c 100644 --- a/renderdoc/driver/vulkan/vk_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_initstate.cpp @@ -623,7 +623,7 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res) return false; } -uint32_t WrappedVulkan::GetSize_InitialState(ResourceId id, WrappedVkRes *res) +uint64_t WrappedVulkan::GetSize_InitialState(ResourceId id, WrappedVkRes *res) { VkResourceRecord *record = GetResourceManager()->GetResourceRecord(id); VkResourceType type = IdentifyTypeByPtr(record->Resource); @@ -652,7 +652,7 @@ uint32_t WrappedVulkan::GetSize_InitialState(ResourceId id, WrappedVkRes *res) return GetSize_SparseInitialState(id, res); // the size primarily comes from the buffer, the size of which we conveniently have stored. - return uint32_t(128 + initContents.mem.size + WriteSerialiser::GetChunkAlignment()); + return uint64_t(128 + initContents.mem.size + WriteSerialiser::GetChunkAlignment()); } RDCERR("Unhandled resource type %s", ToStr(type).c_str()); diff --git a/renderdoc/driver/vulkan/vk_manager.cpp b/renderdoc/driver/vulkan/vk_manager.cpp index 48fbeb16f..18b2eede8 100644 --- a/renderdoc/driver/vulkan/vk_manager.cpp +++ b/renderdoc/driver/vulkan/vk_manager.cpp @@ -738,7 +738,7 @@ bool VulkanResourceManager::Prepare_InitialState(WrappedVkRes *res) return m_Core->Prepare_InitialState(res); } -uint32_t VulkanResourceManager::GetSize_InitialState(ResourceId id, WrappedVkRes *res) +uint64_t VulkanResourceManager::GetSize_InitialState(ResourceId id, WrappedVkRes *res) { return m_Core->GetSize_InitialState(id, res); } diff --git a/renderdoc/driver/vulkan/vk_manager.h b/renderdoc/driver/vulkan/vk_manager.h index 343365ba3..f25c77422 100644 --- a/renderdoc/driver/vulkan/vk_manager.h +++ b/renderdoc/driver/vulkan/vk_manager.h @@ -439,7 +439,7 @@ private: bool AllowDeletedResource_InitialState() { return true; } bool Need_InitialStateChunk(WrappedVkRes *res); bool Prepare_InitialState(WrappedVkRes *res); - uint32_t GetSize_InitialState(ResourceId id, WrappedVkRes *res); + uint64_t GetSize_InitialState(ResourceId id, WrappedVkRes *res); bool Serialise_InitialState(WriteSerialiser &ser, ResourceId resid, WrappedVkRes *res); void Create_InitialState(ResourceId id, WrappedVkRes *live, bool hasData); void Apply_InitialState(WrappedVkRes *live, VkInitialContents initial); diff --git a/renderdoc/driver/vulkan/vk_sparse_initstate.cpp b/renderdoc/driver/vulkan/vk_sparse_initstate.cpp index c7b6504ed..b606bdc9b 100644 --- a/renderdoc/driver/vulkan/vk_sparse_initstate.cpp +++ b/renderdoc/driver/vulkan/vk_sparse_initstate.cpp @@ -359,7 +359,7 @@ bool WrappedVulkan::Prepare_SparseInitialState(WrappedVkImage *im) return true; } -uint32_t WrappedVulkan::GetSize_SparseInitialState(ResourceId id, WrappedVkRes *res) +uint64_t WrappedVulkan::GetSize_SparseInitialState(ResourceId id, WrappedVkRes *res) { VkResourceRecord *record = GetResourceManager()->GetResourceRecord(id); VkResourceType type = IdentifyTypeByPtr(record->Resource); @@ -370,7 +370,7 @@ uint32_t WrappedVulkan::GetSize_SparseInitialState(ResourceId id, WrappedVkRes * SparseBufferInitState &info = contents.sparseBuffer; // some bytes just to cover overheads etc. - uint32_t ret = 128; + uint64_t ret = 128; // the list of memory objects bound ret += 8 + sizeof(VkSparseMemoryBind) * info.numBinds; @@ -379,7 +379,7 @@ uint32_t WrappedVulkan::GetSize_SparseInitialState(ResourceId id, WrappedVkRes * ret += 8 + sizeof(MemIDOffset) * info.numUniqueMems; // the actual data - ret += uint32_t(info.totalSize + WriteSerialiser::GetChunkAlignment()); + ret += uint64_t(info.totalSize + WriteSerialiser::GetChunkAlignment()); return ret; } @@ -388,7 +388,7 @@ uint32_t WrappedVulkan::GetSize_SparseInitialState(ResourceId id, WrappedVkRes * SparseImageInitState &info = contents.sparseImage; // some bytes just to cover overheads etc. - uint32_t ret = 128; + uint64_t ret = 128; // the meta-data structure ret += sizeof(SparseImageInitState); @@ -404,7 +404,7 @@ uint32_t WrappedVulkan::GetSize_SparseInitialState(ResourceId id, WrappedVkRes * ret += sizeof(MemIDOffset) * info.numUniqueMems; // the actual data - ret += uint32_t(info.totalSize + WriteSerialiser::GetChunkAlignment()); + ret += uint64_t(info.totalSize + WriteSerialiser::GetChunkAlignment()); return ret; } diff --git a/renderdoc/serialise/rdcfile.cpp b/renderdoc/serialise/rdcfile.cpp index 17a22438b..d3b3c1738 100644 --- a/renderdoc/serialise/rdcfile.cpp +++ b/renderdoc/serialise/rdcfile.cpp @@ -319,7 +319,7 @@ void RDCFile::Init(StreamReader &reader) m_SerVer = header.version; - if(m_SerVer != SERIALISE_VERSION) + if(m_SerVer != SERIALISE_VERSION && m_SerVer != V1_0_VERSION) { if(header.version < V1_0_VERSION) { diff --git a/renderdoc/serialise/rdcfile.h b/renderdoc/serialise/rdcfile.h index bb2a4f206..2959d0767 100644 --- a/renderdoc/serialise/rdcfile.h +++ b/renderdoc/serialise/rdcfile.h @@ -61,11 +61,12 @@ public: // version number of overall file format or chunk organisation. If the contents/meaning/order of // chunks have changed this does not need to be bumped, there are version numbers within each // API that interprets the stream that can be bumped. - static const uint32_t SERIALISE_VERSION = 0x00000100; + static const uint32_t SERIALISE_VERSION = 0x00000101; // this must never be changed - files before this were in the v0.x series and didn't have embedded // version numbers static const uint32_t V1_0_VERSION = 0x00000100; + static const uint32_t V1_1_VERSION = 0x00000101; ~RDCFile(); diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index f3ac37edd..5157b0d8e 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -60,7 +60,7 @@ Serialiser::~Serialiser() } template <> -uint32_t Serialiser::BeginChunk(uint32_t, uint32_t) +uint32_t Serialiser::BeginChunk(uint32_t, uint64_t) { uint32_t chunkID = 0; @@ -100,7 +100,16 @@ uint32_t Serialiser::BeginChunk(uint32_t, uint32_t) if(c & ChunkTimestamp) m_Read->Read(m_ChunkMetadata.timestampMicro); - m_Read->Read(m_ChunkMetadata.length); + if(c & Chunk64BitSize) + { + m_Read->Read(m_ChunkMetadata.length); + } + else + { + uint32_t chunkSize = 0; + m_Read->Read(chunkSize); + m_ChunkMetadata.length = chunkSize; + } m_LastChunkOffset = m_Read->GetOffset(); } @@ -260,7 +269,7 @@ void Serialiser::SetChunkMetadataRecording(uint32_t fla } template <> -uint32_t Serialiser::BeginChunk(uint32_t chunkID, uint32_t byteLength) +uint32_t Serialiser::BeginChunk(uint32_t chunkID, uint64_t byteLength) { { // chunk index needs to be valid @@ -271,6 +280,8 @@ uint32_t Serialiser::BeginChunk(uint32_t chunkID, uint3 RDCASSERT(chunkID <= ChunkIndexMask); c |= m_ChunkFlags; + if(byteLength > 0xffffffff) + c |= Chunk64BitSize; m_ChunkMetadata.chunkID = chunkID; @@ -334,13 +345,23 @@ uint32_t Serialiser::BeginChunk(uint32_t chunkID, uint3 { // write length, assuming it is an upper bound m_ChunkFixup = 0; - m_Write->Write(byteLength); + RDCASSERT(byteLength < 0x100000000 || (c & Chunk64BitSize) != 0); + if(c & Chunk64BitSize) + { + m_Write->Write(byteLength); + } + else + { + m_Write->Write(uint32_t(byteLength & 0xffffffff)); + } m_LastChunkOffset = m_Write->GetOffset(); m_ChunkMetadata.length = byteLength; } else { // length will be fixed up in EndChunk + // assume that this case will not produce chunks with size larger than can fit in 32 bit + // value uint32_t chunkSize = 0xbeebfeed; m_ChunkFixup = m_Write->GetOffset(); m_Write->Write(chunkSize); @@ -371,12 +392,13 @@ void Serialiser::EndChunk() RDCASSERT(curOffset > chunkOffset); uint64_t chunkLength = (curOffset - chunkOffset) - sizeof(uint32_t); + if(chunkLength > 0xffffffff) + { + RDCERR("!!! CHUNK LENGTH %llu EXCEEDED 32 BIT VALUE. CAPTURE WILL BE CORRUPTED. !!!", + chunkLength); + } - RDCASSERT(chunkLength < 0xffffffff); - - uint32_t chunklen = (uint32_t)chunkLength; - - m_Write->WriteAt(chunkOffset, chunklen); + m_Write->WriteAt(chunkOffset, uint32_t(chunkLength & 0xffffffff)); } else { @@ -393,21 +415,21 @@ void Serialiser::EndChunk() m_Write->Write(padByte); } - RDCDEBUG("Chunk estimated at %u bytes, actual length %llu. Added %llu bytes padding.", + RDCDEBUG("Chunk estimated at %llu bytes, actual length %llu. Added %llu bytes padding.", m_ChunkMetadata.length, writtenLength, numPadBytes); } else if(writtenLength > m_ChunkMetadata.length) { RDCERR( "!!! " - "ESTIMATED UPPER BOUND CHUNK LENGTH %u EXCEEDED: %llu. " + "ESTIMATED UPPER BOUND CHUNK LENGTH %llu EXCEEDED: %llu. " "CAPTURE WILL BE CORRUPTED. " "!!!", m_ChunkMetadata.length, writtenLength); } else { - RDCDEBUG("Chunk was exactly the estimate of %u bytes.", m_ChunkMetadata.length); + RDCDEBUG("Chunk was exactly the estimate of %llu bytes.", m_ChunkMetadata.length); } } diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index fbb8f29cd..4a93461dc 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -100,6 +100,7 @@ public: ChunkThreadID = 0x00020000, ChunkDuration = 0x00040000, ChunkTimestamp = 0x00080000, + Chunk64BitSize = 0x00100000, }; ////////////////////////////////////////// @@ -156,7 +157,7 @@ public: m_ExportStructured = (lookup != NULL); } - uint32_t BeginChunk(uint32_t chunkID, uint32_t byteLength); + uint32_t BeginChunk(uint32_t chunkID, uint64_t byteLength); void EndChunk(); std::string GetCurChunkName() @@ -1632,7 +1633,7 @@ class WriteSerialiser : public Serialiser { public: WriteSerialiser(StreamWriter *writer, Ownership own) : Serialiser(writer, own) {} - void WriteChunk(uint32_t chunkID, uint32_t byteLength = 0) { BeginChunk(chunkID, byteLength); } + void WriteChunk(uint32_t chunkID, uint64_t byteLength = 0) { BeginChunk(chunkID, byteLength); } }; class ReadSerialiser : public Serialiser @@ -1833,7 +1834,7 @@ class ScopedChunk { public: template - ScopedChunk(WriteSerialiser &s, ChunkType i, uint32_t byteLength = 0) + ScopedChunk(WriteSerialiser &s, ChunkType i, uint64_t byteLength = 0) : m_Idx(uint32_t(i)), m_Ser(s), m_Ended(false) { m_Ser.WriteChunk(m_Idx, byteLength);