update mask iterator

This commit is contained in:
Mikhail 2024-10-10 19:57:19 +08:00
parent 7544d18d1e
commit 57b0ba225a
7 changed files with 376 additions and 173 deletions

View File

@ -260,7 +260,8 @@ namespace DCFApixels.DragonECS
} }
public EcsSpan CopyToSpan(ref int[] array) public EcsSpan CopyToSpan(ref int[] array)
{ {
return iterator.CopyToSpan(ref array); int count = CopyTo(ref array);
return new EcsSpan(worldID, array, count);
} }
#endregion #endregion

View File

@ -11,6 +11,7 @@ using Unity.IL2CPP.CompilerServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
using static EcsMaskIteratorUtility;
public interface IEcsComponentMask public interface IEcsComponentMask
{ {
EcsMask ToMask(EcsWorld world); EcsMask ToMask(EcsWorld world);
@ -283,7 +284,7 @@ namespace DCFApixels.DragonECS
do do
{ {
EcsMaskChunck bitJ = EcsMaskChunck.FromID(sortedArray[i]); EcsMaskChunck bitJ = EcsMaskChunck.FromID(sortedArray[i]);
if (bitJ.chankIndex != chankIndexX) if (bitJ.chunkIndex != chankIndexX)
{ {
break; break;
} }
@ -554,7 +555,7 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region AbstractMask #region StaticMask
public static EcsMask FromStatic(EcsWorld world, EcsStaticMask abstractMask) public static EcsMask FromStatic(EcsWorld world, EcsStaticMask abstractMask)
{ {
return world.Get<WorldMaskComponent>().ConvertFromAbstract(abstractMask); return world.Get<WorldMaskComponent>().ConvertFromAbstract(abstractMask);
@ -849,11 +850,11 @@ namespace DCFApixels.DragonECS
internal const int DIV_SHIFT = 5; internal const int DIV_SHIFT = 5;
internal const int MOD_MASK = BITS - 1; internal const int MOD_MASK = BITS - 1;
public readonly int chankIndex; public readonly int chunkIndex;
public readonly int mask; public readonly int mask;
public EcsMaskChunck(int chankIndex, int mask) public EcsMaskChunck(int chankIndex, int mask)
{ {
this.chankIndex = chankIndex; this.chunkIndex = chankIndex;
this.mask = mask; this.mask = mask;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -863,7 +864,7 @@ namespace DCFApixels.DragonECS
} }
public override string ToString() public override string ToString()
{ {
return $"mask({chankIndex}, {mask}, {BitsUtility.CountBits(mask)})"; return $"mask({chunkIndex}, {mask}, {BitsUtility.CountBits(mask)})";
} }
internal class DebuggerProxy internal class DebuggerProxy
{ {
@ -873,7 +874,7 @@ namespace DCFApixels.DragonECS
public string bits; public string bits;
public DebuggerProxy(EcsMaskChunck maskbits) public DebuggerProxy(EcsMaskChunck maskbits)
{ {
chunk = maskbits.chankIndex; chunk = maskbits.chunkIndex;
mask = (uint)maskbits.mask; mask = (uint)maskbits.mask;
BitsUtility.GetBitNumbersNoAlloc(mask, ref values); BitsUtility.GetBitNumbersNoAlloc(mask, ref values);
for (int i = 0; i < values.Length; i++) for (int i = 0; i < values.Length; i++)
@ -893,103 +894,75 @@ namespace DCFApixels.DragonECS
#endif #endif
public class EcsMaskIterator public class EcsMaskIterator
{ {
#region CountStructComparers public readonly EcsWorld World;
private readonly struct IncCountComparer : IStructComparer<int> public readonly EcsMask Mask;
{
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<int>
{
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
internal EcsWorld _source; private readonly UnsafeArray<int> _sortIncBuffer;
internal EcsMask _mask; private readonly UnsafeArray<int> _sortExcBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private UnsafeArray<int> _sortIncBuffer; private readonly bool _isOnlyInc;
private UnsafeArray<int> _sortExcBuffer;
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
#region Constructors #region Constructors/Finalizator
public unsafe EcsMaskIterator(EcsWorld source, EcsMask mask) public unsafe EcsMaskIterator(EcsWorld source, EcsMask mask)
{ {
_source = source; World = source;
_mask = mask; Mask = mask;
_sortIncBuffer = UnsafeArray<int>.FromArray(mask._inc);
_sortIncBuffer = new UnsafeArray<int>(_mask._inc.Length); _sortExcBuffer = UnsafeArray<int>.FromArray(mask._exc);
_sortExcBuffer = new UnsafeArray<int>(_mask._exc.Length); _sortIncChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._incChunckMasks);
_sortIncChunckBuffer = new UnsafeArray<EcsMaskChunck>(_mask._incChunckMasks.Length); _sortExcChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._excChunckMasks);
_sortExcChunckBuffer = new UnsafeArray<EcsMaskChunck>(_mask._excChunckMasks.Length); _isOnlyInc = _sortExcBuffer.Length <= 0;
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];
}
} }
#endregion
#region Finalizator
unsafe ~EcsMaskIterator() unsafe ~EcsMaskIterator()
{ {
_sortIncBuffer.Dispose(); _sortIncBuffer.ReadonlyDispose();
_sortExcBuffer.Dispose(); _sortExcBuffer.ReadonlyDispose();
_sortIncChunckBuffer.Dispose(); _sortIncChunckBuffer.ReadonlyDispose();
_sortExcChunckBuffer.Dispose(); _sortExcChunckBuffer.ReadonlyDispose();
} }
#endregion #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 #endregion
#region Enumerable #region Iterate/Enumerable
public Enumerable Iterate(EcsSpan span) [MethodImpl(MethodImplOptions.AggressiveInlining)]
{ public Enumerable Iterate(EcsSpan span) { return new Enumerable(this, span); }
return new Enumerable(this, span); #if ENABLE_IL2CPP
} [Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif
public readonly ref struct Enumerable public readonly ref struct Enumerable
{ {
private readonly EcsMaskIterator _iterator; private readonly EcsMaskIterator _iterator;
private readonly EcsSpan _span; private readonly EcsSpan _span;
public Enumerable(EcsMaskIterator iterator, EcsSpan span) public Enumerable(EcsMaskIterator iterator, EcsSpan span)
{ {
_iterator = iterator; _iterator = iterator;
@ -997,6 +970,7 @@ namespace DCFApixels.DragonECS
} }
#region CopyTo #region CopyTo
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(EcsGroup group) public void CopyTo(EcsGroup group)
{ {
group.Clear(); group.Clear();
@ -1006,6 +980,7 @@ namespace DCFApixels.DragonECS
group.AddUnchecked(enumerator.Current); group.AddUnchecked(enumerator.Current);
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int CopyTo(ref int[] array) public int CopyTo(ref int[] array)
{ {
int count = 0; int count = 0;
@ -1020,50 +995,41 @@ namespace DCFApixels.DragonECS
} }
return count; return count;
} }
public EcsSpan CopyToSpan(ref int[] array)
{
int count = CopyTo(ref array);
return new EcsSpan(_iterator.World.id, array, count);
}
#endregion #endregion
#region Other #region Other
public override string ToString() public List<int> ToList()
{ {
List<int> ints = new List<int>(); List<int> ints = new List<int>();
foreach (var e in this) foreach (var e in this) { ints.Add(e); }
{ return ints;
ints.Add(e);
}
return CollectionUtility.EntitiesToString(ints, "it");
} }
public override string ToString() { return CollectionUtility.EntitiesToString(ToList(), "it"); }
#endregion #endregion
#region Enumerator #region Enumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() { return new Enumerator(_span, _iterator); } 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 public unsafe ref struct Enumerator
{ {
private ReadOnlySpan<int>.Enumerator _span; private ReadOnlySpan<int>.Enumerator _span;
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private readonly int[] _entityComponentMasks; private readonly int[] _entityComponentMasks;
[ThreadStatic]
private static EcsMaskChunck* _preSortedIncBuffer;
[ThreadStatic]
private static EcsMaskChunck* _preSortedExcBuffer;
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private readonly int _entityComponentMaskLengthBitShift; private readonly int _entityComponentMaskLengthBitShift;
public unsafe Enumerator(EcsSpan span, EcsMaskIterator iterator) public unsafe Enumerator(EcsSpan span, EcsMaskIterator iterator)
{ {
_entityComponentMasks = iterator.World._entityComponentMasks;
_sortIncChunckBuffer = iterator._sortIncChunckBuffer; _sortIncChunckBuffer = iterator._sortIncChunckBuffer;
_sortExcChunckBuffer = iterator._sortExcChunckBuffer; _sortExcChunckBuffer = iterator._sortExcChunckBuffer;
_entityComponentMasks = iterator.World._entityComponentMasks;
_entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift; _entityComponentMaskLengthBitShift = iterator.World._entityComponentMaskLengthBitShift;
if (iterator.Mask.IsBroken) if (iterator.Mask.IsBroken)
@ -1076,74 +1042,36 @@ namespace DCFApixels.DragonECS
UnsafeArray<int> _sortIncBuffer = iterator._sortIncBuffer; UnsafeArray<int> _sortIncBuffer = iterator._sortIncBuffer;
UnsafeArray<int> _sortExcBuffer = iterator._sortExcBuffer; UnsafeArray<int> _sortExcBuffer = iterator._sortExcBuffer;
EcsWorld.PoolSlot[] counts = iterator.World._poolSlots; 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<EcsMaskChunck>(256); preSortingBuffer = TempBuffer<EcsMaskChunck>.Get(max);
_preSortedExcBuffer = UnmanagedArrayUtility.New<EcsMaskChunck>(256); }
else
{
EcsMaskChunck* ptr = stackalloc EcsMaskChunck[max];
preSortingBuffer = ptr;
} }
if (_sortIncChunckBuffer.Length > 1) if (_sortIncChunckBuffer.Length > 1)
{ {
IncCountComparer incComparer = new IncCountComparer(counts); var comparer = new IncCountComparer(counts);
UnsafeArraySortHalperX<int>.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref incComparer); UnsafeArraySortHalperX<int>.InsertionSort(_sortIncBuffer.ptr, _sortIncBuffer.Length, ref comparer);
for (int i = 0; i < _sortIncBuffer.Length; i++) ConvertToChuncks(preSortingBuffer, _sortIncBuffer, _sortIncChunckBuffer);
{
_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
}
}
} }
if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]].count <= 0) if (_sortIncChunckBuffer.Length > 0 && counts[_sortIncBuffer.ptr[0]].count <= 0)
{ {
_span = span.Slice(0, 0).GetEnumerator(); _span = span.Slice(0, 0).GetEnumerator();
return; return;
} }
if (_sortExcChunckBuffer.Length > 1) if (_sortExcChunckBuffer.Length > 1)
{ {
ExcCountComparer excComparer = new ExcCountComparer(counts); ExcCountComparer comparer = new ExcCountComparer(counts);
UnsafeArraySortHalperX<int>.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref excComparer); UnsafeArraySortHalperX<int>.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref comparer);
for (int i = 0; i < _sortExcBuffer.Length; i++) ConvertToChuncks(preSortingBuffer, _sortExcBuffer, _sortExcChunckBuffer);
{
_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
}
}
} }
#endregion #endregion
@ -1163,7 +1091,7 @@ namespace DCFApixels.DragonECS
for (int i = 0; i < _sortIncChunckBuffer.Length; i++) for (int i = 0; i < _sortIncChunckBuffer.Length; i++)
{ {
var bit = _sortIncChunckBuffer.ptr[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; goto skip;
} }
@ -1171,7 +1099,152 @@ namespace DCFApixels.DragonECS
for (int i = 0; i < _sortExcChunckBuffer.Length; i++) for (int i = 0; i < _sortExcChunckBuffer.Length; i++)
{ {
var bit = _sortExcChunckBuffer.ptr[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<int> ToList()
{
List<int> ints = new List<int>();
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<int>.Enumerator _span;
private readonly UnsafeArray<EcsMaskChunck> _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<int> _sortIncBuffer = iterator._sortIncBuffer;
EcsWorld.PoolSlot[] counts = iterator.World._poolSlots;
int max = _sortIncBuffer.Length;
EcsMaskChunck* preSortingBuffer;
if (max > STACK_BUFFER_THRESHOLD)
{
preSortingBuffer = TempBuffer<EcsMaskChunck>.Get(max);
}
else
{
EcsMaskChunck* ptr = stackalloc EcsMaskChunck[max];
preSortingBuffer = ptr;
}
if (_sortIncChunckBuffer.Length > 1)
{
var comparer = new IncCountComparer(counts);
UnsafeArraySortHalperX<int>.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; goto skip;
} }
@ -1187,4 +1260,84 @@ namespace DCFApixels.DragonECS
#endregion #endregion
} }
#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<int> input, UnsafeArray<EcsMaskChunck> 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<int>
{
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<int>
{
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
} }

View File

@ -82,7 +82,7 @@ namespace DCFApixels.DragonECS
// Если система одновременно явялется и системой и модулем то сначала будет вызван IEcsModule // Если система одновременно явялется и системой и модулем то сначала будет вызван IEcsModule
// При этом дается возможность ручной установки порядка импорта системы вызовом Add(this) // При этом дается возможность ручной установки порядка импорта системы вызовом Add(this)
if(_systemModule == system) if (_systemModule == system)
{ {
_systemModuleAdded = true; _systemModuleAdded = true;
} }
@ -413,7 +413,7 @@ namespace DCFApixels.DragonECS
// Автоматический слой нужный только для метода Add // Автоматический слой нужный только для метода Add
// Идея в том что метод Add добавляет слои до EcsConsts.END_LAYER и EcsConsts.POST_END_LAYER // Идея в том что метод Add добавляет слои до EcsConsts.END_LAYER и EcsConsts.POST_END_LAYER
private const string ADD_LAYERS_LAYER = nameof(LayerList) + "." + nameof(ADD_LAYERS_LAYER); private const string ADD_LAYERS_LAYER = nameof(LayerList) + "." + nameof(ADD_LAYERS_LAYER);
private Builder _source; private Builder _source;
private List<string> _layers; private List<string> _layers;

View File

@ -238,7 +238,7 @@ namespace DCFApixels.DragonECS
slot.count++; slot.count++;
slot.version++; slot.version++;
_entities[entityID].componentsCount++; _entities[entityID].componentsCount++;
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] |= maskBit.mask; _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] |= maskBit.mask;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) private void UnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
@ -248,7 +248,7 @@ namespace DCFApixels.DragonECS
slot.count--; slot.count--;
slot.version++; slot.version++;
var count = --_entities[entityID].componentsCount; var count = --_entities[entityID].componentsCount;
_entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chankIndex] &= ~maskBit.mask; _entityComponentMasks[(entityID << _entityComponentMaskLengthBitShift) + maskBit.chunkIndex] &= ~maskBit.mask;
if (count == 0 && IsUsed(entityID)) if (count == 0 && IsUsed(entityID))
{ {
@ -263,7 +263,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool TryRegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) 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; int newChunk = chunk | maskBit.mask;
if (chunk != newChunk) if (chunk != newChunk)
{ {
@ -280,7 +280,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool TryUnregisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) 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; int newChunk = chunk & ~maskBit.mask;
if (chunk != newChunk) if (chunk != newChunk)
{ {
@ -316,7 +316,7 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private bool HasEntityComponent(int entityID, EcsMaskChunck maskBit) 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 #endregion

View File

@ -48,7 +48,7 @@ namespace DCFApixels.DragonECS.Internal
if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false) if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false)
{ {
_version++; _version++;
_filteredAllEntitiesCount = _iterator.Iterate(World.Entities).CopyTo(ref _filteredAllEntities); _filteredAllEntitiesCount = _iterator.IterateTo(World.Entities, ref _filteredAllEntities);
} }
_lastWorldVersion = World.Version; _lastWorldVersion = World.Version;
} }
@ -63,7 +63,7 @@ namespace DCFApixels.DragonECS.Internal
{ {
_filteredEntities = new int[32]; _filteredEntities = new int[32];
} }
_filteredEntitiesCount = _iterator.Iterate(span).CopyTo(ref _filteredEntities); _filteredEntitiesCount = _iterator.IterateTo(span, ref _filteredEntities);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@ -49,7 +49,7 @@ namespace DCFApixels.DragonECS.Internal
if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false) if (_lastWorldVersion != World.Version || _versionsChecker.NextEquals() == false)
{ {
_version++; _version++;
_iterator.Iterate(World.Entities).CopyTo(_filteredAllGroup); _iterator.IterateTo(World.Entities, _filteredAllGroup);
} }
_lastWorldVersion = World.Version; _lastWorldVersion = World.Version;
} }
@ -64,7 +64,7 @@ namespace DCFApixels.DragonECS.Internal
{ {
_filteredGroup = EcsGroup.New(World); _filteredGroup = EcsGroup.New(World);
} }
_iterator.Iterate(span).CopyTo(_filteredGroup); _iterator.IterateTo(span, _filteredGroup);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@ -4,11 +4,45 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices;
#endif
namespace DCFApixels.DragonECS.Internal namespace DCFApixels.DragonECS.Internal
{ {
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices; [Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif
public static unsafe class TempBuffer<T> 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<T>(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.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)] [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif #endif
@ -19,6 +53,16 @@ namespace DCFApixels.DragonECS.Internal
internal T* ptr; internal T* ptr;
internal int Length; internal int Length;
public static UnsafeArray<T> FromArray(T[] array)
{
UnsafeArray<T> result = new UnsafeArray<T>(array.Length);
for (int i = 0; i < array.Length; i++)
{
result.ptr[i] = array[i];
}
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray(int length) public UnsafeArray(int length)
{ {
@ -49,6 +93,11 @@ namespace DCFApixels.DragonECS.Internal
{ {
UnmanagedArrayUtility.Free(ref ptr, ref Length); UnmanagedArrayUtility.Free(ref ptr, ref Length);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ReadonlyDispose()
{
UnmanagedArrayUtility.Free(ptr);
}
public override string ToString() public override string ToString()
{ {
T* ptr = this.ptr; T* ptr = this.ptr;