update/fix lazy gen

This commit is contained in:
Mikhail 2024-02-29 22:42:33 +08:00
parent f67e6d59ea
commit a3a61d21da
5 changed files with 77 additions and 30 deletions

View File

@ -749,14 +749,16 @@ namespace DCFApixels.DragonECS
private EcsGroup _group; private EcsGroup _group;
public EcsWorld World => _group.World; public EcsWorld World => _group.World;
public bool IsReleased => _group.IsReleased; public bool IsReleased => _group.IsReleased;
public entlong[] Entities public EntitySlotInfo[] Entities
{ {
get get
{ {
entlong[] result = new entlong[_group.Count]; EntitySlotInfo[] result = new EntitySlotInfo[_group.Count];
int i = 0; int i = 0;
foreach (var e in _group) foreach (var e in _group)
result[i++] = _group.World.GetEntityLong(e); {
result[i++] = _group.World.GetEntitySlotInfoDebug(e);
}
return result; return result;
} }
} }

View File

@ -131,14 +131,16 @@ namespace DCFApixels.DragonECS
private int[] _values; private int[] _values;
private int _worldID; private int _worldID;
public EcsWorld World => EcsWorld.GetWorld(_worldID); public EcsWorld World => EcsWorld.GetWorld(_worldID);
public entlong[] Entities public EntitySlotInfo[] Entities
{ {
get get
{ {
entlong[] result = new entlong[_values.Length]; EntitySlotInfo[] result = new EntitySlotInfo[_values.Length];
int i = 0; int i = 0;
foreach (var e in _values) foreach (var e in _values)
result[i++] = World.GetEntityLong(e); {
result[i++] = World.GetEntitySlotInfoDebug(e);
}
return result; return result;
} }
} }

View File

@ -2,11 +2,29 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace DCFApixels.DragonECS namespace DCFApixels.DragonECS
{ {
public partial class EcsWorld : IEntityStorage public partial class EcsWorld : IEntityStorage
{ {
[StructLayout(LayoutKind.Explicit, Pack = 4, Size = 4 * 3)]
private struct EntitySlot
{
public static readonly EntitySlot Empty = new EntitySlot(SLEEPING_GEN_FLAG, 0, false);
[FieldOffset(0)]
public short gen;
[FieldOffset(2)]
public short componentsCount;
[FieldOffset(4)]
public bool isUsed;
public EntitySlot(short gen, short componentsCount, bool isUsed)
{
this.gen = gen;
this.componentsCount = componentsCount;
this.isUsed = isUsed;
}
}
public readonly short id; public readonly short id;
private IEcsWorldConfig _config; private IEcsWorldConfig _config;
@ -15,8 +33,9 @@ namespace DCFApixels.DragonECS
private IdDispenser _entityDispenser; private IdDispenser _entityDispenser;
private int _entitiesCount = 0; private int _entitiesCount = 0;
private int _entitiesCapacity = 0; private int _entitiesCapacity = 0;
private short[] _gens = Array.Empty<short>(); //старший бит указывает на то жива ли сущность //private short[] _gens = Array.Empty<short>(); //старший бит указывает на то жива ли сущность
private short[] _componentCounts = Array.Empty<short>(); //private short[] _componentCounts = Array.Empty<short>();
private EntitySlot[] _entities = Array.Empty<EntitySlot>();
private int[] _delEntBuffer = Array.Empty<int>(); private int[] _delEntBuffer = Array.Empty<int>();
private int _delEntBufferCount = 0; private int _delEntBufferCount = 0;
@ -135,7 +154,8 @@ namespace DCFApixels.DragonECS
public void Destroy() public void Destroy()
{ {
_entityDispenser = null; _entityDispenser = null;
_gens = null; //_gens = null;
//_componentCounts = null;
_pools = null; _pools = null;
_nullPool = null; _nullPool = null;
_worlds[id] = null; _worlds[id] = null;
@ -211,9 +231,12 @@ namespace DCFApixels.DragonECS
_entitiesCount++; _entitiesCount++;
if (_entitiesCapacity <= entityID) if (_entitiesCapacity <= entityID)
{ {
OnEntityDispenserResized(_gens.Length << 1); //OnEntityDispenserResized(_gens.Length << 1);
OnEntityDispenserResized(_entities.Length << 1);
} }
_gens[entityID] &= GEN_MASK; //_gens[entityID] &= GEN_MASK;
//_entities[entityID].gen &= GEN_MASK;
_entities[entityID].isUsed = true;
_entityListeners.InvokeOnNewEntity(entityID); _entityListeners.InvokeOnNewEntity(entityID);
} }
@ -239,7 +262,8 @@ namespace DCFApixels.DragonECS
#endif #endif
UpVersion(); UpVersion();
_delEntBuffer[_delEntBufferCount++] = entityID; _delEntBuffer[_delEntBufferCount++] = entityID;
_gens[entityID] |= DEATH_GEN_BIT; //_gens[entityID] |= DEATH_GEN_BIT;
_entities[entityID].isUsed = false;
_entitiesCount--; _entitiesCount--;
_entityListeners.InvokeOnDelEntity(entityID); _entityListeners.InvokeOnDelEntity(entityID);
} }
@ -249,6 +273,10 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public EcsSpan ToSpan() public EcsSpan ToSpan()
{ {
if (_isEnableAutoReleaseDelEntBuffer)
{
ReleaseDelEntityBufferAll();
}
return _entityDispenser.UsedToEcsSpan(id); return _entityDispenser.UsedToEcsSpan(id);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -260,29 +288,33 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe EntitySlotInfo GetEntitySlotInfoDebug(int entityID) public unsafe EntitySlotInfo GetEntitySlotInfoDebug(int entityID)
{ {
return new EntitySlotInfo(entityID, _gens[entityID], id); //return new EntitySlotInfo(entityID, _gens[entityID], id);
return new EntitySlotInfo(entityID, _entities[entityID].gen, id);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsAlive(int entityID, short gen) public bool IsAlive(int entityID, short gen)
{ {
ref short slotGen = ref _gens[entityID]; //ref short slotGen = ref _gens[entityID];
return slotGen == gen && slotGen >= 0; ref var slot = ref _entities[entityID];
return slot.gen == gen && slot.isUsed;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool IsUsed(int entityID) public bool IsUsed(int entityID)
{ {
return _entityDispenser.IsUsed(entityID); //return _entityDispenser.IsUsed(entityID);
return _entities[entityID].isUsed;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public short GetGen(int entityID) public short GetGen(int entityID)
{ {
unchecked unchecked
{ {
ref short slotGen = ref _gens[entityID]; //ref short slotGen = ref _gens[entityID];
ref short slotGen = ref _entities[entityID].gen;
if (slotGen < 0) if (slotGen < 0)
{ //up gen { //up gen
slotGen++; slotGen++;
slotGen &= GEN_MASK; slotGen &= GEN_MASK;
} }
return slotGen; return slotGen;
} }
@ -291,7 +323,8 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public short GetComponentsCount(int entityID) public short GetComponentsCount(int entityID)
{ {
return _componentCounts[entityID]; //return _componentCounts[entityID];
return _entities[entityID].componentsCount;
} }
public bool IsMatchesMask(EcsMask mask, int entityID) public bool IsMatchesMask(EcsMask mask, int entityID)
@ -327,7 +360,8 @@ namespace DCFApixels.DragonECS
int delCount = 0; int delCount = 0;
foreach (var e in Entities) foreach (var e in Entities)
{ {
if (_componentCounts[e] <= 0) //if (_componentCounts[e] <= 0)
if (_entities[e].componentsCount <= 0)
{ {
DelEntity(e); DelEntity(e);
delCount++; delCount++;
@ -349,7 +383,8 @@ namespace DCFApixels.DragonECS
int delCount = 0; int delCount = 0;
foreach (var e in Entities) foreach (var e in Entities)
{ {
if (_componentCounts[e] <= 0) //if (_componentCounts[e] <= 0)
if (_entities[e].componentsCount <= 0)
{ {
delCount++; delCount++;
} }
@ -448,7 +483,8 @@ namespace DCFApixels.DragonECS
for (int i = 0; i < slisedCount; i++) for (int i = 0; i < slisedCount; i++)
{ {
int e = _delEntBuffer[i]; int e = _delEntBuffer[i];
if (_componentCounts[e] <= 0) //if (_componentCounts[e] <= 0)
if (_entities[e].componentsCount <= 0)
{ {
int tmp = _delEntBuffer[i]; int tmp = _delEntBuffer[i];
_delEntBuffer[i] = _delEntBuffer[--slisedCount]; _delEntBuffer[i] = _delEntBuffer[--slisedCount];
@ -474,6 +510,7 @@ namespace DCFApixels.DragonECS
_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;
_entities[e].gen |= SLEEPING_GEN_FLAG;
} }
Densify(); Densify();
} }
@ -491,13 +528,15 @@ namespace DCFApixels.DragonECS
[MethodImpl(MethodImplOptions.NoInlining)] [MethodImpl(MethodImplOptions.NoInlining)]
private void OnEntityDispenserResized(int newSize) private void OnEntityDispenserResized(int newSize)
{ {
Array.Resize(ref _gens, newSize); //Array.Resize(ref _gens, newSize);
Array.Resize(ref _componentCounts, newSize); //Array.Resize(ref _componentCounts, newSize);
Array.Resize(ref _entities, newSize);
Array.Resize(ref _delEntBuffer, newSize); Array.Resize(ref _delEntBuffer, newSize);
_entityComponentMaskLength = _pools.Length / COMPONENT_MATRIX_MASK_BITSIZE + 1; _entityComponentMaskLength = _pools.Length / COMPONENT_MATRIX_MASK_BITSIZE + 1;
Array.Resize(ref _entityComponentMasks, newSize * _entityComponentMaskLength); Array.Resize(ref _entityComponentMasks, newSize * _entityComponentMaskLength);
ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitiesCapacity); //ArrayUtility.Fill(_gens, DEATH_GEN_BIT, _entitiesCapacity);
ArrayUtility.Fill(_entities, EntitySlot.Empty, _entitiesCapacity);
_entitiesCapacity = newSize; _entitiesCapacity = newSize;

View File

@ -210,14 +210,16 @@ namespace DCFApixels.DragonECS
private void RegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit) private void RegisterEntityComponent(int entityID, int componentTypeID, EcsMaskChunck maskBit)
{ {
_poolComponentCounts[componentTypeID]++; _poolComponentCounts[componentTypeID]++;
_componentCounts[entityID]++; //_componentCounts[entityID]++;
_entities[entityID].componentsCount++;
_entityComponentMasks[entityID * _entityComponentMaskLength + 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];
var count = --_entities[entityID].componentsCount;
_entityComponentMasks[entityID * _entityComponentMaskLength + maskBit.chankIndex] &= ~maskBit.mask; _entityComponentMasks[entityID * _entityComponentMaskLength + maskBit.chankIndex] &= ~maskBit.mask;
if (count == 0 && IsUsed(entityID)) if (count == 0 && IsUsed(entityID))
@ -239,7 +241,8 @@ namespace DCFApixels.DragonECS
{ {
chunk = newChunk; chunk = newChunk;
_poolComponentCounts[componentTypeID]++; _poolComponentCounts[componentTypeID]++;
_componentCounts[entityID]++; //_componentCounts[entityID]++;
_entities[entityID].componentsCount++;
return true; return true;
} }
return false; return false;
@ -252,7 +255,8 @@ namespace DCFApixels.DragonECS
if (chunk != newChunk) if (chunk != newChunk)
{ {
_poolComponentCounts[componentTypeID]--; _poolComponentCounts[componentTypeID]--;
var count = --_componentCounts[entityID]; //var count = --_componentCounts[entityID];
var count = --_entities[entityID].componentsCount;
chunk = newChunk; chunk = newChunk;
if (count == 0 && IsUsed(entityID)) if (count == 0 && IsUsed(entityID))

View File

@ -17,7 +17,7 @@ namespace DCFApixels.DragonECS
public partial class EcsWorld public partial class EcsWorld
{ {
private const short GEN_MASK = 0x7fff; private const short GEN_MASK = 0x7fff;
private const short DEATH_GEN_BIT = short.MinValue; private const short SLEEPING_GEN_FLAG = short.MinValue;
private const int DEL_ENT_BUFFER_SIZE_OFFSET = 5; private const int DEL_ENT_BUFFER_SIZE_OFFSET = 5;
private const int DEL_ENT_BUFFER_MIN_SIZE = 64; private const int DEL_ENT_BUFFER_MIN_SIZE = 64;