unsafe public static BlobAssetReference <T> Create(byte[] data) { byte *buffer = (byte *)UnsafeUtility.Malloc(sizeof(BlobAssetHeader) + data.Length, 16, Allocator.Persistent); fixed(byte *ptr = &data[0]) { UnsafeUtility.MemCpy(buffer + sizeof(BlobAssetHeader), ptr, data.Length); } BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Refcount = 1; header->Allocator = Allocator.Persistent; BlobAssetReference <T> assetReference; assetReference.m_Ptr = buffer + sizeof(BlobAssetHeader); #if ENABLE_UNITY_COLLECTIONS_CHECKS assetReference.m_Safety = AtomicSafetyHandle.Create(); AtomicSafetyHandle.SetAllowSecondaryVersionWriting(assetReference.m_Safety, false); AtomicSafetyHandle.UseSecondaryVersion(ref assetReference.m_Safety); #endif return(assetReference); }
public BlobAssetReference <T> CreateBlobAssetReference <T>(Allocator allocator) where T : struct { Assert.AreEqual(16, sizeof(BlobAssetHeader)); long dataSize = (m_Ptr - m_RootPtr); byte *buffer = (byte *)UnsafeUtility.Malloc(sizeof(BlobAssetHeader) + dataSize, 16, allocator); UnsafeUtility.MemCpy(buffer + sizeof(BlobAssetHeader), m_RootPtr, dataSize); BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Refcount = 1; header->Allocator = allocator; BlobAssetReference <T> assetReference; assetReference.m_Ptr = buffer + sizeof(BlobAssetHeader); #if ENABLE_UNITY_COLLECTIONS_CHECKS assetReference.m_Safety = AtomicSafetyHandle.Create(); AtomicSafetyHandle.SetAllowSecondaryVersionWriting(assetReference.m_Safety, false); AtomicSafetyHandle.UseSecondaryVersion(ref assetReference.m_Safety); #endif return(assetReference); }
public static unsafe void WriteBlobAsset <T>(ref BlobAssetReference <T> assetReference, string fileName) where T : struct { using (BinaryWriter writer = new BinaryWriter(File.Open(ConvertFileName(fileName), FileMode.Create))) { var assetPtr = assetReference.GetUnsafePtr(); BlobAssetHeader *header = ((BlobAssetHeader *)assetPtr) - 1; long dataSize = header->Length; var data = new byte[dataSize]; fixed(byte *ptr = &data[0]) { UnsafeUtility.MemCpy(ptr, UnsafeUtility.AddressOf(ref assetReference.Value), data.Length); } writer.Write(data); writer.Close(); } }
public static BlobAssetReference <T> Create(void *ptr, int length) { byte *buffer = (byte *)UnsafeUtility.Malloc(sizeof(BlobAssetHeader) + length, 16, Allocator.Persistent); UnsafeUtility.MemCpy(buffer + sizeof(BlobAssetHeader), ptr, length); BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Length = length; header->Allocator = Allocator.Persistent; BlobAssetReference <T> blobAssetReference; header->ValidationPtr = blobAssetReference.m_data.m_Ptr = buffer + sizeof(BlobAssetHeader); return(blobAssetReference); }
/// <summary> /// Creates a blob asset from a pointer to data and a specified size. /// </summary> /// <remarks>The blob asset is created in unmanaged memory. Call <see cref="Dispose"/> to free the asset memory /// when it is no longer needed. This function can only be used in an [unsafe context]. /// [unsafe context]: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code /// </remarks> /// <param name="ptr">A pointer to the buffer containing the data to store in the blob asset.</param> /// <param name="length">The length of the buffer in bytes.</param> /// <returns>A reference to newly created blob asset.</returns> /// <seealso cref="BlobBuilder"/> public static BlobAssetReference <T> Create(void *ptr, int length) { byte *buffer = (byte *)Memory.Unmanaged.Allocate(sizeof(BlobAssetHeader) + length, 16, Allocator.Persistent); UnsafeUtility.MemCpy(buffer + sizeof(BlobAssetHeader), ptr, length); BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Length = length; header->Allocator = Allocator.Persistent; // @TODO use 64bit hash header->Hash = math.hash(ptr, length); BlobAssetReference <T> blobAssetReference; blobAssetReference.m_data.m_Align8Union = 0; header->ValidationPtr = blobAssetReference.m_data.m_Ptr = buffer + sizeof(BlobAssetHeader); return(blobAssetReference); }
public BlobAssetReference <T> CreateBlobAssetReference <T>(Allocator allocator) where T : struct { Assert.AreEqual(16, sizeof(BlobAssetHeader)); long dataSize = (m_Ptr - m_RootPtr); Assertions.Assert.IsTrue(dataSize <= 0x7FFFFFFF); byte *buffer = (byte *)UnsafeUtility.Malloc(sizeof(BlobAssetHeader) + dataSize, 16, allocator); UnsafeUtility.MemCpy(buffer + sizeof(BlobAssetHeader), m_RootPtr, dataSize); BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Length = (int)dataSize; header->Allocator = allocator; BlobAssetReference <T> blobAssetReference; header->ValidationPtr = blobAssetReference.m_data.m_Ptr = buffer + sizeof(BlobAssetHeader); return(blobAssetReference); }
/// <summary> /// Completes construction of the blob asset and returns a reference to the asset in unmanaged memory. /// </summary> /// <remarks>Use the <see cref="BlobAssetReference{T}"/> to access the blob asset. When the asset is no longer /// needed, call<see cref="BlobAssetReference{T}.Dispose()"/> to destroy the blob asset and free its allocated /// memory.</remarks> /// <param name="allocator">The type of memory to allocate. Unless the asset has a very short life span, use /// <see cref="Allocator.Persistent"/>.</param> /// <typeparam name="T">The data type of the struct used to construct the asset's root. Use the same struct type /// that you used when calling <see cref="ConstructRoot{T}"/>.</typeparam> /// <returns></returns> public BlobAssetReference <T> CreateBlobAssetReference <T>(Allocator allocator) where T : struct { var offsets = new NativeArray <int>(m_allocations.Length + 1, Allocator.Temp); var sortedAllocs = new NativeArray <SortedIndex>(m_allocations.Length, Allocator.Temp); offsets[0] = 0; for (int i = 0; i < m_allocations.Length; ++i) { offsets[i + 1] = offsets[i] + m_allocations[i].size; sortedAllocs[i] = new SortedIndex { p = m_allocations[i].p, index = i }; } int dataSize = offsets[m_allocations.Length]; sortedAllocs.Sort(); var sortedPatches = new NativeArray <SortedIndex>(m_patches.Length, Allocator.Temp); for (int i = 0; i < m_patches.Length; ++i) { sortedPatches[i] = new SortedIndex { p = (byte *)m_patches[i].offsetPtr, index = i } } ; sortedPatches.Sort(); byte *buffer = (byte *)Memory.Unmanaged.Allocate(sizeof(BlobAssetHeader) + dataSize, 16, allocator); byte *data = buffer + sizeof(BlobAssetHeader); for (int i = 0; i < m_allocations.Length; ++i) { UnsafeUtility.MemCpy(data + offsets[i], m_allocations[i].p, m_allocations[i].size); } int iAlloc = 0; var allocStart = m_allocations[sortedAllocs[0].index].p; var allocEnd = allocStart + m_allocations[sortedAllocs[0].index].size; for (int i = 0; i < m_patches.Length; ++i) { int patchIndex = sortedPatches[i].index; int *offsetPtr = (int *)sortedPatches[i].p; while (offsetPtr > allocEnd) { ++iAlloc; allocStart = m_allocations[sortedAllocs[iAlloc].index].p; allocEnd = allocStart + m_allocations[sortedAllocs[iAlloc].index].size; } var patch = m_patches[patchIndex]; int offsetPtrInData = offsets[sortedAllocs[iAlloc].index] + (int)((byte *)offsetPtr - allocStart); int targetPtrInData = offsets[patch.target.allocIndex] + patch.target.offset; *(int *)(data + offsetPtrInData) = targetPtrInData - offsetPtrInData; if (patch.length != 0) { *(int *)(data + offsetPtrInData + 4) = patch.length; } } sortedPatches.Dispose(); sortedAllocs.Dispose(); offsets.Dispose(); BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Length = (int)dataSize; header->Allocator = allocator; // @TODO use 64bit hash header->Hash = math.hash(buffer + sizeof(BlobAssetHeader), dataSize); BlobAssetReference <T> blobAssetReference; blobAssetReference.m_data.m_Align8Union = 0; header->ValidationPtr = blobAssetReference.m_data.m_Ptr = buffer + sizeof(BlobAssetHeader); return(blobAssetReference); } void *AllocationToPointer(BlobDataRef blobDataRef) { return(m_allocations[blobDataRef.allocIndex].p + blobDataRef.offset); } BlobAllocation EnsureEnoughRoomInChunk(int size, int alignment) { if (m_currentChunkIndex == -1) { return(AllocateNewChunk()); } var alloc = m_allocations[m_currentChunkIndex]; int startOffset = CollectionHelper.Align(alloc.size, alignment); if (startOffset + size > m_chunkSize) { return(AllocateNewChunk()); } UnsafeUtility.MemClear(alloc.p + alloc.size, startOffset - alloc.size); alloc.size = startOffset; return(alloc); } BlobDataRef Allocate(int size, int alignment) { if (size > m_chunkSize) { size = CollectionHelper.Align(size, 16); var allocIndex = m_allocations.Length; var mem = (byte *)Memory.Unmanaged.Allocate(size, alignment, m_allocator); UnsafeUtility.MemClear(mem, size); m_allocations.Add(new BlobAllocation { p = mem, size = size }); return(new BlobDataRef { allocIndex = allocIndex, offset = 0 }); } BlobAllocation alloc = EnsureEnoughRoomInChunk(size, alignment); var offset = alloc.size; UnsafeUtility.MemClear(alloc.p + alloc.size, size); alloc.size += size; m_allocations[m_currentChunkIndex] = alloc; return(new BlobDataRef { allocIndex = m_currentChunkIndex, offset = offset }); } BlobAllocation AllocateNewChunk() { // align size of last chunk to 16 bytes so chunks can be concatenated without breaking alignment if (m_currentChunkIndex != -1) { var currentAlloc = m_allocations[m_currentChunkIndex]; currentAlloc.size = CollectionHelper.Align(currentAlloc.size, 16); m_allocations[m_currentChunkIndex] = currentAlloc; } m_currentChunkIndex = m_allocations.Length; var alloc = new BlobAllocation { p = (byte *)Memory.Unmanaged.Allocate(m_chunkSize, 16, m_allocator), size = 0 }; m_allocations.Add(alloc); return(alloc); }
public override int GetHashCode() { BlobAssetHeader *onStack = header; return((int)math.hash(&onStack, sizeof(BlobAssetHeader *))); }
public BlobAssetPtr(BlobAssetHeader *header) { this.header = header; }
public BlobAssetPtr(BlobAssetHeader *header) => Header = header;
public BlobAssetReference <T> CreateBlobAssetReference <T>(Allocator allocator) where T : struct { Assert.AreEqual(16, sizeof(BlobAssetHeader)); NativeArray <int> offsets = new NativeArray <int>(m_allocations.Length + 1, m_allocator); var sortedAllocs = new NativeArray <SortedIndex>(m_allocations.Length, m_allocator); offsets[0] = 0; for (int i = 0; i < m_allocations.Length; ++i) { offsets[i + 1] = offsets[i] + m_allocations[i].size; sortedAllocs[i] = new SortedIndex { p = m_allocations[i].p, index = i }; } int dataSize = offsets[m_allocations.Length]; sortedAllocs.Sort(); var sortedPatches = new NativeArray <SortedIndex>(m_patches.Length, m_allocator); for (int i = 0; i < m_patches.Length; ++i) { sortedPatches[i] = new SortedIndex { p = (byte *)m_patches[i].offsetPtr, index = i } } ; sortedPatches.Sort(); byte *buffer = (byte *)UnsafeUtility.Malloc(sizeof(BlobAssetHeader) + dataSize, 16, allocator); byte *data = buffer + sizeof(BlobAssetHeader); for (int i = 0; i < m_allocations.Length; ++i) { UnsafeUtility.MemCpy(data + offsets[i], m_allocations[i].p, m_allocations[i].size); } int iAlloc = 0; var allocStart = m_allocations[sortedAllocs[0].index].p; var allocEnd = allocStart + m_allocations[sortedAllocs[0].index].size; for (int i = 0; i < m_patches.Length; ++i) { int patchIndex = sortedPatches[i].index; int *offsetPtr = (int *)sortedPatches[i].p; while (offsetPtr > allocEnd) { ++iAlloc; allocStart = m_allocations[sortedAllocs[iAlloc].index].p; allocEnd = allocStart + m_allocations[sortedAllocs[iAlloc].index].size; } var patch = m_patches[patchIndex]; int offsetPtrInData = offsets[sortedAllocs[iAlloc].index] + (int)((byte *)offsetPtr - allocStart); int targetPtrInData = offsets[patch.target.allocIndex] + patch.target.offset; *(int *)(data + offsetPtrInData) = targetPtrInData - offsetPtrInData; if (patch.length != 0) { *(int *)(data + offsetPtrInData + 4) = patch.length; } } sortedPatches.Dispose(); sortedAllocs.Dispose(); BlobAssetHeader *header = (BlobAssetHeader *)buffer; *header = new BlobAssetHeader(); header->Length = (int)dataSize; header->Allocator = allocator; BlobAssetReference <T> blobAssetReference; header->ValidationPtr = blobAssetReference.m_data.m_Ptr = buffer + sizeof(BlobAssetHeader); return(blobAssetReference); }