예제 #1
0
        public static IpcCircularBuffer Create(string name, int blockSize, int numberOfBlocks)
        {
            Random r = new Random();
            long   readSemaphoreId  = ((long)r.Next() << 32) + r.Next();
            long   writeSemaphoreId = ((long)r.Next() << 32) + r.Next();

            Section section = new Section(name, blockSize * numberOfBlocks, MemoryProtection.ReadWrite);

            using (SectionView view = section.MapView(BufferHeader.SizeOf))
            {
                BufferHeader header = new BufferHeader
                {
                    BlockSize        = blockSize,
                    NumberOfBlocks   = numberOfBlocks,
                    ReadSemaphoreId  = readSemaphoreId,
                    WriteSemaphoreId = writeSemaphoreId,
                    ReadPosition     = 0, WritePosition = 0
                };

                view.WriteStruct(header);
            }

            return(new IpcCircularBuffer(
                       section,
                       name,
                       new Semaphore(name + "_" + readSemaphoreId.ToString("x"), 0, numberOfBlocks),
                       new Semaphore(name + "_" + writeSemaphoreId.ToString("x"), numberOfBlocks, numberOfBlocks)
                       ));
        }
예제 #2
0
        public void CopyFrom(DynamicBufferUnsafe <T> v)
        {
            ResizeUninitialized(v.Length);

            UnsafeUtility.MemCpy(BufferHeader.GetElementPointer(m_Buffer),
                                 BufferHeader.GetElementPointer(v.m_Buffer), Length * UnsafeUtility.SizeOf <T>());
        }
예제 #3
0
        public static IpcCircularBuffer Create(string name, int blockSize, int numberOfBlocks)
        {
            Random  r = new Random();
            long    readSemaphoreId  = ((long)r.Next() << 32) + r.Next();
            long    writeSemaphoreId = ((long)r.Next() << 32) + r.Next();
            Section section;

            section = new Section(name, blockSize * numberOfBlocks, MemoryProtection.ReadWrite);

            using (var view = section.MapView(Marshal.SizeOf(typeof(BufferHeader))))
            {
                BufferHeader header = new BufferHeader();

                header.BlockSize        = blockSize;
                header.NumberOfBlocks   = numberOfBlocks;
                header.ReadSemaphoreId  = readSemaphoreId;
                header.WriteSemaphoreId = writeSemaphoreId;
                header.ReadPosition     = 0;
                header.WritePosition    = 0;

                view.WriteStruct <BufferHeader>(header);
            }

            return(new IpcCircularBuffer(
                       section,
                       name,
                       new Semaphore(name + "_" + readSemaphoreId.ToString("x"), 0, numberOfBlocks),
                       new Semaphore(name + "_" + writeSemaphoreId.ToString("x"), numberOfBlocks, numberOfBlocks)
                       ));
        }
예제 #4
0
 public BufferResult FirstPage()
 {
     return(new BufferResult()
     {
         Length = (*_first).Used, Buffer = (IntPtr)BufferHeader.Data(_first)
     });
 }
예제 #5
0
        public override void WriteByte(byte value)
        {
            EnsureCapacity();
            var data = BufferHeader.Data(_current) + (*_current).Used;

            (*data) = value;
            ++(*_current).Used;
        }
예제 #6
0
        public void AddRange(NativeArray <T> newElems)
        {
            int elemSize  = UnsafeUtility.SizeOf <T>();
            int oldLength = Length;

            ResizeUninitialized(oldLength + newElems.Length);

            byte *basePtr = BufferHeader.GetElementPointer(m_Buffer);

            UnsafeUtility.MemCpy(basePtr + (long)oldLength * elemSize, newElems.GetUnsafeReadOnlyPtr <T>(), (long)elemSize * newElems.Length);
        }
예제 #7
0
        public void RemoveRange(int index, int count)
        {
            CheckBounds(index + count - 1);

            int   elemSize = UnsafeUtility.SizeOf <T>();
            byte *basePtr  = BufferHeader.GetElementPointer(m_Buffer);

            UnsafeUtility.MemMove(basePtr + index * elemSize, basePtr + (index + count) * elemSize, (long)elemSize * (Length - count - index));

            m_Buffer->Length -= count;
        }
예제 #8
0
        public void Insert(int index, T elem)
        {
            int length = Length;

            ResizeUninitialized(length + 1);
            CheckBounds(index); //CheckBounds after ResizeUninitialized since index == length is allowed
            int   elemSize = UnsafeUtility.SizeOf <T>();
            byte *basePtr  = BufferHeader.GetElementPointer(m_Buffer);

            UnsafeUtility.MemMove(basePtr + (index + 1) * elemSize, basePtr + index * elemSize, (long)elemSize * (length - index));
            this[index] = elem;
        }
예제 #9
0
 public T this[int index]
 {
     get
     {
         CheckBounds(index);
         return(UnsafeUtility.ReadArrayElement <T>(BufferHeader.GetElementPointer(m_Buffer), index));
     }
     set
     {
         CheckBounds(index);
         UnsafeUtility.WriteArrayElement <T>(BufferHeader.GetElementPointer(m_Buffer), index, value);
     }
 }
예제 #10
0
        public BufferResult NextPage(BufferResult result)
        {
            var current = (BufferHeader *)((byte *)result.Buffer - BufferHeader.BufferHeaderSize);
            var next    = (*current).Next;

            if (next == null)
            {
                return(new BufferResult());
            }

            return(new BufferResult()
            {
                Length = (*next).Used, Buffer = (IntPtr)BufferHeader.Data(next)
            });
        }
예제 #11
0
    public void SetBufferRaw(Entity entity, int componentTypeIndex, BufferHeader *tempBuffer, int sizeInChunk)
    {
        EntityComponentStore->AssertEntityHasComponent(entity, componentTypeIndex);

        if (m_IsMainThread)
        {
            EntityManager.DependencyManager->CompleteReadAndWriteDependency(componentTypeIndex);
        }

        var ptr = EntityComponentStore->GetComponentDataWithTypeRW(entity, componentTypeIndex,
                                                                   EntityComponentStore->GlobalSystemVersion);

        BufferHeader.Destroy((BufferHeader *)ptr);

        UnsafeUtility.MemCpy(ptr, tempBuffer, sizeInChunk);
    }
예제 #12
0
        public byte[] FullBuffer()
        {
            var data     = new byte[_length];
            var page     = _first;
            int position = 0;

            fixed(byte *b = data)
            while (page != null)
            {
                var length = (*page).Used;

                MemoryUtils.CopyMemory(BufferHeader.Data(page), b + position, length);
                position += length;
                page      = (*page).Next;
            }

            return(data);
        }
예제 #13
0
        static unsafe void WriteChunkData(YamlWriter writer, EntityManager entityManager, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapInfos, Chunk *initialChunk, Archetype *archetype, int archetypeIndex, bool dumpChunkRawData)
        {
            var    tempChunkMem = stackalloc byte[Chunk.kChunkSize];
            Chunk *tempChunk    = (Chunk *)tempChunkMem;

            if (dumpChunkRawData)
            {
                UnsafeUtility.MemCpy(tempChunk, initialChunk, Chunk.kChunkSize);

                byte *tempChunkBuffer = tempChunk->Buffer;

                BufferHeader.PatchAfterCloningChunk(tempChunk);
                EntityRemapUtility.PatchEntities(archetype->ScalarEntityPatches, archetype->ScalarEntityPatchCount, archetype->BufferEntityPatches, archetype->BufferEntityPatchCount, tempChunkBuffer, tempChunk->Count, ref entityRemapInfos);
                ClearChunkHeaderComponents(tempChunk);
                ChunkDataUtility.MemsetUnusedChunkData(tempChunk, 0);

                tempChunk->Archetype = (Archetype *)archetypeIndex;
            }

            using (writer.WriteCollection(k_ChunkDataCollectionTag))
            {
                using (writer.WriteCollection("Header"))
                {
                    WriteEntity(writer, nameof(Chunk.metaChunkEntity), initialChunk->metaChunkEntity);
                    writer.WriteKeyValue(nameof(Chunk.Capacity), initialChunk->Capacity);
                    writer.WriteKeyValue(nameof(Chunk.Count), initialChunk->Count);

                    if (dumpChunkRawData)
                    {
                        writer.WriteFormattedBinaryData("Header-RawData", tempChunk, Chunk.kBufferOffset);
                    }
                }

                // First pass to sort by component type
                var entitiesByChunkIndex   = new Dictionary <int, Entity>();
                var componentDataList      = new List <int>();
                var chunkComponentDataList = new List <int>();
                var chunkTypes             = archetype->Types;
                for (int typeI = 0; typeI < archetype->TypesCount; typeI++)
                {
                    var componentType         = &chunkTypes[typeI];
                    var type                  = TypeManager.GetType(componentType->TypeIndex);
                    ref readonly var typeInfo = ref TypeManager.GetTypeInfo(componentType->TypeIndex);
예제 #14
0
            protected override VisitStatus BeginContainer <TProperty, TContainer, TValue>(TProperty property, ref TContainer container,
                                                                                          ref TValue value, ref ChangeTracker changeTracker)
            {
                if (typeof(IComponentData).IsAssignableFrom(typeof(TValue)))
                {
                    var index = TypeManager.GetTypeIndex(typeof(TValue));
                    if (!TypeManager.GetTypeInfo(index).IsZeroSized)
                    {
                        Unsafe.Copy(m_EntityManager.GetComponentDataRawRW(m_TargetEntity, index), ref value);
                    }
                }

                if (typeof(ISharedComponentData).IsAssignableFrom(typeof(TValue)))
                {
                    var index = TypeManager.GetTypeIndex(typeof(TValue));
                    m_EntityManager.SetSharedComponentDataBoxed(m_TargetEntity, index, value);
                }

                if (typeof(IDynamicBufferContainer).IsAssignableFrom(typeof(TValue)) &&
                    value is IDynamicBufferContainer buffer)
                {
                    var index         = TypeManager.GetTypeIndex(buffer.ElementType);
                    var componentType = TypeManager.GetTypeInfo(index);

                    var srcBuffer =
                        (BufferHeader *)m_EntityManager.GetComponentDataRawRW(m_SourceEntity, componentType.TypeIndex);
                    var dstBuffer =
                        (BufferHeader *)m_EntityManager.GetComponentDataRawRW(m_TargetEntity, componentType.TypeIndex);

                    dstBuffer->Length = srcBuffer->Length;
                    BufferHeader.EnsureCapacity(dstBuffer, srcBuffer->Length, componentType.ElementSize, 4,
                                                BufferHeader.TrashMode.RetainOldData);

                    // Copy all blittable data
                    UnsafeUtility.MemCpy(BufferHeader.GetElementPointer(dstBuffer),
                                         BufferHeader.GetElementPointer(srcBuffer), componentType.ElementSize * srcBuffer->Length);
                }

                return(VisitStatus.Override);
            }
        internal static NativeArray <NativeView> GetBufferViews(this ArchetypeChunk self, ChunkTypeIndex index, int elementSize, Allocator allocator)
        {
            var typeSize = self.GetTypeSize(index);
            var offset   = self.GetTypeOffset(index);

            var count = self.Count;
            var views = new NativeArray <NativeView>(count, allocator, NativeArrayOptions.UninitializedMemory);

            unsafe
            {
                var ptr = self.m_Chunk->Buffer + offset;

                for (int i = 0; i < count; i++)
                {
                    var buffer = (BufferHeader *)(ptr + i * typeSize);
                    var data   = BufferHeader.GetElementPointer(buffer);

                    views[i] = new NativeView(data, buffer->Length * elementSize);
                }
            }
            return(views);
        }
예제 #16
0
        public override void Write(byte[] buffer, int offset, int count)
        {
            var initialCount = count;

            fixed(byte *src = buffer)
            while (true)
            {
                int capacity = EnsureCapacity();
                int toCopy   = Math.Min(count, capacity);

                MemoryUtils.CopyMemory(src + offset, BufferHeader.Data(_current) + (*_current).Used, toCopy);
                (*_current).Used += toCopy;
                count            -= toCopy;
                if (count == 0)
                {
                    break;
                }
                offset += toCopy;
            }

            _length += initialCount;
        }
예제 #17
0
        protected override void OnUpdate()
        {
            var entityComponentStore            = EntityManager.GetCheckedEntityDataAccess()->EntityComponentStore;
            var globalVersion                   = entityComponentStore->GlobalSystemVersion;
            var animatedAssetReferenceTypeIndex = m_AnimatedAssetReferenceTypeIndex;

            Dependency =
                Entities
                .WithNativeDisableUnsafePtrRestriction(entityComponentStore)
                .WithBurst(FloatMode.Fast)
                .WithAll <ApplyAnimationResultTag>()
                .WithNone <AnimationPPtrBindingRetarget>()
                .ForEach(
                    (in DynamicBuffer <AnimationPPtrBinding> bindings, in TinyAnimationTime animationTime) =>
            {
                var time = animationTime.Value;
                for (int i = 0; i < bindings.Length; ++i)
                {
                    var binding = bindings[i];
                    var result  = (int)KeyframeCurveEvaluator.Evaluate(time, binding.Curve);

                    var source = binding.SourceEntity;
                    entityComponentStore->AssertEntityHasComponent(source, animatedAssetReferenceTypeIndex);

                    var pPtrBindingSourcesBuffer = (BufferHeader *)entityComponentStore->GetComponentDataWithTypeRO(source, animatedAssetReferenceTypeIndex);
                    var pPtrBindingSource        = ((AnimationPPtrBindingSources *)BufferHeader.GetElementPointer(pPtrBindingSourcesBuffer))[result];

                    var typeIndex = binding.TargetComponentTypeIndex;

                    var entity = binding.TargetEntity;

                    entityComponentStore->AssertEntityHasComponent(entity, typeIndex);

                    var targetComponentPtr = entityComponentStore->GetComponentDataWithTypeRW(entity, typeIndex, globalVersion);
                    var targetFieldPtr     = targetComponentPtr + binding.FieldOffset;

                    UnsafeUtility.MemCpy(targetFieldPtr, UnsafeUtility.AddressOf(ref pPtrBindingSource.Value), UnsafeUtility.SizeOf <Entity>());
                }
            }).Schedule(Dependency);
예제 #18
0
        public void CopyFrom(T[] v)
        {
            if (v == null)
            {
                throw new ArgumentNullException(nameof(v));
            }

#if NET_DOTS
            Clear();
            foreach (var d in v)
            {
                Add(d);
            }
#else
            ResizeUninitialized(v.Length);

            GCHandle gcHandle = GCHandle.Alloc((object)v, GCHandleType.Pinned);
            IntPtr   num      = gcHandle.AddrOfPinnedObject();

            UnsafeUtility.MemCpy(BufferHeader.GetElementPointer(m_Buffer),
                                 (void *)num, Length * UnsafeUtility.SizeOf <T>());
            gcHandle.Free();
#endif
        }
예제 #19
0
        static unsafe void WriteChunkData(YamlWriter writer, EntityManager entityManager, Chunk *initialChunk, Archetype *archetype, bool dumpChunkRawData)
        {
            using (writer.WriteCollection(k_ChunkDataCollectionTag))
            {
                using (writer.WriteCollection("Header"))
                {
                    WriteEntity(writer, nameof(Chunk.metaChunkEntity), initialChunk->metaChunkEntity);
                    writer.WriteKeyValue(nameof(Chunk.Capacity), initialChunk->Capacity)
                    .WriteKeyValue(nameof(Chunk.Count), initialChunk->Count);

                    if (dumpChunkRawData)
                    {
                        writer.WriteFormattedBinaryData("RawData", initialChunk, Chunk.kBufferOffset);
                    }
                }

                // First pass to sort by component type
                var entitiesByChunkIndex   = new Dictionary <int, Entity>();
                var componentDataList      = new List <int>();
                var chunkComponentDataList = new List <int>();
                var chunkTypes             = archetype->Types;
                for (int typeI = 0; typeI < archetype->TypesCount; typeI++)
                {
                    var componentType = &chunkTypes[typeI];
                    var type          = TypeManager.GetType(componentType->TypeIndex);
                    var typeInfo      = TypeManager.GetTypeInfo(componentType->TypeIndex);

                    if (componentType->IsChunkComponent)
                    {
                        chunkComponentDataList.Add(typeI);
                    }

                    // Is it a Component Data ?
                    else if (typeof(IComponentData).IsAssignableFrom(type) || typeof(Entity).IsAssignableFrom(type) || typeof(IBufferElementData).IsAssignableFrom(type))
                    {
                        // Ignore Tag Component, no data to dump
                        if (typeInfo.IsZeroSized)
                        {
                            continue;
                        }

                        if (typeof(Entity).IsAssignableFrom(type))
                        {
                            componentDataList.Insert(0, typeI);

                            for (int i = 0; i < initialChunk->Count;)
                            {
                                var entity = (Entity)Marshal.PtrToStructure((IntPtr)initialChunk->Buffer + archetype->SizeOfs[0] * i, type);
                                if (entityManager.Exists(entity))
                                {
                                    entitiesByChunkIndex.Add(i, entity);
                                    i++;
                                }
                            }
                        }
                        else
                        {
                            componentDataList.Add(typeI);
                        }
                    }
                }

                // Parse the Component Data for this chunk and store them
                using (writer.WriteCollection(k_ComponentDataCollectionTag))
                {
                    foreach (var typeI in componentDataList)
                    {
                        var componentTypeInArchetype = &chunkTypes[typeI];
                        var componentType            = TypeManager.GetType(componentTypeInArchetype->TypeIndex);
                        var componentTypeInfo        = TypeManager.GetTypeInfo(componentTypeInArchetype->TypeIndex);
                        var componentExtractedInfo   = TypeDataExtractor.GetTypeExtractedInfo(componentType);

                        using (writer.WriteCollection(k_ComponentDataTag))
                        {
                            writer.WriteInlineMap("info", new[]
                            {
                                new KeyValuePair <object, object>(nameof(Type), componentType.Name),
                                new KeyValuePair <object, object>(nameof(TypeManager.TypeInfo.SizeInChunk), componentTypeInfo.SizeInChunk)
                            });

                            using (writer.WriteCollection("Entities"))
                            {
                                var indexInTypeArray       = ChunkDataUtility.GetIndexInTypeArray(archetype, componentTypeInArchetype->TypeIndex);
                                var componentOffsetInChunk = archetype->Offsets[indexInTypeArray];
                                var componentSize          = archetype->SizeOfs[indexInTypeArray];
                                var componentsBuffer       = initialChunk->Buffer + componentOffsetInChunk;
                                var entityData             = new Dictionary <string, string>();

                                // Dump all entities in this chunk
                                foreach (var kvp in entitiesByChunkIndex)
                                {
                                    var entity = kvp.Value;
                                    entityData.Clear();

                                    // Get the location of the component data
                                    var compData = componentsBuffer + kvp.Key * componentSize;

                                    // If the component we are dumping is a Dynamic Buffer
                                    if (typeof(IBufferElementData).IsAssignableFrom(componentType))
                                    {
                                        var header = (BufferHeader *)compData;
                                        var begin  = BufferHeader.GetElementPointer(header);
                                        var size   = Marshal.SizeOf(componentType);

                                        using (writer.WriteCollection(entity.ToString()))
                                        {
                                            for (var it = 0; it < header->Length; it++)
                                            {
                                                var item = begin + (size * it);
                                                entityData.Clear();

                                                // Dump each field of the current entity's component data
                                                foreach (var componentFieldInfo in componentExtractedInfo.Fields)
                                                {
                                                    var compDataObject = Marshal.PtrToStructure((IntPtr)item + componentFieldInfo.Offset, componentFieldInfo.Type);
                                                    entityData.Add(componentFieldInfo.Name, compDataObject.ToString());
                                                }
                                                writer.WriteInlineMap($"{it:0000}", entityData);
                                            }
                                        }
                                    }

                                    // If it's a Component Data
                                    else
                                    {
                                        // Dump each field of the current entity's component data
                                        foreach (var componentFieldInfo in componentExtractedInfo.Fields)
                                        {
                                            var compDataObject = Marshal.PtrToStructure((IntPtr)compData + componentFieldInfo.Offset, componentFieldInfo.Type);
                                            entityData.Add(componentFieldInfo.Name, compDataObject.ToString());
                                        }
                                        writer.WriteInlineMap(entity.ToString(), entityData);
                                    }
                                }
                                if (dumpChunkRawData)
                                {
                                    var csize = EntityComponentStore.GetComponentArraySize(componentSize, archetype->ChunkCapacity);
                                    writer.WriteFormattedBinaryData("RawData", componentsBuffer, csize, componentOffsetInChunk + Chunk.kBufferOffset);
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #20
0
        public static unsafe void SerializeWorld(EntityManager entityManager, BinaryWriter writer, out int[] sharedComponentsToSerialize, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapInfos)
        {
            writer.Write(CurrentFileFormatVersion);
            var archetypeManager = entityManager.ArchetypeManager;

            Dictionary <EntityArchetype, int> archetypeToIndex;

            EntityArchetype[] archetypeArray;
            GetAllArchetypes(archetypeManager, out archetypeToIndex, out archetypeArray);

            var typeindices = new HashSet <int>();

            foreach (var archetype in archetypeArray)
            {
                for (int iType = 0; iType < archetype.Archetype->TypesCount; ++iType)
                {
                    typeindices.Add(archetype.Archetype->Types[iType].TypeIndex & TypeManager.ClearFlagsMask);
                }
            }

            var typeArray = typeindices.Select(index =>
            {
                var type = TypeManager.GetType(index);
                var name = TypeManager.GetType(index).AssemblyQualifiedName;
                var hash = TypeManager.GetTypeInfo(index).StableTypeHash;
                return(new
                {
                    index,
                    type,
                    name,
                    hash,
                    utf8Name = Encoding.UTF8.GetBytes(name)
                });
            }).OrderBy(t => t.name).ToArray();

            int typeNameBufferSize = typeArray.Sum(t => t.utf8Name.Length + 1);

            writer.Write(typeArray.Length);
            foreach (var n in typeArray)
            {
                writer.Write(n.hash);
            }

            writer.Write(typeNameBufferSize);
            foreach (var n in typeArray)
            {
                writer.Write(n.utf8Name);
                writer.Write((byte)0);
            }

            var typeIndexMap = new Dictionary <int, int>();

            for (int i = 0; i < typeArray.Length; ++i)
            {
                typeIndexMap[typeArray[i].index] = i;
            }

            WriteArchetypes(writer, archetypeArray, typeIndexMap);
            var sharedComponentMapping = GatherSharedComponents(archetypeArray, out var sharedComponentArraysTotalCount);
            var sharedComponentArrays  = new NativeArray <int>(sharedComponentArraysTotalCount, Allocator.Temp);

            FillSharedComponentArrays(sharedComponentArrays, archetypeArray, sharedComponentMapping);
            writer.Write(sharedComponentArrays.Length);
            writer.WriteArray(sharedComponentArrays);
            sharedComponentArrays.Dispose();

            //TODO: ensure chunks are defragged?

            var bufferPatches   = new NativeList <BufferPatchRecord>(128, Allocator.Temp);
            var totalChunkCount = GenerateRemapInfo(entityManager, archetypeArray, entityRemapInfos);

            writer.Write(totalChunkCount);

            GatherAllUsedBlobAssets(archetypeArray, out var blobAssetRefs, out var blobAssets);

            var blobAssetOffsets   = new NativeArray <int>(blobAssets.Length, Allocator.Temp);
            int totalBlobAssetSize = 0;

            int Align16(int x) => (x + 15) & ~15;

            for (int i = 0; i < blobAssets.Length; ++i)
            {
                totalBlobAssetSize += sizeof(BlobAssetHeader);
                blobAssetOffsets[i] = totalBlobAssetSize;
                totalBlobAssetSize += Align16(blobAssets[i].header->Length);
            }

            writer.Write(totalBlobAssetSize);

            var zeroBytes = int4.zero;

            for (int i = 0; i < blobAssets.Length; ++i)
            {
                var             blobAssetLength = blobAssets[i].header->Length;
                BlobAssetHeader header          = new BlobAssetHeader
                {
                    ValidationPtr = null, Allocator = Allocator.None, Length = Align16(blobAssetLength)
                };
                writer.WriteBytes(&header, sizeof(BlobAssetHeader));
                writer.WriteBytes(blobAssets[i].header + 1, blobAssetLength);
                writer.WriteBytes(&zeroBytes, header.Length - blobAssetLength);
            }

            var tempChunk = (Chunk *)UnsafeUtility.Malloc(Chunk.kChunkSize, 16, Allocator.Temp);

            for (int archetypeIndex = 0; archetypeIndex < archetypeArray.Length; ++archetypeIndex)
            {
                var archetype = archetypeArray[archetypeIndex].Archetype;
                for (var ci = 0; ci < archetype->Chunks.Count; ++ci)
                {
                    var chunk = archetype->Chunks.p[ci];
                    bufferPatches.Clear();

                    UnsafeUtility.MemCpy(tempChunk, chunk, Chunk.kChunkSize);
                    tempChunk->metaChunkEntity = EntityRemapUtility.RemapEntity(ref entityRemapInfos, tempChunk->metaChunkEntity);

                    // Prevent patching from touching buffers allocated memory
                    BufferHeader.PatchAfterCloningChunk(tempChunk);

                    byte *tempChunkBuffer = tempChunk->Buffer;
                    EntityRemapUtility.PatchEntities(archetype->ScalarEntityPatches, archetype->ScalarEntityPatchCount, archetype->BufferEntityPatches, archetype->BufferEntityPatchCount, tempChunkBuffer, tempChunk->Count, ref entityRemapInfos);
                    if (archetype->ContainsBlobAssetRefs)
                    {
                        PatchBlobAssetsInChunkBeforeSave(tempChunk, chunk, blobAssetOffsets, blobAssetRefs);
                    }

                    FillPatchRecordsForChunk(chunk, bufferPatches);

                    ClearChunkHeaderComponents(tempChunk);
                    ChunkDataUtility.MemsetUnusedChunkData(tempChunk, 0);
                    tempChunk->Archetype = (Archetype *)archetypeIndex;

                    if (archetype->NumManagedArrays != 0)
                    {
                        throw new ArgumentException("Serialization of GameObject components is not supported for pure entity scenes");
                    }

                    writer.WriteBytes(tempChunk, Chunk.kChunkSize);

                    writer.Write(bufferPatches.Length);

                    if (bufferPatches.Length > 0)
                    {
                        writer.WriteList(bufferPatches);

                        // Write heap backed data for each required patch.
                        // TODO: PERF: Investigate static-only deserialization could manage one block and mark in pointers somehow that they are not indiviual
                        for (int i = 0; i < bufferPatches.Length; ++i)
                        {
                            var patch  = bufferPatches[i];
                            var header = (BufferHeader *)OffsetFromPointer(tempChunk->Buffer, patch.ChunkOffset);
                            writer.WriteBytes(header->Pointer, patch.AllocSizeBytes);
                            BufferHeader.Destroy(header);
                        }
                    }
                }
            }

            blobAssetRefs.Dispose();
            blobAssets.Dispose();

            bufferPatches.Dispose();
            UnsafeUtility.Free(tempChunk, Allocator.Temp);

            sharedComponentsToSerialize = new int[sharedComponentMapping.Count - 1];

            foreach (var i in sharedComponentMapping)
            {
                if (i.Key != 0)
                {
                    sharedComponentsToSerialize[i.Value - 1] = i.Key;
                }
            }
        }
        protected override unsafe void OnUpdate()
        {
            using (var entityGuidHashMap = new NativeHashMap <EntityGuid, Entity>(m_EntityGuidQuery.CalculateLength(), Allocator.TempJob))
            {
                var entityType = EntityManager.GetArchetypeChunkEntityType();

                new BuildEntityGuidHashMapJob
                {
                    Entity         = entityType,
                    EntityGuidType = GetArchetypeChunkComponentType <EntityGuid>(true),
                    HashMap        = entityGuidHashMap.ToConcurrent()
                }.Schedule(m_EntityGuidQuery).Complete();

                using (var chunks = m_EntityReferenceRemapQuery.CreateArchetypeChunkArray(Allocator.TempJob))
                {
                    var entityReferenceRemapType = GetArchetypeChunkBufferType <EntityReferenceRemap>(true);

                    // Run through all chunks
                    for (var chunkIndex = 0; chunkIndex < chunks.Length; chunkIndex++)
                    {
                        var entities = chunks[chunkIndex].GetNativeArray(entityType);
                        var entityReferenceRemaps = chunks[chunkIndex].GetBufferAccessor(entityReferenceRemapType);

                        // Run through each entity of the chunk
                        for (var entityIndex = 0; entityIndex < entityReferenceRemaps.Length; entityIndex++)
                        {
                            var entity = entities[entityIndex];
                            var entityReferenceRemap = entityReferenceRemaps[entityIndex];

                            // Run through each remap for the entity
                            for (var remapIndex = 0; remapIndex < entityReferenceRemap.Length; remapIndex++)
                            {
                                var remap = entityReferenceRemap[remapIndex];

                                // Find the live entity which matches this guid
                                if (!entityGuidHashMap.TryGetValue(remap.Guid, out var target))
                                {
                                    continue;
                                }

                                // Resolve the type
                                var typeIndex = TypeManager.GetTypeIndexFromStableTypeHash(remap.TypeHash);

                                if (TypeManager.IsSharedComponent(typeIndex))
                                {
                                    // @TODO get this working in the NET_DOTS runtime

                                    /*
                                     * var type = TypeManager.GetType(typeIndex);
                                     *
                                     * // ASSUMPTION: Shared component data is blittable
                                     * if (!UnsafeUtility.IsBlittable(type))
                                     * {
                                     *  throw new Exception($"Trying to remap entity reference for a non blittable shared component Type=[{type.FullName}]");
                                     * }
                                     *
                                     * // Patch shared component reference
                                     * var sharedComponent = EntityManager.GetSharedComponentData(entity, typeIndex);
                                     *(Entity*) ((byte*) Unsafe.AsPointer(ref sharedComponent) + remap.Offset) = target;
                                     * EntityManager.SetSharedComponentDataBoxed(entity, typeIndex, sharedComponent);
                                     */
                                    continue;
                                }

                                if (TypeManager.IsBuffer(typeIndex))
                                {
                                    // Patch buffer component reference
                                    var ptr = (BufferHeader *)EntityManager.GetComponentDataRawRW(entity, typeIndex);
                                    *(Entity *)(BufferHeader.GetElementPointer(ptr) + remap.Offset) = target;
                                    continue;
                                }

                                // Patch standard component reference
                                *(Entity *)((byte *)EntityManager.GetComponentDataRawRW(entity, typeIndex) + remap.Offset) = target;
                            }
                        }
                    }
                }
            }
        }
        public static unsafe (IntPtr ptr, int length) GetBufferArrayRawRO(this Entity entity, EntityManager em, int typeIndex)
        {
            var header = (BufferHeader *)em.GetComponentDataRawRO(entity, typeIndex);

            return(new IntPtr(BufferHeader.GetElementPointer(header)), header->Length);
        }
예제 #23
0
 public static byte* Data(BufferHeader* header)
 {
     return ((byte*)header) + BufferHeader.BufferHeaderSize;
 }
예제 #24
0
        private static unsafe Entity CopyEntity(Entity srcEntity, World srcWorld, World dstWorld)
        {
            Assert.AreNotEqual(Entity.Null, srcEntity);

            using (var entityReferences = new NativeList <EntityReferenceRemap>(8, Allocator.Temp))
                using (var componentTypes = srcWorld.EntityManager.GetComponentTypes(srcEntity))
                {
                    var archetype = dstWorld.EntityManager.CreateArchetype(componentTypes.ToArray());
                    var dstEntity = dstWorld.EntityManager.CreateEntity(archetype);

                    if (componentTypes.Any(x => x.HasEntityReferences) && !dstWorld.EntityManager.HasComponent <EntityReferenceRemap>(dstEntity))
                    {
                        dstWorld.EntityManager.AddBuffer <EntityReferenceRemap>(dstEntity);
                    }

                    foreach (var componentType in componentTypes)
                    {
                        var typeInfo = TypeManager.GetTypeInfo(componentType.TypeIndex);

                        if (typeInfo.SizeInChunk == 0)
                        {
                            continue;
                        }

                        if (componentType.IsSharedComponent)
                        {
                            // @TODO For now we assume that all shared component data is blittable
                            var srcComponent = srcWorld.EntityManager.GetSharedComponentData(srcEntity, componentType.TypeIndex);

                            var ptr = Unsafe.AsPointer(ref srcComponent);

                            // Pull out all references into the `entityReferences` list
                            ExtractEntityReferences(entityReferences, typeInfo, srcWorld.EntityManager, ptr);

                            // Zero out entity references
                            ClearEntityReferences(typeInfo, ptr);

                            dstWorld.EntityManager.SetSharedComponentDataBoxed(dstEntity, componentType.TypeIndex, srcComponent);
                            continue;
                        }

                        if (componentType.IsBuffer)
                        {
                            var srcBuffer = (BufferHeader *)srcWorld.EntityManager.GetComponentDataRawRW(srcEntity, componentType.TypeIndex);
                            var dstBuffer = (BufferHeader *)dstWorld.EntityManager.GetComponentDataRawRW(dstEntity, componentType.TypeIndex);

                            dstBuffer->Length = srcBuffer->Length;
                            BufferHeader.EnsureCapacity(dstBuffer, srcBuffer->Length, typeInfo.ElementSize, 4, BufferHeader.TrashMode.RetainOldData);

                            // Copy all blittable data
                            UnsafeUtility.MemCpy(BufferHeader.GetElementPointer(dstBuffer), BufferHeader.GetElementPointer(srcBuffer), typeInfo.ElementSize * srcBuffer->Length);

                            for (var i = 0; i < srcBuffer->Length; i++)
                            {
                                var baseOffset = i * typeInfo.ElementSize;

                                // Pull out all references into the `entityReferences` list
                                ExtractEntityReferences(entityReferences, typeInfo, srcWorld.EntityManager, BufferHeader.GetElementPointer(dstBuffer), baseOffset);

                                // Zero out entity references
                                ClearEntityReferences(typeInfo, BufferHeader.GetElementPointer(dstBuffer), baseOffset);
                            }

                            continue;
                        }

                        var componentData = srcWorld.EntityManager.GetComponentDataRawRW(srcEntity, componentType.TypeIndex);

                        // Copy all blittable data
                        dstWorld.EntityManager.SetComponentDataRaw(dstEntity, componentType.TypeIndex, componentData, typeInfo.SizeInChunk);

                        // Pull out all references into the `entityReferences` list
                        ExtractEntityReferences(entityReferences, typeInfo, srcWorld.EntityManager, componentData);

                        // Zero out entity references
                        ClearEntityReferences(typeInfo, dstWorld.EntityManager.GetComponentDataRawRW(dstEntity, componentType.TypeIndex));
                    }

                    if (entityReferences.Length > 0)
                    {
                        dstWorld.EntityManager.GetBuffer <EntityReferenceRemap>(dstEntity).AddRange(entityReferences);
                    }

                    return(dstEntity);
                }
        }
예제 #25
0
 public void EnsureCapacity(int length)
 {
     BufferHeader.EnsureCapacity(m_Buffer, length, UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), BufferHeader.TrashMode.RetainOldData, false, 0);
 }
예제 #26
0
        //
        // Code to read the log files generated at runtime
        //
        private void ReadLogFile(IProgressListener progress)
        {
            BufferHeader bheader;
            long         start_position = reader.Position;
            long         last_pct       = 0;

            if (header == null)
            {
                header = Header.Read(reader);
            }
            if (header == null)
            {
                return;
            }

            while (!reader.IsEof)
            {
                // We check if we must cancel before reading more data (and after processing all the data we've read).
                // This way we don't cancel in the middle of event processing (since we store data at class level
                // we may end up with corruption the next time we read the same buffer otherwise).
                if (progress != null)
                {
                    if (progress.Cancelled)
                    {
                        return;
                    }

                    long pct = (reader.Position - start_position) * 100 / (reader.Length - start_position);
                    if (pct != last_pct)
                    {
                        last_pct = pct;
                        progress.ReportProgress("Loading profiler log", pct / 100.0f);
                    }
                }

                bheader = BufferHeader.Read(reader);
                if (bheader == null)
                {
                    // entire buffer isn't available (yet)
                    return;
                }

                //Console.WriteLine ("BUFFER ThreadId: " + bheader.ThreadId + " Len:" + bheader.Length);
                currentObjBase = bheader.ObjBase;
                currentPtrBase = bheader.PtrBase;

                while (!reader.IsBufferEmpty)
                {
                    MetadataEvent me;
                    HeapEvent     he;
                    GcEvent       ge;

                    Event e = Event.Read(reader);
                    //Console.WriteLine ("Event: {0}", e);
                    if ((me = e as MetadataEvent) != null)
                    {
                        ReadLogFileChunk_Type(me);
                    }
                    else if ((he = e as HeapEvent) != null)
                    {
                        ReadLogFileChunk_Object(he);
                    }
                    else if ((ge = e as GcEvent) != null)
                    {
                        ReadGcEvent(ge);
                    }
                }
            }
        }
예제 #27
0
        public static unsafe void SerializeWorld(EntityManager entityManager, BinaryWriter writer, out int[] sharedComponentsToSerialize, NativeArray <EntityRemapUtility.EntityRemapInfo> entityRemapInfos)
        {
            writer.Write(CurrentFileFormatVersion);
            var entityComponentStore = entityManager.EntityComponentStore;

            NativeHashMap <EntityArchetype, int> archetypeToIndex;

            EntityArchetype[] archetypeArray;
            GetAllArchetypes(entityComponentStore, out archetypeToIndex, out archetypeArray);

            var typeHashes = new NativeHashMap <ulong, int>(1024, Allocator.Temp);

            foreach (var archetype in archetypeArray)
            {
                for (int iType = 0; iType < archetype.Archetype->TypesCount; ++iType)
                {
                    var typeIndex = archetype.Archetype->Types[iType].TypeIndex;
                    var ti        = TypeManager.GetTypeInfo(typeIndex);
                    var hash      = ti.StableTypeHash;
                    typeHashes.TryAdd(hash, 0);
                }
            }
            var typeHashSet = typeHashes.GetKeyArray(Allocator.Temp);

            writer.Write(typeHashSet.Length);
            foreach (ulong hash in typeHashSet)
            {
                writer.Write(hash);
            }

            var typeHashToIndexMap = new NativeHashMap <ulong, int>(typeHashSet.Length, Allocator.Temp);

            for (int i = 0; i < typeHashes.Length; ++i)
            {
                typeHashToIndexMap.TryAdd(typeHashSet[i], i);
            }

            WriteArchetypes(writer, archetypeArray, typeHashToIndexMap);
            var sharedComponentMapping = GatherSharedComponents(archetypeArray, out var sharedComponentArraysTotalCount);
            var sharedComponentArrays  = new NativeArray <int>(sharedComponentArraysTotalCount, Allocator.Temp);

            FillSharedComponentArrays(sharedComponentArrays, archetypeArray, sharedComponentMapping);
            writer.Write(sharedComponentArrays.Length);
            writer.WriteArray(sharedComponentArrays);
            sharedComponentArrays.Dispose();

            //TODO: ensure chunks are defragged?

            var bufferPatches   = new NativeList <BufferPatchRecord>(128, Allocator.Temp);
            var totalChunkCount = GenerateRemapInfo(entityManager, archetypeArray, entityRemapInfos);

            writer.Write(totalChunkCount);

            GatherAllUsedBlobAssets(archetypeArray, out var blobAssetRefs, out var blobAssets);

            var blobAssetOffsets   = new NativeArray <int>(blobAssets.Length, Allocator.Temp);
            int totalBlobAssetSize = 0;

            int Align16(int x) => (x + 15) & ~15;

            for (int i = 0; i < blobAssets.Length; ++i)
            {
                totalBlobAssetSize += sizeof(BlobAssetHeader);
                blobAssetOffsets[i] = totalBlobAssetSize;
                totalBlobAssetSize += Align16(blobAssets[i].header->Length);
            }

            writer.Write(totalBlobAssetSize);

            var zeroBytes = int4.zero;

            for (int i = 0; i < blobAssets.Length; ++i)
            {
                var             blobAssetLength = blobAssets[i].header->Length;
                BlobAssetHeader header          = new BlobAssetHeader
                {
                    ValidationPtr = null, Allocator = Allocator.None, Length = Align16(blobAssetLength)
                };
                writer.WriteBytes(&header, sizeof(BlobAssetHeader));
                writer.WriteBytes(blobAssets[i].header + 1, blobAssetLength);
                writer.WriteBytes(&zeroBytes, header.Length - blobAssetLength);
            }

            var tempChunk = (Chunk *)UnsafeUtility.Malloc(Chunk.kChunkSize, 16, Allocator.Temp);

            for (int archetypeIndex = 0; archetypeIndex < archetypeArray.Length; ++archetypeIndex)
            {
                var archetype = archetypeArray[archetypeIndex].Archetype;
                for (var ci = 0; ci < archetype->Chunks.Count; ++ci)
                {
                    var chunk = archetype->Chunks.p[ci];
                    bufferPatches.Clear();

                    UnsafeUtility.MemCpy(tempChunk, chunk, Chunk.kChunkSize);
                    tempChunk->metaChunkEntity = EntityRemapUtility.RemapEntity(ref entityRemapInfos, tempChunk->metaChunkEntity);

                    // Prevent patching from touching buffers allocated memory
                    BufferHeader.PatchAfterCloningChunk(tempChunk);

                    byte *tempChunkBuffer = tempChunk->Buffer;
                    EntityRemapUtility.PatchEntities(archetype->ScalarEntityPatches, archetype->ScalarEntityPatchCount, archetype->BufferEntityPatches, archetype->BufferEntityPatchCount, tempChunkBuffer, tempChunk->Count, ref entityRemapInfos);
                    if (archetype->ContainsBlobAssetRefs)
                    {
                        PatchBlobAssetsInChunkBeforeSave(tempChunk, chunk, blobAssetOffsets, blobAssetRefs);
                    }

                    FillPatchRecordsForChunk(chunk, bufferPatches);

                    ClearChunkHeaderComponents(tempChunk);
                    ChunkDataUtility.MemsetUnusedChunkData(tempChunk, 0);
                    tempChunk->Archetype = (Archetype *)archetypeIndex;

                    if (archetype->NumManagedArrays != 0)
                    {
                        throw new ArgumentException("Serialization of GameObject components is not supported for pure entity scenes");
                    }

                    writer.WriteBytes(tempChunk, Chunk.kChunkSize);

                    writer.Write(bufferPatches.Length);

                    if (bufferPatches.Length > 0)
                    {
                        writer.WriteList(bufferPatches);

                        // Write heap backed data for each required patch.
                        // TODO: PERF: Investigate static-only deserialization could manage one block and mark in pointers somehow that they are not indiviual
                        for (int i = 0; i < bufferPatches.Length; ++i)
                        {
                            var patch  = bufferPatches[i];
                            var header = (BufferHeader *)OffsetFromPointer(tempChunk->Buffer, patch.ChunkOffset);
                            writer.WriteBytes(header->Pointer, patch.AllocSizeBytes);
                            BufferHeader.Destroy(header);
                        }
                    }
                }
            }

            blobAssetRefs.Dispose();
            blobAssets.Dispose();

            bufferPatches.Dispose();
            UnsafeUtility.Free(tempChunk, Allocator.Temp);

            sharedComponentsToSerialize = new int[sharedComponentMapping.Length - 1];

            using (var keyArray = sharedComponentMapping.GetKeyArray(Allocator.Temp))
                foreach (var key in keyArray)
                {
                    if (key == 0)
                    {
                        continue;
                    }

                    if (sharedComponentMapping.TryGetValue(key, out var val))
                    {
                        sharedComponentsToSerialize[val - 1] = key;
                    }
                }

            archetypeToIndex.Dispose();
            typeHashes.Dispose();
            typeHashSet.Dispose();
            typeHashToIndexMap.Dispose();
        }
예제 #28
0
 public void *GetUnsafeReadOnlyPtr()
 {
     return(BufferHeader.GetElementPointer(m_Buffer));
 }
        public static unsafe (IntPtr ptr, int length) GetBufferArrayRawRO(this ArchetypeChunk chunk, int chunkIndex, int typeIndex)
        {
            var header = (BufferHeader *)GetComponentDataWithTypeRO(chunk, chunkIndex, typeIndex);

            return(new IntPtr(BufferHeader.GetElementPointer(header)), header->Length);
        }
예제 #30
0
            public void Dealloc(BufferHeader* header)
            {
                var rightThread = Thread.CurrentThread.ManagedThreadId == _threadID;
                do
                {
                    var next = (*header).Next;

                    if (rightThread && _pool.Count < _capacity && _pageSize == (*header).Size)
                    {
                        _pool.Enqueue((IntPtr)header);
                        (*header).Used = 0;
                        (*header).Next = null;
                    }
                    else
                        Marshal.FreeHGlobal((IntPtr)header);

                    header = next;
                } while (header != null);
            }