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) )); }
public void CopyFrom(DynamicBufferUnsafe <T> v) { ResizeUninitialized(v.Length); UnsafeUtility.MemCpy(BufferHeader.GetElementPointer(m_Buffer), BufferHeader.GetElementPointer(v.m_Buffer), Length * UnsafeUtility.SizeOf <T>()); }
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) )); }
public BufferResult FirstPage() { return(new BufferResult() { Length = (*_first).Used, Buffer = (IntPtr)BufferHeader.Data(_first) }); }
public override void WriteByte(byte value) { EnsureCapacity(); var data = BufferHeader.Data(_current) + (*_current).Used; (*data) = value; ++(*_current).Used; }
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); }
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; }
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; }
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); } }
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) }); }
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); }
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); }
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);
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); }
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; }
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);
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 }
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); } } } } } } }
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); }
public static byte* Data(BufferHeader* header) { return ((byte*)header) + BufferHeader.BufferHeaderSize; }
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); } }
public void EnsureCapacity(int length) { BufferHeader.EnsureCapacity(m_Buffer, length, UnsafeUtility.SizeOf <T>(), UnsafeUtility.AlignOf <T>(), BufferHeader.TrashMode.RetainOldData, false, 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); } } } }
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(); }
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); }
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); }