/// <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);
        }
示例#2
0
 private void doReachCheck(TextWriter warningLog, NodeId node, SortedIndex nodeList, int curDepth)
 {
     throw new NotImplementedException();
 }
示例#3
0
        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);
        }
示例#4
0
 public void CreateReachabilityList(TextWriter warningLog, NodeId node, SortedIndex nodeList)
 {
     CheckErrorState();
     lock (reachabilityLock) {
         reachabilityTreeDepth = -1;
         doReachCheck(warningLog, node, nodeList, 1);
     }
 }