optimize entity-component masks

This commit is contained in:
Mikhail 2024-02-16 21:17:20 +08:00
parent e1260a96fc
commit 475a51818f
3 changed files with 65 additions and 31 deletions

View File

@ -266,7 +266,7 @@ namespace DCFApixels.DragonECS
#endregion #endregion
private ReadOnlySpan<int>.Enumerator _span; private ReadOnlySpan<int>.Enumerator _span;
private readonly int[][] _entitiesComponentMasks; private readonly int[] _entityComponentMasks;
private static EcsMaskChunck* _preSortedIncBuffer; private static EcsMaskChunck* _preSortedIncBuffer;
private static EcsMaskChunck* _preSortedExcBuffer; private static EcsMaskChunck* _preSortedExcBuffer;
@ -274,16 +274,19 @@ namespace DCFApixels.DragonECS
private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer; private UnsafeArray<EcsMaskChunck> _sortIncChunckBuffer;
private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer; private UnsafeArray<EcsMaskChunck> _sortExcChunckBuffer;
private readonly int _entityComponentMaskLength;
//private EcsAspect aspect; //private EcsAspect aspect;
public unsafe Enumerator(EcsSpan span, EcsAspect aspect) public unsafe Enumerator(EcsSpan span, EcsAspect aspect)
{ {
//this.aspect = aspect; //this.aspect = aspect;
_span = span.GetEnumerator(); _span = span.GetEnumerator();
_entitiesComponentMasks = aspect.World._entitiesComponentMasks; _entityComponentMasks = aspect.World._entityComponentMasks;
_sortIncChunckBuffer = aspect._sortIncChunckBuffer; _sortIncChunckBuffer = aspect._sortIncChunckBuffer;
_sortExcChunckBuffer = aspect._sortExcChunckBuffer; _sortExcChunckBuffer = aspect._sortExcChunckBuffer;
_entityComponentMaskLength = aspect.World._entityComponentMaskLength;
#region Sort #region Sort
UnsafeArray<int> _sortIncBuffer = aspect._sortIncBuffer; UnsafeArray<int> _sortIncBuffer = aspect._sortIncBuffer;
UnsafeArray<int> _sortExcBuffer = aspect._sortExcBuffer; UnsafeArray<int> _sortExcBuffer = aspect._sortExcBuffer;
@ -374,13 +377,13 @@ 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 ((_entitiesComponentMasks[e][bit.chankIndex] & bit.mask) != bit.mask) if ((_entityComponentMasks[e * _entityComponentMaskLength + bit.chankIndex] & bit.mask) != bit.mask)
goto skip; goto skip;
} }
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 ((_entitiesComponentMasks[e][bit.chankIndex] & bit.mask) > 0) if ((_entityComponentMasks[e * _entityComponentMaskLength + bit.chankIndex] & bit.mask) > 0)
goto skip; goto skip;
} }
return true; return true;

View File

@ -22,7 +22,9 @@ namespace DCFApixels.DragonECS
private int _delEntBufferCount = 0; private int _delEntBufferCount = 0;
private bool _isEnableAutoReleaseDelEntBuffer = true; private bool _isEnableAutoReleaseDelEntBuffer = true;
internal int[][] _entitiesComponentMasks = Array.Empty<int[]>(); internal int _entityComponentMaskLength;
internal int[] _entityComponentMasks = Array.Empty<int>();
private const int COMPONENT_MATRIX_MASK_BITSIZE = 32;
private long _version = 0; private long _version = 0;
@ -255,14 +257,25 @@ namespace DCFApixels.DragonECS
return *(entlong*)&x; return *(entlong*)&x;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsAlive(int entityID, short gen) { return _gens[entityID] == gen; } public bool IsAlive(int entityID, short gen)
{
return _gens[entityID] == gen;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsUsed(int entityID) { return _gens[entityID] >= 0; } public bool IsUsed(int entityID)
{
return _gens[entityID] >= 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public short GetGen(int entityID) { return _gens[entityID]; } public short GetGen(int entityID)
{
return _gens[entityID];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public short GetComponentsCount(int entityID) { return _componentCounts[entityID]; } public short GetComponentsCount(int entityID)
{
return _componentCounts[entityID];
}
public bool IsMatchesMask(EcsMask mask, int entityID) public bool IsMatchesMask(EcsMask mask, int entityID)
{ {
@ -292,10 +305,6 @@ namespace DCFApixels.DragonECS
} }
} }
} }
//public void Densify()
//{
// _entityDispenser.Sort();
//}
#endregion #endregion
#region Copy/Clone #region Copy/Clone
@ -367,7 +376,8 @@ namespace DCFApixels.DragonECS
{ {
ReleaseDelEntityBuffer(_delEntBufferCount); ReleaseDelEntityBuffer(_delEntBufferCount);
} }
public void ReleaseDelEntityBuffer(int count) //private UnsafeArray<int> _delBufferFilter = new UnsafeArray<int>(8);
public unsafe void ReleaseDelEntityBuffer(int count)
{ {
if (_delEntBufferCount <= 0) if (_delEntBufferCount <= 0)
{ {
@ -376,15 +386,15 @@ namespace DCFApixels.DragonECS
unchecked { _version++; } unchecked { _version++; }
count = Math.Clamp(count, 0, _delEntBufferCount); count = Math.Clamp(count, 0, _delEntBufferCount);
_delEntBufferCount -= count; _delEntBufferCount -= count;
ReadOnlySpan<int> buffser = new ReadOnlySpan<int>(_delEntBuffer, _delEntBufferCount, count); ReadOnlySpan<int> buffer = new ReadOnlySpan<int>(_delEntBuffer, _delEntBufferCount, count);
for (int i = 0; i < _poolsCount; i++) for (int i = 0; i < _poolsCount; i++)
{ {
_pools[i].OnReleaseDelEntityBuffer(buffser); _pools[i].OnReleaseDelEntityBuffer(buffer);
} }
_listeners.InvokeOnReleaseDelEntityBuffer(buffser); _listeners.InvokeOnReleaseDelEntityBuffer(buffer);
for (int i = 0; i < buffser.Length; i++) for (int i = 0; i < buffer.Length; i++)
{ {
int e = buffser[i]; int e = buffer[i];
_entityDispenser.Release(e); _entityDispenser.Release(e);
unchecked { _gens[e]++; }//up gen unchecked { _gens[e]++; }//up gen
_gens[e] |= DEATH_GEN_BIT; _gens[e] |= DEATH_GEN_BIT;
@ -408,14 +418,10 @@ namespace DCFApixels.DragonECS
Array.Resize(ref _gens, newSize); Array.Resize(ref _gens, newSize);
Array.Resize(ref _componentCounts, newSize); Array.Resize(ref _componentCounts, newSize);
Array.Resize(ref _delEntBuffer, newSize); Array.Resize(ref _delEntBuffer, newSize);
Array.Resize(ref _entitiesComponentMasks, newSize); _entityComponentMaskLength = _pools.Length / COMPONENT_MATRIX_MASK_BITSIZE + 1;
Array.Resize(ref _entityComponentMasks, newSize * _entityComponentMaskLength);
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitiesCapacity); ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitiesCapacity);
int maskLength = _pools.Length / 32 + 1;
for (int i = _entitiesCapacity; i < newSize; i++)
{
_entitiesComponentMasks[i] = new int[maskLength];
}
_entitiesCapacity = newSize; _entitiesCapacity = newSize;

View File

@ -136,10 +136,35 @@ namespace DCFApixels.DragonECS
Array.Resize(ref _poolComponentCounts, _pools.Length); Array.Resize(ref _poolComponentCounts, _pools.Length);
ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length); ArrayUtility.Fill(_pools, _nullPool, oldCapacity, oldCapacity - _pools.Length);
for (int i = 0; i < _entitiesCapacity; i++) //for (int i = 0; i < _entitiesCapacity; i++)
//{
// //Array.Resize(ref _entityComponentMasks[i], _pools.Length / 32 + 1);
//}
int newEntityComponentMaskLength = _pools.Length / COMPONENT_MATRIX_MASK_BITSIZE + 1;
int dif = newEntityComponentMaskLength - _entityComponentMaskLength;
if (dif > 0)
{ {
Array.Resize(ref _entitiesComponentMasks[i], _pools.Length / 32 + 1); int[] newEntityComponentMasks = new int[_entitiesCapacity * newEntityComponentMaskLength];
int indxMax = _entityComponentMaskLength * _entitiesCapacity;
int indx = 0;
int newIndx = 0;
int nextIndx = _entityComponentMaskLength;
while (indx < indxMax)
{
while (indx < nextIndx)
{
newEntityComponentMasks[newIndx] = _entityComponentMasks[indx];
indx++;
newIndx++;
}
newIndx += dif;
nextIndx += _entityComponentMaskLength;
}
_entityComponentMaskLength = newEntityComponentMaskLength;
_entityComponentMasks = newEntityComponentMasks;
} }
} }
if (_pools[componentTypeID] != _nullPool) if (_pools[componentTypeID] != _nullPool)
@ -160,14 +185,14 @@ namespace DCFApixels.DragonECS
{ {
_poolComponentCounts[componentTypeID]++; _poolComponentCounts[componentTypeID]++;
_componentCounts[entityID]++; _componentCounts[entityID]++;
_entitiesComponentMasks[entityID][maskBit.chankIndex] |= maskBit.mask; _entityComponentMasks[entityID * _entityComponentMaskLength + maskBit.chankIndex] |= 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)
{ {
_poolComponentCounts[componentTypeID]--; _poolComponentCounts[componentTypeID]--;
var count = --_componentCounts[entityID]; var count = --_componentCounts[entityID];
_entitiesComponentMasks[entityID][maskBit.chankIndex] &= ~maskBit.mask; _entityComponentMasks[entityID * _entityComponentMaskLength + maskBit.chankIndex] &= ~maskBit.mask;
if (count == 0 && IsUsed(entityID)) if (count == 0 && IsUsed(entityID))
{ {
@ -180,7 +205,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 (_entitiesComponentMasks[entityID][maskBit.chankIndex] & maskBit.mask) != maskBit.mask; return (_entityComponentMasks[entityID * _entityComponentMaskLength + maskBit.chankIndex] & maskBit.mask) != maskBit.mask;
} }
#endregion #endregion