diff --git a/src/EcsAspect.cs b/src/EcsAspect.cs index 5d5aa29..da2043b 100644 --- a/src/EcsAspect.cs +++ b/src/EcsAspect.cs @@ -260,7 +260,8 @@ namespace DCFApixels.DragonECS } public EcsSpan CopyToSpan(ref int[] array) { - return iterator.CopyToSpan(ref array); + int count = CopyTo(ref array); + return new EcsSpan(worldID, array, count); } #endregion diff --git a/src/EcsMask.cs b/src/EcsMask.cs index 8d135dc..34d8671 100644 --- a/src/EcsMask.cs +++ b/src/EcsMask.cs @@ -11,6 +11,7 @@ using Unity.IL2CPP.CompilerServices; namespace DCFApixels.DragonECS { + using static EcsMaskIteratorUtility; public interface IEcsComponentMask { EcsMask ToMask(EcsWorld world); @@ -283,7 +284,7 @@ namespace DCFApixels.DragonECS do { EcsMaskChunck bitJ = EcsMaskChunck.FromID(sortedArray[i]); - if (bitJ.chankIndex != chankIndexX) + if (bitJ.chunkIndex != chankIndexX) { break; } @@ -554,7 +555,7 @@ namespace DCFApixels.DragonECS #endregion - #region AbstractMask + #region StaticMask public static EcsMask FromStatic(EcsWorld world, EcsStaticMask abstractMask) { return world.Get().ConvertFromAbstract(abstractMask); @@ -849,11 +850,11 @@ namespace DCFApixels.DragonECS internal const int DIV_SHIFT = 5; internal const int MOD_MASK = BITS - 1; - public readonly int chankIndex; + public readonly int chunkIndex; public readonly int mask; public EcsMaskChunck(int chankIndex, int mask) { - this.chankIndex = chankIndex; + this.chunkIndex = chankIndex; this.mask = mask; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -863,7 +864,7 @@ namespace DCFApixels.DragonECS } public override string ToString() { - return $"mask({chankIndex}, {mask}, {BitsUtility.CountBits(mask)})"; + return $"mask({chunkIndex}, {mask}, {BitsUtility.CountBits(mask)})"; } internal class DebuggerProxy { @@ -873,7 +874,7 @@ namespace DCFApixels.DragonECS public string bits; public DebuggerProxy(EcsMaskChunck maskbits) { - chunk = maskbits.chankIndex; + chunk = maskbits.chunkIndex; mask = (uint)maskbits.mask; BitsUtility.GetBitNumbersNoAlloc(mask, ref values); for (int i = 0; i < values.Length; i++) @@ -893,103 +894,75 @@ namespace DCFApixels.DragonECS #endif public class EcsMaskIterator { - #region CountStructComparers - private readonly struct IncCountComparer : IStructComparer - { - public readonly EcsWorld.PoolSlot[] counts; - public IncCountComparer(EcsWorld.PoolSlot[] counts) - { - this.counts = counts; - } - public int Compare(int a, int b) - { - return counts[a].count - counts[b].count; - } - } - private readonly struct ExcCountComparer : IStructComparer - { - public readonly EcsWorld.PoolSlot[] counts; - public ExcCountComparer(EcsWorld.PoolSlot[] counts) - { - this.counts = counts; - } - public int Compare(int a, int b) - { - return counts[b].count - counts[a].count; - } - } - #endregion + public readonly EcsWorld World; + public readonly EcsMask Mask; - internal EcsWorld _source; - internal EcsMask _mask; + private readonly UnsafeArray _sortIncBuffer; + private readonly UnsafeArray _sortExcBuffer; + private readonly UnsafeArray _sortIncChunckBuffer; + private readonly UnsafeArray _sortExcChunckBuffer; - private UnsafeArray _sortIncBuffer; - private UnsafeArray _sortExcBuffer; - private UnsafeArray _sortIncChunckBuffer; - private UnsafeArray _sortExcChunckBuffer; + private readonly bool _isOnlyInc; - #region Constructors + #region Constructors/Finalizator public unsafe EcsMaskIterator(EcsWorld source, EcsMask mask) { - _source = source; - _mask = mask; - - _sortIncBuffer = new UnsafeArray(_mask._inc.Length); - _sortExcBuffer = new UnsafeArray(_mask._exc.Length); - _sortIncChunckBuffer = new UnsafeArray(_mask._incChunckMasks.Length); - _sortExcChunckBuffer = new UnsafeArray(_mask._excChunckMasks.Length); - - for (int i = 0; i < _sortIncBuffer.Length; i++) - { - _sortIncBuffer.ptr[i] = _mask._inc[i]; - } - for (int i = 0; i < _sortExcBuffer.Length; i++) - { - _sortExcBuffer.ptr[i] = _mask._exc[i]; - } - - for (int i = 0; i < _sortIncChunckBuffer.Length; i++) - { - _sortIncChunckBuffer.ptr[i] = _mask._incChunckMasks[i]; - } - for (int i = 0; i < _sortExcChunckBuffer.Length; i++) - { - _sortExcChunckBuffer.ptr[i] = _mask._excChunckMasks[i]; - } + World = source; + Mask = mask; + _sortIncBuffer = UnsafeArray.FromArray(mask._inc); + _sortExcBuffer = UnsafeArray.FromArray(mask._exc); + _sortIncChunckBuffer = UnsafeArray.FromArray(mask._incChunckMasks); + _sortExcChunckBuffer = UnsafeArray.FromArray(mask._excChunckMasks); + _isOnlyInc = _sortExcBuffer.Length <= 0; } - #endregion - - #region Finalizator unsafe ~EcsMaskIterator() { - _sortIncBuffer.Dispose(); - _sortExcBuffer.Dispose(); - _sortIncChunckBuffer.Dispose(); - _sortExcChunckBuffer.Dispose(); + _sortIncBuffer.ReadonlyDispose(); + _sortExcBuffer.ReadonlyDispose(); + _sortIncChunckBuffer.ReadonlyDispose(); + _sortExcChunckBuffer.ReadonlyDispose(); } #endregion - #region Properties - public EcsWorld World + + #region IterateTo + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void IterateTo(EcsSpan source, EcsGroup group) { - get { return _source; } + if (_isOnlyInc) + { + IterateOnlyInc(source).CopyTo(group); + } + else + { + Iterate(source).CopyTo(group); + } } - public EcsMask Mask + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int IterateTo(EcsSpan source, ref int[] array) { - get { return _mask; } + if (_isOnlyInc) + { + return IterateOnlyInc(source).CopyTo(ref array); + } + else + { + return Iterate(source).CopyTo(ref array); + } } #endregion - #region Enumerable - public Enumerable Iterate(EcsSpan span) - { - return new Enumerable(this, span); - } + #region Iterate/Enumerable + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerable Iterate(EcsSpan span) { return new Enumerable(this, span); } +#if ENABLE_IL2CPP + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif public readonly ref struct Enumerable { private readonly EcsMaskIterator _iterator; private readonly EcsSpan _span; - public Enumerable(EcsMaskIterator iterator, EcsSpan span) { _iterator = iterator; @@ -997,6 +970,7 @@ namespace DCFApixels.DragonECS } #region CopyTo + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(EcsGroup group) { group.Clear(); @@ -1006,6 +980,7 @@ namespace DCFApixels.DragonECS group.AddUnchecked(enumerator.Current); } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public int CopyTo(ref int[] array) { int count = 0; @@ -1020,50 +995,41 @@ namespace DCFApixels.DragonECS } return count; } - public EcsSpan CopyToSpan(ref int[] array) - { - int count = CopyTo(ref array); - return new EcsSpan(_iterator.World.id, array, count); - } #endregion #region Other - public override string ToString() + public List ToList() { List ints = new List(); - foreach (var e in this) - { - ints.Add(e); - } - return CollectionUtility.EntitiesToString(ints, "it"); + foreach (var e in this) { ints.Add(e); } + return ints; } + public override string ToString() { return CollectionUtility.EntitiesToString(ToList(), "it"); } #endregion #region Enumerator [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { return new Enumerator(_span, _iterator); } - +#if ENABLE_IL2CPP + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif public unsafe ref struct Enumerator { private ReadOnlySpan.Enumerator _span; + + private readonly UnsafeArray _sortIncChunckBuffer; + private readonly UnsafeArray _sortExcChunckBuffer; + private readonly int[] _entityComponentMasks; - - [ThreadStatic] - private static EcsMaskChunck* _preSortedIncBuffer; - [ThreadStatic] - private static EcsMaskChunck* _preSortedExcBuffer; - - private UnsafeArray _sortIncChunckBuffer; - private UnsafeArray _sortExcChunckBuffer; - private readonly int _entityComponentMaskLengthBitShift; public unsafe Enumerator(EcsSpan span, EcsMaskIterator iterator) { - _entityComponentMasks = iterator.World._entityComponentMasks; _sortIncChunckBuffer = iterator._sortIncChunckBuffer; _sortExcChunckBuffer = iterator._sortExcChunckBuffer; + _entityComponentMasks = iterator.World._entityComponentMasks; _entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift; if (iterator.Mask.IsBroken) @@ -1076,74 +1042,36 @@ namespace DCFApixels.DragonECS UnsafeArray _sortIncBuffer = iterator._sortIncBuffer; UnsafeArray _sortExcBuffer = iterator._sortExcBuffer; EcsWorld.PoolSlot[] counts = iterator.World._poolSlots; + int max = _sortIncBuffer.Length > _sortExcBuffer.Length ? _sortIncBuffer.Length : _sortExcBuffer.Length; - if (_preSortedIncBuffer == null) + EcsMaskChunck* preSortingBuffer; + if (max > STACK_BUFFER_THRESHOLD) { - _preSortedIncBuffer = UnmanagedArrayUtility.New(256); - _preSortedExcBuffer = UnmanagedArrayUtility.New(256); + preSortingBuffer = TempBuffer.Get(max); + } + else + { + EcsMaskChunck* ptr = stackalloc EcsMaskChunck[max]; + preSortingBuffer = ptr; } if (_sortIncChunckBuffer.Length > 1) { - IncCountComparer incComparer = new IncCountComparer(counts); - UnsafeArraySortHalperX.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref incComparer); - for (int i = 0; i < _sortIncBuffer.Length; i++) - { - _preSortedIncBuffer[i] = EcsMaskChunck.FromID(_sortIncBuffer.ptr[i]); - } - for (int i = 0, ii = 0; ii < _sortIncChunckBuffer.Length; ii++) - { - EcsMaskChunck chunkX = _preSortedIncBuffer[i]; - int chankIndexX = chunkX.chankIndex; - int maskX = chunkX.mask; - - for (int j = i + 1; j < _sortIncBuffer.Length; j++) - { - if (_preSortedIncBuffer[j].chankIndex == chankIndexX) - { - maskX |= _preSortedIncBuffer[j].mask; - } - } - _sortIncChunckBuffer.ptr[ii] = new EcsMaskChunck(chankIndexX, maskX); - while (++i < _sortIncBuffer.Length && _preSortedIncBuffer[i].chankIndex == chankIndexX) - { - // skip - } - } + var comparer = new IncCountComparer(counts); + UnsafeArraySortHalperX.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref comparer); + ConvertToChuncks(preSortingBuffer, _sortIncBuffer, _sortIncChunckBuffer); } if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]].count <= 0) { _span = span.Slice(0, 0).GetEnumerator(); return; } + if (_sortExcChunckBuffer.Length > 1) { - ExcCountComparer excComparer = new ExcCountComparer(counts); - UnsafeArraySortHalperX.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref excComparer); - for (int i = 0; i < _sortExcBuffer.Length; i++) - { - _preSortedExcBuffer[i] = EcsMaskChunck.FromID(_sortExcBuffer.ptr[i]); - } - - for (int i = 0, ii = 0; ii < _sortExcChunckBuffer.Length; ii++) - { - EcsMaskChunck bas = _preSortedExcBuffer[i]; - int chankIndexX = bas.chankIndex; - int maskX = bas.mask; - - for (int j = i + 1; j < _sortExcBuffer.Length; j++) - { - if (_preSortedExcBuffer[j].chankIndex == chankIndexX) - { - maskX |= _preSortedExcBuffer[j].mask; - } - } - _sortExcChunckBuffer.ptr[ii] = new EcsMaskChunck(chankIndexX, maskX); - while (++i < _sortExcBuffer.Length && _preSortedExcBuffer[i].chankIndex == chankIndexX) - { - // skip - } - } + ExcCountComparer comparer = new ExcCountComparer(counts); + UnsafeArraySortHalperX.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref comparer); + ConvertToChuncks(preSortingBuffer, _sortExcBuffer, _sortExcChunckBuffer); } #endregion @@ -1163,7 +1091,7 @@ namespace DCFApixels.DragonECS for (int i = 0; i < _sortIncChunckBuffer.Length; i++) { var bit = _sortIncChunckBuffer.ptr[i]; - if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != bit.mask) + if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != bit.mask) { goto skip; } @@ -1171,7 +1099,152 @@ namespace DCFApixels.DragonECS for (int i = 0; i < _sortExcChunckBuffer.Length; i++) { var bit = _sortExcChunckBuffer.ptr[i]; - if ((_entityComponentMasks[chunck + bit.chankIndex] & bit.mask) != 0) + if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != 0) + { + goto skip; + } + } + return true; + skip: continue; + } + return false; + } + } + #endregion + } + #endregion + + #region Iterate/Enumerable OnlyInc + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public OnlyIncEnumerable IterateOnlyInc(EcsSpan span) { return new OnlyIncEnumerable(this, span); } +#if ENABLE_IL2CPP + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + public readonly ref struct OnlyIncEnumerable + { + private readonly EcsMaskIterator _iterator; + private readonly EcsSpan _span; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public OnlyIncEnumerable(EcsMaskIterator iterator, EcsSpan span) + { + _iterator = iterator; + _span = span; + } + + #region CopyTo + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void CopyTo(EcsGroup group) + { + group.Clear(); + var enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + group.AddUnchecked(enumerator.Current); + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CopyTo(ref int[] array) + { + int count = 0; + var enumerator = GetEnumerator(); + while (enumerator.MoveNext()) + { + if (array.Length <= count) + { + Array.Resize(ref array, array.Length << 1); + } + array[count++] = enumerator.Current; + } + return count; + } + #endregion + + #region Other + public List ToList() + { + List ints = new List(); + foreach (var e in this) { ints.Add(e); } + return ints; + } + public override string ToString() { return CollectionUtility.EntitiesToString(ToList(), "inc_it"); } + #endregion + + #region Enumerator + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public Enumerator GetEnumerator() { return new Enumerator(_span, _iterator); } +#if ENABLE_IL2CPP + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + public unsafe ref struct Enumerator + { + private ReadOnlySpan.Enumerator _span; + + private readonly UnsafeArray _sortIncChunckBuffer; + + private readonly int[] _entityComponentMasks; + private readonly int _entityComponentMaskLengthBitShift; + + public unsafe Enumerator(EcsSpan span, EcsMaskIterator iterator) + { + _sortIncChunckBuffer = iterator._sortIncChunckBuffer; + + _entityComponentMasks = iterator.World._entityComponentMasks; + _entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift; + + if (iterator.Mask.IsBroken) + { + _span = span.Slice(0, 0).GetEnumerator(); + return; + } + + #region Sort + UnsafeArray _sortIncBuffer = iterator._sortIncBuffer; + EcsWorld.PoolSlot[] counts = iterator.World._poolSlots; + int max = _sortIncBuffer.Length; + + EcsMaskChunck* preSortingBuffer; + if (max > STACK_BUFFER_THRESHOLD) + { + preSortingBuffer = TempBuffer.Get(max); + } + else + { + EcsMaskChunck* ptr = stackalloc EcsMaskChunck[max]; + preSortingBuffer = ptr; + } + + if (_sortIncChunckBuffer.Length > 1) + { + var comparer = new IncCountComparer(counts); + UnsafeArraySortHalperX.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref comparer); + ConvertToChuncks(preSortingBuffer, _sortIncBuffer, _sortIncChunckBuffer); + } + if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]].count <= 0) + { + _span = span.Slice(0, 0).GetEnumerator(); + return; + } + #endregion + + _span = span.GetEnumerator(); + } + public int Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _span.Current; } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() + { + while (_span.MoveNext()) + { + int chunck = _span.Current << _entityComponentMaskLengthBitShift; + for (int i = 0; i < _sortIncChunckBuffer.Length; i++) + { + var bit = _sortIncChunckBuffer.ptr[i]; + if ((_entityComponentMasks[chunck + bit.chunkIndex] & bit.mask) != bit.mask) { goto skip; } @@ -1187,4 +1260,84 @@ namespace DCFApixels.DragonECS #endregion } #endregion +} + +namespace DCFApixels.DragonECS.Internal +{ + #region EcsMaskIteratorUtility +#if ENABLE_IL2CPP + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + internal unsafe class EcsMaskIteratorUtility + { + internal const int STACK_BUFFER_THRESHOLD = 256; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ConvertToChuncks(EcsMaskChunck* ptr, UnsafeArray input, UnsafeArray output) + { + for (int i = 0; i < input.Length; i++) + { + ptr[i] = EcsMaskChunck.FromID(input.ptr[i]); + } + + for (int inputI = 0, outputI = 0; outputI < output.Length; inputI++, ptr++) + { + int maskX = ptr->mask; + if (maskX == 0) { continue; } + int chunkIndexX = ptr->chunkIndex; + + EcsMaskChunck* subptr = ptr; + for (int j = 1; j < input.Length - inputI; j++, subptr++) + { + if (subptr->chunkIndex == chunkIndexX) + { + maskX |= subptr->mask; + *subptr = default; + } + } + output.ptr[outputI] = new EcsMaskChunck(chunkIndexX, maskX); + outputI++; + } + } + +#if ENABLE_IL2CPP + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + internal readonly struct IncCountComparer : IStructComparer + { + public readonly EcsWorld.PoolSlot[] counts; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public IncCountComparer(EcsWorld.PoolSlot[] counts) + { + this.counts = counts; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Compare(int a, int b) + { + return counts[a].count - counts[b].count; + } + } + +#if ENABLE_IL2CPP + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + internal readonly struct ExcCountComparer : IStructComparer + { + public readonly EcsWorld.PoolSlot[] counts; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ExcCountComparer(EcsWorld.PoolSlot[] counts) + { + this.counts = counts; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int Compare(int a, int b) + { + return counts[b].count - counts[a].count; + } + } + } + #endregion } \ No newline at end of file diff --git a/src/EcsPipeline.Builder.cs b/src/EcsPipeline.Builder.cs index 0abd4ad..054b0f9 100644 --- a/src/EcsPipeline.Builder.cs +++ b/src/EcsPipeline.Builder.cs @@ -82,7 +82,7 @@ namespace DCFApixels.DragonECS // Если система одновременно явялется и системой и модулем то сначала будет вызван IEcsModule // При этом дается возможность ручной установки порядка импорта системы вызовом Add(this) - if(_systemModule == system) + if (_systemModule == system) { _systemModuleAdded = true; } @@ -413,7 +413,7 @@ namespace DCFApixels.DragonECS // Автоматический слой нужный только для метода Add // Идея в том что метод Add добавляет слои до EcsConsts.END_LAYER и EcsConsts.POST_END_LAYER private const string ADD_LAYERS_LAYER = nameof(LayerList) + "." + nameof(ADD_LAYERS_LAYER); - + private Builder _source; private List _layers; diff --git a/src/EcsWorld.pools.cs b/src/EcsWorld.pools.cs index 2a87a4a..3964ca5 100644 --- a/src/EcsWorld.pools.cs +++ b/src/EcsWorld.pools.cs @@ -238,7 +238,7 @@ namespace DCFApixels.DragonECS slot.count++; slot.version++; _entities[entityID].componentsCount++; - _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] |= maskBit.mask; + _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] |= maskBit.mask; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) @@ -248,7 +248,7 @@ namespace DCFApixels.DragonECS slot.count--; slot.version++; var count = --_entities[entityID].componentsCount; - _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] &= ~maskBit.mask; + _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] &= ~maskBit.mask; if (count == 0 && IsUsed(entityID)) { @@ -263,7 +263,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool TryRegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) { - ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex]; + ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex]; int newChunk = chunk | maskBit.mask; if (chunk != newChunk) { @@ -280,7 +280,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool TryUnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) { - ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex]; + ref int chunk = ref _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex]; int newChunk = chunk & ~maskBit.mask; if (chunk != newChunk) { @@ -316,7 +316,7 @@ namespace DCFApixels.DragonECS [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool HasEntityComponent(int entityID, EcsMaskChunck maskBit) { - return (_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] & maskBit.mask) == maskBit.mask; + return (_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] & maskBit.mask) == maskBit.mask; } #endregion diff --git a/src/Executors/EcsWhereExecutor.cs b/src/Executors/EcsWhereExecutor.cs index 5f3fb77..49b654e 100644 --- a/src/Executors/EcsWhereExecutor.cs +++ b/src/Executors/EcsWhereExecutor.cs @@ -48,7 +48,7 @@ namespace DCFApixels.DragonECS.Internal if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false) { _version++; - _filteredAllEntitiesCount = _iterator.Iterate(World.Entities).CopyTo(ref _filteredAllEntities); + _filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities); } _lastWorldVersion = World.Version; } @@ -63,7 +63,7 @@ namespace DCFApixels.DragonECS.Internal { _filteredEntities = new int[32]; } - _filteredEntitiesCount = _iterator.Iterate(span).CopyTo(ref _filteredEntities); + _filteredEntitiesCount = _iterator.IterateTo(span, ref _filteredEntities); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Executors/EcsWhereToGroupExecutor.cs b/src/Executors/EcsWhereToGroupExecutor.cs index 884c268..243411f 100644 --- a/src/Executors/EcsWhereToGroupExecutor.cs +++ b/src/Executors/EcsWhereToGroupExecutor.cs @@ -49,7 +49,7 @@ namespace DCFApixels.DragonECS.Internal if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false) { _version++; - _iterator.Iterate(World.Entities).CopyTo(_filteredAllGroup); + _iterator.IterateTo(World.Entities, _filteredAllGroup); } _lastWorldVersion = World.Version; } @@ -64,7 +64,7 @@ namespace DCFApixels.DragonECS.Internal { _filteredGroup = EcsGroup.New(World); } - _iterator.Iterate(span).CopyTo(_filteredGroup); + _iterator.IterateTo(span, _filteredGroup); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/Internal/UnsafeArray.cs b/src/Internal/UnsafeArray.cs index 4a1f796..cf8ba0d 100644 --- a/src/Internal/UnsafeArray.cs +++ b/src/Internal/UnsafeArray.cs @@ -4,11 +4,45 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; +#if ENABLE_IL2CPP +using Unity.IL2CPP.CompilerServices; +#endif namespace DCFApixels.DragonECS.Internal { #if ENABLE_IL2CPP - using Unity.IL2CPP.CompilerServices; + [Il2CppSetOption (Option.NullChecks, false)] + [Il2CppSetOption(Option.ArrayBoundsChecks, false)] +#endif + public static unsafe class TempBuffer where T : unmanaged + { + [ThreadStatic] private static T* _ptr; + [ThreadStatic] private static int _size; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static T* Get(int size) + { + if (_size < size) + { + if (_ptr != null) + { + UnmanagedArrayUtility.Free(_ptr); + } + _ptr = UnmanagedArrayUtility.New(size); + _size = size; + } + return _ptr; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Clear() + { + for (int i = 0; i < _size; i++) + { + _ptr[i] = default; + } + } + } +#if ENABLE_IL2CPP [Il2CppSetOption (Option.NullChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)] #endif @@ -19,6 +53,16 @@ namespace DCFApixels.DragonECS.Internal internal T* ptr; internal int Length; + public static UnsafeArray FromArray(T[] array) + { + UnsafeArray result = new UnsafeArray(array.Length); + for (int i = 0; i < array.Length; i++) + { + result.ptr[i] = array[i]; + } + return result; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public UnsafeArray(int length) { @@ -49,6 +93,11 @@ namespace DCFApixels.DragonECS.Internal { UnmanagedArrayUtility.Free(ref ptr, ref Length); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void ReadonlyDispose() + { + UnmanagedArrayUtility.Free(ptr); + } public override string ToString() { T* ptr = this.ptr;