summaryrefslogtreecommitdiff
path: root/Runtime/Serialize/Blobification/BlobWrite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Serialize/Blobification/BlobWrite.cpp')
-rw-r--r--Runtime/Serialize/Blobification/BlobWrite.cpp148
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;
+ }
+ }
+}