diff --git a/src/Executors/EcsQueryExecutor.cs b/src/Executors/EcsQueryExecutor.cs index 0e7ee76..e05dd87 100644 --- a/src/Executors/EcsQueryExecutor.cs +++ b/src/Executors/EcsQueryExecutor.cs @@ -1,4 +1,5 @@ -using System; +using DCFApixels.DragonECS.Internal; +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -55,37 +56,107 @@ namespace DCFApixels.DragonECS protected abstract void OnDestroy(); } - public readonly struct PoolVersionsChecker + public readonly unsafe struct WorldStateVersionsChecker : IDisposable { - private readonly EcsMask _mask; - private readonly long[] _versions; - - public PoolVersionsChecker(EcsMask mask) + private readonly EcsWorld _world; + private readonly int[] _maskInc; + private readonly int[] _maskExc; + // [0] world version + // [-> _maskInc.Length] inc versions + // [-> _maskExc.Length] exc versions + private readonly long* _versions; + public long Version { - _mask = mask; - _versions = new long[mask._inc.Length + mask._exc.Length]; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _versions[0]; } } - public bool NextEquals() + public WorldStateVersionsChecker(EcsMask mask) { - var slots = _mask.World._poolSlots; - bool result = true; - int index = 0; - foreach (var i in _mask._inc) + _world = mask.World; + _maskInc = mask._inc; + _maskExc = mask._exc; + _versions = UnmanagedArrayUtility.New(1 + mask._inc.Length + mask._exc.Length); + } + public bool Check() + { + if (*_versions == _world.Version) { - if (slots[i].version != _versions[index++]) + return true; + } + + long* ptr = _versions; + var slots = _world._poolSlots; + foreach (var slotIndex in _maskInc) + { + ptr++; + if (*ptr != slots[slotIndex].version) { - result = false; + return false; } } - foreach (var i in _mask._exc) + foreach (var slotIndex in _maskExc) { - if (slots[i].version != _versions[index++]) + ptr++; + if (*ptr != slots[slotIndex].version) + { + return false; + } + } + return true; + } + public void Next() + { + *_versions = _world.Version; + + long* ptr = _versions; + var slots = _world._poolSlots; + foreach (var slotIndex in _maskInc) + { + ptr++; + *ptr = slots[slotIndex].version; + } + foreach (var slotIndex in _maskExc) + { + ptr++; + *ptr = slots[slotIndex].version; + } + } + public bool CheckAndNext() + { + if (*_versions == _world.Version) + { + return true; + } + *_versions = _world.Version; + + long* ptr = _versions; + var slots = _world._poolSlots; + bool result = true; + foreach (var slotIndex in _maskInc) + { + ptr++; + if (*ptr != slots[slotIndex].version) { result = false; + *ptr = slots[slotIndex].version; + } + } + foreach (var slotIndex in _maskExc) + { + ptr++; + if (*ptr != slots[slotIndex].version) + { + result = false; + *ptr = slots[slotIndex].version; } } return result; } + + public void Dispose() + { + + } } } \ No newline at end of file diff --git a/src/Executors/EcsWhereExecutor.cs b/src/Executors/EcsWhereExecutor.cs index 49b654e..9928811 100644 --- a/src/Executors/EcsWhereExecutor.cs +++ b/src/Executors/EcsWhereExecutor.cs @@ -20,8 +20,7 @@ namespace DCFApixels.DragonECS.Internal private int[] _filteredEntities = null; private int _filteredEntitiesCount = 0; - private long _lastWorldVersion = 0; - private PoolVersionsChecker _versionsChecker; + private WorldStateVersionsChecker _versionsChecker; #region Properties public sealed override long Version @@ -34,10 +33,13 @@ namespace DCFApixels.DragonECS.Internal #region OnInitialize/OnDestroy protected sealed override void OnInitialize() { - _versionsChecker = new PoolVersionsChecker(Mask); + _versionsChecker = new WorldStateVersionsChecker(Mask); _iterator = Mask.GetIterator(); } - protected sealed override void OnDestroy() { } + protected sealed override void OnDestroy() + { + _versionsChecker.Dispose(); + } #endregion #region Methods @@ -45,12 +47,11 @@ namespace DCFApixels.DragonECS.Internal private void Execute_Iternal() { World.ReleaseDelEntityBufferAllAuto(); - if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false) + if (_versionsChecker.CheckAndNext() == false) { _version++; _filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities); } - _lastWorldVersion = World.Version; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ExecuteFor_Iternal(EcsSpan span) diff --git a/src/Executors/EcsWhereToGroupExecutor.cs b/src/Executors/EcsWhereToGroupExecutor.cs index 243411f..111798d 100644 --- a/src/Executors/EcsWhereToGroupExecutor.cs +++ b/src/Executors/EcsWhereToGroupExecutor.cs @@ -17,8 +17,7 @@ namespace DCFApixels.DragonECS.Internal private EcsGroup _filteredGroup; - private long _lastWorldVersion; - private PoolVersionsChecker _versionsChecker; + private WorldStateVersionsChecker _versionsChecker; #region Properties public sealed override long Version @@ -31,13 +30,14 @@ namespace DCFApixels.DragonECS.Internal #region OnInitialize/OnDestroy protected sealed override void OnInitialize() { - _versionsChecker = new PoolVersionsChecker(Mask); + _versionsChecker = new WorldStateVersionsChecker(Mask); _filteredAllGroup = EcsGroup.New(World); _iterator = Mask.GetIterator(); } protected sealed override void OnDestroy() { _filteredAllGroup.Dispose(); + _versionsChecker.Dispose(); } #endregion @@ -46,12 +46,11 @@ namespace DCFApixels.DragonECS.Internal private void Execute_Iternal() { World.ReleaseDelEntityBufferAllAuto(); - if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false) + if (_versionsChecker.CheckAndNext() == false) { _version++; _iterator.IterateTo(World.Entities, _filteredAllGroup); } - _lastWorldVersion = World.Version; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ExecuteFor_Iternal(EcsSpan span)