update framework

This commit is contained in:
szy73711 committed 2022-11-13 02:16:19 +08:00
1 parent 3a1e97df6f
commit e3f449f183
31 files changed
+984 -307

No files matched your search

@@ -0,0 +1,25 @@
using System;
namespace GameCore.TinyECS
{
public struct ComponentId
{
struct Inner<T> where T : unmanaged
{
public int id;
private Inner(int i) => id = i;
public static Inner<T> Instance = default;
}
static int currentId;
public static int Get<T>() where T : unmanaged
{
if (Inner<T>.Instance.id == 0)
{
Inner<T>.Instance.id = ++currentId;
}
return Inner<T>.Instance.id;
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27dc063854d0042ba9329b5bf058f2a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -15,34 +15,12 @@ namespace GameCore.TinyECS
this.generation = generation;
}
public override string ToString()
{
return $"Entity<{type}>({index},{generation})";
}
public override string ToString() => $"Entity<{type}>({index},{generation})";
public bool Equals(Entity<TEnum> other) => type.Equals(other.type) && index == other.index && generation == other.generation;
public override bool Equals(object obj) => obj is Entity<TEnum> other && Equals(other);
public override int GetHashCode() => HashCode.Combine(type, index, generation);
public static bool operator ==(Entity<TEnum> lhs, Entity<TEnum> rhs) => lhs.Equals(rhs);
public static bool operator !=(Entity<TEnum> lhs, Entity<TEnum> rhs) => !(lhs == rhs);
public bool Equals(Entity<TEnum> other)
{
return type.Equals(other.type) && index == other.index && generation == other.generation;
}
public override bool Equals(object obj)
{
return obj is Entity<TEnum> other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(type, index, generation);
}
public static bool operator ==(Entity<TEnum> lhs, Entity<TEnum> rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(Entity<TEnum> lhs, Entity<TEnum> rhs)
{
return !(lhs == rhs);
}
}
}
@@ -0,0 +1,201 @@
using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using System.Diagnostics;
namespace GameCore.TinyECS
{
public partial struct EntityDataBlockMeta
{
public FixedList64Bytes<byte> componentIdToIndex;
public FixedList128Bytes<short> componentIdToOffset;
public int elementSize;
public int elementAlign;
}
public unsafe struct EntityDataBlockChain : IDisposable
{
public readonly EntityDataBlockMeta blockMeta;
private FixedList512Bytes<IntPtr> blockPtrList;
private int maxElementCountPerBlock;
private int elementCount;
public int BlockCount => blockPtrList.Length;
public int BlockCapacity => blockPtrList.Capacity;
public int ElementCount => elementCount;
public int MaxElementCount => MaxElementCountPerBlock * BlockCapacity;
public int MaxElementCountPerBlock => maxElementCountPerBlock;
public bool IsFull => elementCount == MaxElementCount;
public bool IsEmpty => elementCount == 0;
public EntityDataBlockChain(EntityDataBlockMeta blockMeta, int maxElementCountPerBlock)
{
this.blockMeta = blockMeta;
blockPtrList = default;
this.maxElementCountPerBlock = maxElementCountPerBlock;
elementCount = 0;
}
public void Dispose()
{
for (var i = BlockCount - 1; i >= 0; --i)
{
ReleaseBlock(i);
}
}
void AllocBlock()
{
var bufferSize = blockMeta.elementSize * maxElementCountPerBlock;
var ptr = UnsafeUtility.Malloc(bufferSize, blockMeta.elementAlign, Allocator.Persistent);
blockPtrList.Add((IntPtr)ptr);
}
void ReleaseBlock(int blockIndex)
{
var pBlock = (void*)blockPtrList[blockIndex];
if (pBlock != null)
{
UnsafeUtility.Free(pBlock, Allocator.Persistent);
blockPtrList.RemoveAt(blockIndex);
}
}
void* ElementPtrAt(int elementIndex)
{
var blockIndex = elementIndex / maxElementCountPerBlock;
var pBlock = blockPtrList[blockIndex];
return (byte*)pBlock + elementIndex * blockMeta.elementSize;
}
void* ComponentPtrAt<T>(int elementIndex) where T : unmanaged
{
var componentId = ComponentId.Get<T>();
var componentIndex = blockMeta.componentIdToIndex[componentId];
if (componentIndex > 0)
{
var pElement = ElementPtrAt(elementIndex);
return (byte*)pElement + blockMeta.componentIdToOffset[componentId];
}
return null;
}
[Conditional("DEBUG")]
void CheckElementIndex(int index)
{
if (index < 0 || index >= elementCount)
throw new IndexOutOfRangeException($"Invalid index: {index}");
}
[Conditional("DEBUG")]
void CheckBlockIndex(int index)
{
if (index < 0 || index > (elementCount / maxElementCountPerBlock))
throw new IndexOutOfRangeException($"Invalid index: {index}");
}
public void Clear()
{
elementCount = 0;
}
public void Add()
{
if (elementCount % maxElementCountPerBlock == 0)
{
if (IsFull)
throw new OutOfMemoryException("Block chain is full!");
var blockIndex = elementCount / maxElementCountPerBlock;
if (blockIndex >= BlockCount)
AllocBlock();
}
void* ptr = ElementPtrAt(elementCount);
UnsafeUtility.MemClear(ptr, blockMeta.elementSize);
elementCount++;
}
public void Remove(int index)
{
CheckElementIndex(index);
if (index != elementCount - 1)
{
var src = ElementPtrAt(elementCount - 1);
var dst = ElementPtrAt(index);
UnsafeUtility.MemCpy(dst, src, blockMeta.elementSize);
}
elementCount--;
}
public ref T GetData<T>(int index) where T : unmanaged
{
CheckElementIndex(index);
var pComponent = ComponentPtrAt<T>(index);
if (pComponent == null)
throw new Exception($"Invalid component type: {typeof(T)}");
return ref UnsafeUtility.AsRef<T>(pComponent);
}
public EntityDataBlockView AsBlockView(int blockIndex)
{
CheckBlockIndex(blockIndex);
var ptr = (void*)blockPtrList[blockIndex];
return new(ptr, blockMeta, maxElementCountPerBlock * blockIndex, elementCount);
}
}
public unsafe readonly struct EntityDataBlockView
{
private readonly void* ptr;
public readonly EntityDataBlockMeta meta;
public readonly int elementStartIndex;
public readonly int elementCount;
public EntityDataBlockView(void* ptr, EntityDataBlockMeta meta, int elementStartIndex, int elementCount)
{
this.ptr = ptr;
this.meta = meta;
this.elementStartIndex = elementStartIndex;
this.elementCount = elementCount;
}
void* ElementPtrAt(int elementIndex)
{
return (byte*)ptr + elementIndex * meta.elementSize;
}
void* ComponentPtrAt<T>(int elementIndex) where T : unmanaged
{
var componentId = ComponentId.Get<T>();
var componentIndex = meta.componentIdToIndex[componentId];
if (componentIndex > 0)
{
var pElement = ElementPtrAt(elementIndex);
return (byte*)pElement + meta.componentIdToOffset[componentId];
}
return null;
}
[Conditional("DEBUG")]
void CheckIndex(int index)
{
if (index < elementStartIndex || index >= elementStartIndex + elementCount)
throw new IndexOutOfRangeException($"Invalid index: {index}");
}
public ref T GetData<T>(int index) where T : unmanaged
{
var pComponent = ComponentPtrAt<T>(index);
if (pComponent == null)
throw new Exception($"Invalid component type: {typeof(T)}");
return ref UnsafeUtility.AsRef<T>(pComponent);
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 24392c1216204b6ea64acd57bb43441b
timeCreated: 1668251924
@@ -0,0 +1,45 @@
using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using System.Diagnostics;
using GameCore.LowLevel;
namespace GameCore.TinyECS
{
public partial struct EntityDataBlockMeta
{
public static EntityDataBlockMeta Create<T1>()
where T1 : unmanaged
{
var meta = new EntityDataBlockMeta();
meta.componentIdToIndex.Length = meta.componentIdToIndex.Capacity;
meta.componentIdToOffset.Length = meta.componentIdToOffset.Capacity;
var id1 = ComponentId.Get<T1>();
meta.componentIdToIndex[id1] = 1;
meta.componentIdToOffset[id1] = 0;
meta.elementSize = UnsafeUtility.SizeOf<T1>();
meta.elementAlign = UnsafeUtility.AlignOf<T1>();
return meta;
}
public static EntityDataBlockMeta Create<T1, T2>()
where T1 : unmanaged
where T2 : unmanaged
{
var meta = new EntityDataBlockMeta();
meta.componentIdToIndex.Length = meta.componentIdToIndex.Capacity;
meta.componentIdToOffset.Length = meta.componentIdToOffset.Capacity;
var id1 = ComponentId.Get<T1>();
var id2 = ComponentId.Get<T2>();
meta.componentIdToIndex[id1] = 1;
meta.componentIdToIndex[id2] = 2;
meta.componentIdToOffset[id1] = (short)StructUtility.OffsetOf<(T1, T2), T1>();
meta.componentIdToOffset[id2] = (short)StructUtility.OffsetOf<(T1, T2), T2>();
meta.elementSize = UnsafeUtility.SizeOf<(T1, T2)>();
meta.elementAlign = UnsafeUtility.AlignOf<(T2, T2)>();
return meta;
}
}
}
@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c9227b743e78463b8df770cefc98fb18
timeCreated: 1668274486
@@ -0,0 +1,14 @@
using System;
using Unity.Collections;
using Unity.Mathematics;
namespace GameCore.TinyECS
{
public struct EntityDataSet : IDisposable
{
public void Dispose()
{
//TODO
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 842aeb285b0ae4d48af690621927f619
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -1,9 +1,10 @@
{
"name": "TinyECS.Runtime",
"name": "nimin.tinyecs",
"rootNamespace": "",
"references": [
"Unity.Collections",
"Unity.Mathematics"
"Unity.Mathematics",
"nimin.lowlevel"
],
"includePlatforms": [
"Android",
@@ -23,7 +24,7 @@
"XboxOne"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"allowUnsafeCode": true,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
@@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: c2bd585c8e44341079d076e23cd9d3eb
guid: 9cf4bf50619414a2296aa8fb1643a952
AssemblyDefinitionImporter:
externalObjects: {}
userData: