diff options
Diffstat (limited to 'Runtime/Serialize/Blobification/BlobWrite.cpp')
-rw-r--r-- | Runtime/Serialize/Blobification/BlobWrite.cpp | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/Runtime/Serialize/Blobification/BlobWrite.cpp b/Runtime/Serialize/Blobification/BlobWrite.cpp new file mode 100644 index 0000000..dcb7705 --- /dev/null +++ b/Runtime/Serialize/Blobification/BlobWrite.cpp @@ -0,0 +1,148 @@ +#include "UnityPrefix.h" +#include "BlobWrite.h" +#include "Configuration/UnityConfigure.h" +#include "BlobWriteTargetSupport.h" + +BlobWrite::BlobWrite (container_type& blob, TransferInstructionFlags flags, BuildTargetPlatform targetPlatform) +: m_Blob(blob), + m_CopyData(true), + m_ReduceCopy(false), + m_TargetPlatform(targetPlatform) +{ + m_Flags = false; + m_SwapEndianess = m_Flags & kSwapEndianess; + m_Use64BitOffsetPtr = IsBuildTarget64BitBlob (targetPlatform); +} + +void BlobWrite::Push (size_t size, void* srcDataPtr, size_t align) +{ + Assert (m_CopyData); + + size_t offset = AlignAddress(m_Blob.size(), align); + m_Context.push( TypeContext(offset, 0, reinterpret_cast<UInt8*> (srcDataPtr), size) ); + m_Blob.resize_initialized(offset + size, 0); + m_CopyData = false; +} + +void BlobWrite::WritePtrValueAtLocation (size_t locationInBlob, SInt64 value) +{ + if (m_Use64BitOffsetPtr) + { + SInt64 offset64 = value; + + if (m_SwapEndianess) + SwapEndianBytes(offset64); + memcpy (&m_Blob[locationInBlob], &offset64, sizeof(offset64)); + } + else + { + SInt32 offset32 = value; + + if (m_SwapEndianess) + SwapEndianBytes(offset32); + memcpy (&m_Blob[locationInBlob], &offset32, sizeof(offset32)); + } +} + + +void BlobWrite::TransferPtrImpl (bool isValidPtr, ReduceCopyData* reduceCopyData, size_t alignOfT) +{ + Assert(!m_CopyData); + // When the data is null we will not call Transfer. + m_CopyData = isValidPtr; + + // Need to update OffsetPtr's member 'mOffset' + // compute member offset in memory buffer + size_t dataPosition = AlignAddress(m_Blob.size(), alignOfT); + size_t offset = GetActiveOffset(); + offset = dataPosition - offset; + if (!isValidPtr) + offset = 0; + + // Write the ptr + WritePtrValueAtLocation(GetActiveOffset (), offset); + + // Setup reduce copy data for later use by ReduceCopyImpl + if (reduceCopyData != NULL) + { + if (isValidPtr) + { + reduceCopyData->ptrPosition = GetActiveOffset(); + reduceCopyData->dataStart = dataPosition; + reduceCopyData->blobSize = m_Blob.size(); + } + else + { + reduceCopyData->ptrPosition = 0xFFFFF; + reduceCopyData->dataStart = 0xFFFFF; + reduceCopyData->blobSize = 0xFFFFF; + } + } + + + // Offset write location in the blob + m_Context.top().m_Offset += m_Use64BitOffsetPtr ? sizeof(SInt64) : sizeof(SInt32); + if (HasOffsetPtrWithDebugPtr()) + m_Context.top().m_Offset += sizeof(void*); +} + +bool BlobWrite::HasOffsetPtrWithDebugPtr () const +{ + return m_TargetPlatform == kBuildNoTargetPlatform; +} + +bool BlobWrite::AllowDataLayoutValidation () const +{ + size_t targetOffsetPtrSize = Use64BitOffsetPtr () ? sizeof(SInt64) : sizeof(SInt32); + if (HasOffsetPtrWithDebugPtr ()) + targetOffsetPtrSize += sizeof(void*); + + size_t srcOffsetPtrSize = sizeof(OffsetPtr<UInt8>); + + return targetOffsetPtrSize == srcOffsetPtrSize; +} + +// Ensure that the user has matching Transfer calls & Data layout in the struct +void BlobWrite::ValidateSerializedLayout (void* srcData, const char* name) +{ + UInt8* srcDataPtr = reinterpret_cast<UInt8*> (srcData); + + // (float4 and some others transfer functions, transfer temporary data, we ignore layout checks on those and hope for the best) + int srcDataOffset = srcDataPtr - m_Context.top().m_SourceDataPtr; + if (srcDataOffset < 0 || srcDataOffset >= m_Context.top().m_SourceDataSize) + return; + + // When targeting a platform with a different layout than our own, obviously these checks dont make sense... + if (!AllowDataLayoutValidation ()) + return; + + int blobOffset = m_Context.top().m_Offset; + if (srcDataOffset != blobOffset) + { + AssertString(Format("BlobWrite: Transfer '%s' is not called in the same order as the struct is laid out. Expected: %d got: %d ", name, srcDataOffset, blobOffset)); + } +} + +void BlobWrite::ReduceCopyImpl (const ReduceCopyData& reduce, size_t alignOfT) +{ + if (!m_ReduceCopy || reduce.dataStart == 0xFFFFF) + return; + + // Find any data in the blob that matches the last written data. + // if we find it, delete it again and reference the previous memory block instead + size_t dataSize = m_Blob.size() - reduce.dataStart; + for (int i=0;i < reduce.dataStart;i+=alignOfT) + { + if (memcmp(&m_Blob[i], &m_Blob[reduce.dataStart], dataSize) == 0) + { + // Update offset pointer + SInt64 offset = i - reduce.ptrPosition; + WritePtrValueAtLocation (reduce.ptrPosition, offset); + + // resize blob based on the reduce copy + m_Blob.resize_initialized(reduce.blobSize, 0); + + return; + } + } +} |