This commit is contained in:
Mikhail 2024-11-03 18:57:56 +08:00
parent 7652936e5b
commit c569007e8f
6 changed files with 165 additions and 97 deletions

View File

@ -22,7 +22,6 @@ namespace DCFApixels.DragonECS
{
using static EcsMaskIteratorUtility;
#if ENABLE_IL2CPP
[Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
@ -483,12 +482,19 @@ namespace DCFApixels.DragonECS
#endif
public class EcsMaskIterator
{
// TODO есть идея перенести эти ChunckBuffer-ы в стек,
// для этого нужно проработать дизайн так чтобы память в стеке выделялась за пределами итератора и GetEnumerator,
// а далее передавались поинтеры, в противном случае использовался бы стандартный подход
public readonly EcsWorld World;
public readonly EcsMask Mask;
private readonly UnsafeArray<int> _sortIncBuffer;
/// <summary> slised _sortIncBuffer </summary>
private readonly UnsafeArray<int> _sortExcBuffer;
private readonly UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
/// <summary> slised _sortIncChunckBuffer </summary>
private readonly UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private readonly bool _isOnlyInc;
@ -498,21 +504,86 @@ namespace DCFApixels.DragonECS
{
World = source;
Mask = mask;
_sortIncBuffer = UnsafeArray<int>.FromArray(mask._incs);
_sortExcBuffer = UnsafeArray<int>.FromArray(mask._excs);
_sortIncChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._incChunckMasks);
_sortExcChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._excChunckMasks);
//_sortIncBuffer = UnsafeArray<int>.FromArray(mask._incs);
//_sortExcBuffer = UnsafeArray<int>.FromArray(mask._excs);
//_sortIncChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._incChunckMasks);
//_sortExcChunckBuffer = UnsafeArray<EcsMaskChunck>.FromArray(mask._excChunckMasks);
var sortBuffer = new UnsafeArray<int>(mask._incs.Length + mask._excs.Length);
var sortChunckBuffer = new UnsafeArray<EcsMaskChunck>(mask._incChunckMasks.Length + mask._excChunckMasks.Length);
_sortIncBuffer = sortBuffer.Slice(0, mask._incs.Length);
_sortIncBuffer.CopyFromArray_Unchecked(mask._incs);
_sortExcBuffer = sortBuffer.Slice(mask._incs.Length, mask._excs.Length);
_sortExcBuffer.CopyFromArray_Unchecked(mask._excs);
_sortIncChunckBuffer = sortChunckBuffer.Slice(0, mask._incChunckMasks.Length);
_sortIncChunckBuffer.CopyFromArray_Unchecked(mask._incChunckMasks);
_sortExcChunckBuffer = sortChunckBuffer.Slice(mask._incChunckMasks.Length, mask._excChunckMasks.Length);
_sortExcChunckBuffer.CopyFromArray_Unchecked(mask._excChunckMasks);
_isOnlyInc = _sortExcBuffer.Length <= 0;
}
unsafe ~EcsMaskIterator()
{
_sortIncBuffer.ReadonlyDispose();
_sortExcBuffer.ReadonlyDispose();
//_sortExcBuffer.ReadonlyDispose();// использует общую памяять с _sortIncBuffer;
_sortIncChunckBuffer.ReadonlyDispose();
_sortExcChunckBuffer.ReadonlyDispose();
//_sortExcChunckBuffer.ReadonlyDispose();// использует общую памяять с _sortIncChunckBuffer;
}
#endregion
#region SortConstraints
private unsafe int SortConstraints_Internal()
{
UnsafeArray<int> sortIncBuffer = _sortIncBuffer;
UnsafeArray<int> sortExcBuffer = _sortExcBuffer;
EcsWorld.PoolSlot[] counts = World._poolSlots;
int maxBufferSize = sortIncBuffer.Length > sortExcBuffer.Length ? sortIncBuffer.Length : sortExcBuffer.Length;
int maxEntites = int.MaxValue;
EcsMaskChunck* preSortingBuffer;
if (maxBufferSize > STACK_BUFFER_THRESHOLD)
{
preSortingBuffer = TempBuffer<EcsMaskChunck>.Get(maxBufferSize);
}
else
{
EcsMaskChunck* ptr = stackalloc EcsMaskChunck[maxBufferSize];
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)
{
maxEntites = counts[_sortIncBuffer.ptr[0]].count;
if (maxEntites <= 0)
{
return 0;
}
}
if (_sortExcChunckBuffer.Length > 1)
{
ExcCountComparer comparer = new ExcCountComparer(counts);
UnsafeArraySortHalperX<int>.InsertionSort(sortExcBuffer.ptr, sortExcBuffer.Length, ref comparer);
ConvertToChuncks(preSortingBuffer, sortExcBuffer, _sortExcChunckBuffer);
}
// Выражение мало IncCount < (AllEntitesCount - ExcCount) вероятно будет истинным.
// ExcCount = максимальное количество ентитей с исключеющим ограничением и IncCount = минимальоне количество ентитей с включающим ограничением
// Поэтому исключающее ограничение игнорируется для maxEntites.
return maxEntites;
}
#endregion
#region IterateTo
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -598,7 +669,20 @@ namespace DCFApixels.DragonECS
#region Enumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() { return new Enumerator(_span, _iterator); }
public Enumerator GetEnumerator()
{
if (_iterator.Mask.IsBroken)
{
return new Enumerator(_span.Slice(0, 0), _iterator);
}
int maxEntities = _iterator.SortConstraints_Internal();
if (maxEntities <= 0)
{
return new Enumerator(_span.Slice(0, 0), _iterator);
}
return new Enumerator(_span, _iterator);
}
#if ENABLE_IL2CPP
[Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
@ -621,49 +705,6 @@ namespace DCFApixels.DragonECS
_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;
UnsafeArray<int> _sortExcBuffer = iterator._sortExcBuffer;
EcsWorld.PoolSlot[] counts = iterator.World._poolSlots;
int max = _sortIncBuffer.Length > _sortExcBuffer.Length ? _sortIncBuffer.Length : _sortExcBuffer.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;
}
if (_sortExcChunckBuffer.Length > 1)
{
ExcCountComparer comparer = new ExcCountComparer(counts);
UnsafeArraySortHalperX<int>.InsertionSort(_sortExcBuffer.ptr, _sortExcBuffer.Length, ref comparer);
ConvertToChuncks(preSortingBuffer, _sortExcBuffer, _sortExcChunckBuffer);
}
#endregion
_span = span.GetEnumerator();
}
public int Current
@ -761,7 +802,20 @@ namespace DCFApixels.DragonECS
#region Enumerator
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() { return new Enumerator(_span, _iterator); }
public Enumerator GetEnumerator()
{
if (_iterator.Mask.IsBroken)
{
return new Enumerator(_span.Slice(0, 0), _iterator);
}
int maxEntities = _iterator.SortConstraints_Internal();
if (maxEntities <= 0)
{
return new Enumerator(_span.Slice(0, 0), _iterator);
}
return new Enumerator(_span, _iterator);
}
#if ENABLE_IL2CPP
[Il2CppSetOption (Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
@ -782,41 +836,6 @@ namespace DCFApixels.DragonECS
_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

View File

@ -32,25 +32,32 @@ namespace DCFApixels.DragonECS
component = default;
}
}
internal readonly struct QueryCache<TExecutor, TAspcet> : IEcsWorldComponent<QueryCache<TExecutor, TAspcet>>
//TODO добавить сквозной кеш для инстансов TExecutor
//private readonly struct WhereCache<TExecutor> : IEcsWorldComponent<WhereCache<TExecutor>>
//{
// private readonly SparseArray<int, TExecutor> _pairs
//}
// Это не подохидт
internal readonly struct WhereQueryCache<TExecutor, TAspcet> : IEcsWorldComponent<WhereQueryCache<TExecutor, TAspcet>>
where TExecutor : EcsQueryExecutor, new()
where TAspcet : EcsAspect, new()
{
public readonly TExecutor Executor;
public readonly TAspcet Aspcet;
public QueryCache(TExecutor executor, TAspcet aspcet)
public WhereQueryCache(TExecutor executor, TAspcet aspcet)
{
Executor = executor;
Aspcet = aspcet;
}
void IEcsWorldComponent<QueryCache<TExecutor, TAspcet>>.Init(ref QueryCache<TExecutor, TAspcet> component, EcsWorld world)
void IEcsWorldComponent<WhereQueryCache<TExecutor, TAspcet>>.Init(ref WhereQueryCache<TExecutor, TAspcet> component, EcsWorld world)
{
TExecutor instance = new TExecutor();
TAspcet aspect = world.GetAspect<TAspcet>();
instance.Initialize(world, aspect.Mask);
component = new QueryCache<TExecutor, TAspcet>(instance, aspect);
component = new WhereQueryCache<TExecutor, TAspcet>(instance, aspect);
}
void IEcsWorldComponent<QueryCache<TExecutor, TAspcet>>.OnDestroy(ref QueryCache<TExecutor, TAspcet> component, EcsWorld world)
void IEcsWorldComponent<WhereQueryCache<TExecutor, TAspcet>>.OnDestroy(ref WhereQueryCache<TExecutor, TAspcet> component, EcsWorld world)
{
component = default;
}

View File

@ -234,7 +234,7 @@ namespace DCFApixels.DragonECS
where TExecutor : EcsQueryExecutor, new()
where TAspect : EcsAspect, new()
{
ref var cmp = ref Get<QueryCache<TExecutor, TAspect>>();
ref var cmp = ref Get<WhereQueryCache<TExecutor, TAspect>>();
executor = cmp.Executor;
aspect = cmp.Aspcet;
}

View File

@ -250,6 +250,8 @@ namespace DCFApixels.DragonECS.Internal
new IntPtr(oldPointer),
new IntPtr(MetaCache<T>.Size * newCount))).ToPointer();
}
}
public static class CollectionUtility

View File

@ -2,13 +2,15 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices;
#endif
namespace DCFApixels.DragonECS.Internal
{
//TODO разработать возможность ручного устанавливания ID типам.
//это нужно для упрощения разработки сетевух
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices;
[Il2CppSetOption(Option.NullChecks, false)]
[Il2CppSetOption(Option.ArrayBoundsChecks, false)]
#endif

View File

@ -2,7 +2,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
#if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices;
@ -63,6 +62,8 @@ namespace DCFApixels.DragonECS.Internal
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray(int length)
{
@ -82,6 +83,34 @@ namespace DCFApixels.DragonECS.Internal
Length = length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<T> Slice(int start)
{
if ((uint)start > (uint)Length)
{
throw new ArgumentOutOfRangeException();
}
return new UnsafeArray<T>(ptr + start, Length - start);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<T> Slice(int start, int length)
{
if ((uint)start > (uint)Length || (uint)length > (uint)(Length - start))
{
throw new ArgumentOutOfRangeException();
}
return new UnsafeArray<T>(ptr + start, length);
}
public void CopyFromArray_Unchecked(T[] array)
{
for (int i = 0; i < array.Length; i++)
{
ptr[i] = array[i];
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<T> Clone()
{
@ -101,7 +130,12 @@ namespace DCFApixels.DragonECS.Internal
public override string ToString()
{
T* ptr = this.ptr;
return CollectionUtility.AutoToString(EnumerableInt.Range(0, Length).Select(i => ptr[i]), "ua");
var elements = new T[Length];
for (int i = 0; i < Length; i++)
{
elements[i] = ptr[i];
}
return CollectionUtility.AutoToString(elements, "ua");
}
IEnumerator<T> IEnumerable<T>.GetEnumerator() { return GetEnumerator(); }
@ -139,8 +173,12 @@ namespace DCFApixels.DragonECS.Internal
public int length;
public DebuggerProxy(UnsafeArray<T> instance)
{
elements = EnumerableInt.Range(0, instance.Length).Select(i => instance.ptr[i]).ToArray();
length = instance.Length;
elements = new T[length];
for (int i = 0; i < length; i++)
{
elements[i] = instance.ptr[i];
}
}
}
}