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); }
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 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); }