fix value pool

This commit is contained in:
Mikhail 2026-03-18 14:39:34 +08:00
parent c347011452
commit 1c6edc6e6b
2 changed files with 42 additions and 24 deletions

View File

@ -124,6 +124,10 @@ namespace DCFApixels.DragonECS.Core.Internal
{ {
return new HMem<byte>(Realloc(Handler.FromDataPtr(target), newByteLength), newByteLength); return new HMem<byte>(Realloc(Handler.FromDataPtr(target), newByteLength), newByteLength);
} }
public static HMem<T> Realloc<T>(HMem<T> target, int newCount) where T : unmanaged
{
return new HMem<T>(Realloc_Internal(target, Marshal.SizeOf<T>() * newCount, typeof(T)), newCount);
}
public static HMem<T> Realloc<T>(Handler target, int newCount) where T : unmanaged public static HMem<T> Realloc<T>(Handler target, int newCount) where T : unmanaged
{ {
return new HMem<T>(Realloc_Internal(target, Marshal.SizeOf<T>() * newCount, typeof(T)), newCount); return new HMem<T>(Realloc_Internal(target, Marshal.SizeOf<T>() * newCount, typeof(T)), newCount);

View File

@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static DCFApixels.DragonECS.Core.Internal.MemoryAllocator;
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
using Unity.IL2CPP.CompilerServices; using Unity.IL2CPP.CompilerServices;
#endif #endif
@ -42,7 +43,7 @@ namespace DCFApixels.DragonECS
private EcsMaskChunck _maskBit; private EcsMaskChunck _maskBit;
public int* _mapping; // index = entityID / value = itemIndex;/ value = 0 = no entityID. public int* _mapping; // index = entityID / value = itemIndex;/ value = 0 = no entityID.
public void* _items; // dense; _items[0] - fake component. public T* _items; // dense; _items[0] - fake component.
public int _itemsLength; public int _itemsLength;
public int _itemsCount; public int _itemsCount;
public int* _recycledItems; public int* _recycledItems;
@ -50,6 +51,10 @@ namespace DCFApixels.DragonECS
public int _recycledItemsCount; public int _recycledItemsCount;
private readonly EcsValuePoolSharedStore* _sharedStore; private readonly EcsValuePoolSharedStore* _sharedStore;
private HMem<int> _mappingHandler;
private HMem<T> _itemsHandler;
private HMem<int> _recycledItemsHandler;
private readonly IEcsComponentLifecycle<T> _customLifecycle = EcsComponentLifecycle<T>.CustomHandler; private readonly IEcsComponentLifecycle<T> _customLifecycle = EcsComponentLifecycle<T>.CustomHandler;
private readonly bool _isCustomLifecycle = EcsComponentLifecycle<T>.IsCustom; private readonly bool _isCustomLifecycle = EcsComponentLifecycle<T>.IsCustom;
private readonly IEcsComponentCopy<T> _customCopy = EcsComponentCopy<T>.CustomHandler; private readonly IEcsComponentCopy<T> _customCopy = EcsComponentCopy<T>.CustomHandler;
@ -96,14 +101,14 @@ namespace DCFApixels.DragonECS
{ {
if (_sharedStore == null) if (_sharedStore == null)
{ {
_sharedStore = MemoryAllocator.Alloc<EcsValuePoolSharedStore>(1).Ptr; _sharedStore = Alloc<EcsValuePoolSharedStore>(1).Ptr;
} }
} }
public EcsValuePool(int capacity, int recycledCapacity = -1) public EcsValuePool(int capacity, int recycledCapacity = -1)
{ {
if (_sharedStore == null) if (_sharedStore == null)
{ {
_sharedStore = MemoryAllocator.Alloc<EcsValuePoolSharedStore>(1).Ptr; _sharedStore = Alloc<EcsValuePoolSharedStore>(1).Ptr;
} }
capacity = ArrayUtility.NextPow2(capacity); capacity = ArrayUtility.NextPow2(capacity);
if (recycledCapacity < 0) if (recycledCapacity < 0)
@ -111,10 +116,12 @@ namespace DCFApixels.DragonECS
recycledCapacity = capacity / 2; recycledCapacity = capacity / 2;
} }
_itemsLength = capacity; _itemsLength = capacity;
_items = MemoryAllocator.Alloc<T>(_itemsLength).Ptr; _itemsHandler = Alloc<T>(_itemsLength);
_items = _itemsHandler.Ptr;
_sharedStore->_items = _items; _sharedStore->_items = _items;
_recycledItemsLength = recycledCapacity; _recycledItemsLength = recycledCapacity;
_recycledItems = MemoryAllocator.Alloc<int>(_recycledItemsLength).Ptr; _recycledItemsHandler = Alloc<int>(_recycledItemsLength);
_recycledItems = _recycledItemsHandler.Ptr;
} }
void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID) void IEcsPoolImplementation.OnInit(EcsWorld world, EcsWorld.PoolsMediator mediator, int componentTypeID)
{ {
@ -126,29 +133,33 @@ namespace DCFApixels.DragonECS
_sharedStore->_worldID = _worldID; _sharedStore->_worldID = _worldID;
_sharedStore->_componentTypeID = _componentTypeID; _sharedStore->_componentTypeID = _componentTypeID;
_mapping = MemoryAllocator.AllocAndInit<int>(world.Capacity).Ptr; _mappingHandler = AllocAndInit<int>(world.Capacity);
_mappingLength = world.Capacity; _mapping = _mappingHandler.Ptr;
_sharedStore->_mapping = _mapping; _sharedStore->_mapping = _mapping;
var worldConfig = world.Configs.GetWorldConfigOrDefault(); var worldConfig = world.Configs.GetWorldConfigOrDefault();
if (_items == null) if (_items == null)
{ {
_itemsLength = ArrayUtility.NextPow2(worldConfig.PoolComponentsCapacity); _itemsLength = ArrayUtility.NextPow2(worldConfig.PoolComponentsCapacity);
_items = MemoryAllocator.Alloc<T>(_itemsLength).Ptr; _itemsHandler = Alloc<T>(_itemsLength);
_items = _itemsHandler.Ptr;
_sharedStore->_items = _items; _sharedStore->_items = _items;
} }
if (_recycledItems == null) if (_recycledItems == null)
{ {
_recycledItemsLength = worldConfig.PoolRecycledComponentsCapacity; _recycledItemsLength = worldConfig.PoolRecycledComponentsCapacity;
_recycledItems = MemoryAllocator.Alloc<int>(_recycledItemsLength).Ptr; _recycledItemsHandler = Alloc<int>(_recycledItemsLength);
_recycledItems = _recycledItemsHandler.Ptr;
} }
} }
void IEcsPoolImplementation.OnWorldDestroy() { } void IEcsPoolImplementation.OnWorldDestroy() { }
~EcsValuePool() ~EcsValuePool()
{ {
MemoryAllocator.Free(_mapping); Free(_mappingHandler);
MemoryAllocator.Free(_items); Free(_itemsHandler);
MemoryAllocator.Free(_sharedStore); Free(_recycledItemsHandler);
MemoryAllocator.Free(_recycledItems);
Free(_sharedStore);
} }
#endregion #endregion
@ -180,12 +191,13 @@ namespace DCFApixels.DragonECS
if (itemIndex >= _itemsLength) if (itemIndex >= _itemsLength)
{ {
_itemsLength = ArrayUtility.NextPow2(_itemsLength << 1); _itemsLength = ArrayUtility.NextPow2(_itemsLength << 1);
_items = MemoryAllocator.Realloc(_items, _itemsLength).Ptr; _itemsHandler = Realloc(_itemsHandler, _itemsLength);
_items = _itemsHandler.Ptr;
_sharedStore->_items = _items; _sharedStore->_items = _items;
} }
} }
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
ref T result = ref ((T*)_items)[itemIndex]; ref T result = ref _items[itemIndex];
EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref result, _worldID, entityID); EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref result, _worldID, entityID);
return ref result; return ref result;
} }
@ -195,7 +207,7 @@ namespace DCFApixels.DragonECS
#if DEBUG // не нужен STAB_MODE #if DEBUG // не нужен STAB_MODE
if (!Has(entityID)) { EcsPoolThrowHelper.ThrowNotHaveComponent<T>(entityID); } if (!Has(entityID)) { EcsPoolThrowHelper.ThrowNotHaveComponent<T>(entityID); }
#endif #endif
return ref ((T*)_items)[_mapping[entityID]]; return ref _items[_mapping[entityID]];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref readonly T Read(int entityID) public ref readonly T Read(int entityID)
@ -203,7 +215,7 @@ namespace DCFApixels.DragonECS
#if DEBUG // не нужен STAB_MODE #if DEBUG // не нужен STAB_MODE
if (!Has(entityID)) { EcsPoolThrowHelper.ThrowNotHaveComponent<T>(entityID); } if (!Has(entityID)) { EcsPoolThrowHelper.ThrowNotHaveComponent<T>(entityID); }
#endif #endif
return ref ((T*)_items)[_mapping[entityID]]; return ref _items[_mapping[entityID]];
} }
public ref T TryAddOrGet(int entityID) public ref T TryAddOrGet(int entityID)
{ {
@ -229,14 +241,15 @@ namespace DCFApixels.DragonECS
if (itemIndex >= _itemsLength) if (itemIndex >= _itemsLength)
{ {
_itemsLength = ArrayUtility.NextPow2(_itemsLength << 1); _itemsLength = ArrayUtility.NextPow2(_itemsLength << 1);
_items = MemoryAllocator.Realloc(_items, _itemsLength).Ptr; _itemsHandler = Realloc(_itemsHandler, _itemsLength);
_items = _itemsHandler.Ptr;
_sharedStore->_items = _items; _sharedStore->_items = _items;
} }
} }
_mediator.RegisterComponent(entityID, _componentTypeID, _maskBit); _mediator.RegisterComponent(entityID, _componentTypeID, _maskBit);
EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref ((T*)_items)[itemIndex], _worldID, entityID); EcsComponentLifecycle<T>.OnAdd(_isCustomLifecycle, _customLifecycle, ref _items[itemIndex], _worldID, entityID);
} //Add block end } //Add block end
return ref ((T*)_items)[itemIndex]; return ref _items[itemIndex];
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Has(int entityID) public bool Has(int entityID)
@ -258,7 +271,8 @@ namespace DCFApixels.DragonECS
if (_recycledItemsCount >= _recycledItemsLength) if (_recycledItemsCount >= _recycledItemsLength)
{ {
_recycledItemsLength = ArrayUtility.NextPow2(_recycledItemsLength << 1); _recycledItemsLength = ArrayUtility.NextPow2(_recycledItemsLength << 1);
_recycledItems = MemoryAllocator.Realloc<int>(_recycledItems, _recycledItemsLength).Ptr; _recycledItemsHandler = Realloc(_recycledItemsHandler, _recycledItemsLength);
_recycledItems = _recycledItemsHandler.Ptr;
} }
_recycledItems[_recycledItemsCount++] = itemIndex; _recycledItems[_recycledItemsCount++] = itemIndex;
itemIndex = 0; itemIndex = 0;
@ -314,12 +328,12 @@ namespace DCFApixels.DragonECS
#endregion #endregion
#region Callbacks #region Callbacks
private int _mappingLength;
void IEcsPoolImplementation.OnWorldResize(int newSize) void IEcsPoolImplementation.OnWorldResize(int newSize)
{ {
_mapping = MemoryAllocator.ReallocAndInit(_mapping, _mappingLength, newSize).Ptr; _mappingHandler = ReallocAndInit<int>(_mappingHandler, newSize);
_mapping = _mappingHandler.Ptr;
_sharedStore->_mapping = _mapping; _sharedStore->_mapping = _mapping;
_mappingLength = newSize;
} }
void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer) void IEcsPoolImplementation.OnReleaseDelEntityBuffer(ReadOnlySpan<int> buffer)
{ {