replace bitset
parent
05fa578652
commit
d4115b231c
|
@ -1,33 +0,0 @@
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Encompass
|
|
||||||
{
|
|
||||||
internal class BitArrayPool
|
|
||||||
{
|
|
||||||
private Stack<BitArray> bitArrays;
|
|
||||||
|
|
||||||
public BitArrayPool(int capacity)
|
|
||||||
{
|
|
||||||
bitArrays = new Stack<BitArray>(capacity);
|
|
||||||
|
|
||||||
for (var i = 0; i < capacity; i++)
|
|
||||||
{
|
|
||||||
bitArrays.Push(new BitArray(128));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitArray Obtain(int size)
|
|
||||||
{
|
|
||||||
var bitArray = bitArrays.Pop();
|
|
||||||
bitArray.Length = size;
|
|
||||||
bitArray.SetAll(false);
|
|
||||||
return bitArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Free(BitArray bitArray)
|
|
||||||
{
|
|
||||||
bitArrays.Push(bitArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,182 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Encompass.Collections
|
|
||||||
{
|
|
||||||
public static class BitSetBuilder
|
|
||||||
{
|
|
||||||
public static BitSet Zeroes()
|
|
||||||
{
|
|
||||||
return new BitSet(VectorBuilder.Zeroes(), VectorBuilder.Zeroes(), VectorBuilder.Zeroes(), VectorBuilder.Zeroes());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static BitSet Ones()
|
|
||||||
{
|
|
||||||
return new BitSet(VectorBuilder.Ones(), VectorBuilder.Ones(), VectorBuilder.Ones(), VectorBuilder.Ones());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class VectorBuilder
|
|
||||||
{
|
|
||||||
static readonly uint[] zeroes = new uint[Vector<uint>.Count]; // max size of a Vector<T> is 8 uints
|
|
||||||
static readonly uint[] ones = Enumerable.Repeat(uint.MaxValue, Vector<uint>.Count).ToArray();
|
|
||||||
static uint[] builderInts = new uint[Vector<uint>.Count];
|
|
||||||
|
|
||||||
private static void ResetBuilder()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < Vector<uint>.Count; i++)
|
|
||||||
{
|
|
||||||
builderInts[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector<uint> Zeroes()
|
|
||||||
{
|
|
||||||
return new Vector<uint>(zeroes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector<uint> Ones()
|
|
||||||
{
|
|
||||||
return new Vector<uint>(ones);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector<uint> Build(int index)
|
|
||||||
{
|
|
||||||
if (index > Vector<uint>.Count * 32) { throw new System.ArgumentOutOfRangeException(nameof(index)); }
|
|
||||||
ResetBuilder();
|
|
||||||
builderInts[index / 32] |= (uint)(1 << (index % 32));
|
|
||||||
return new Vector<uint>(builderInts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct BitSet
|
|
||||||
{
|
|
||||||
public static int VectorLength { get { return Vector<uint>.Count * 32; } }
|
|
||||||
|
|
||||||
public Vector<uint> A { get; }
|
|
||||||
public Vector<uint> B { get; }
|
|
||||||
public Vector<uint> C { get; }
|
|
||||||
public Vector<uint> D { get; }
|
|
||||||
|
|
||||||
internal BitSet(Vector<uint> a, Vector<uint> b, Vector<uint> c, Vector<uint> d)
|
|
||||||
{
|
|
||||||
A = a;
|
|
||||||
B = b;
|
|
||||||
C = c;
|
|
||||||
D = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitSet And(BitSet other)
|
|
||||||
{
|
|
||||||
return new BitSet(A & other.A, B & other.B, C & other.C, D & other.D);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitSet Or(BitSet other)
|
|
||||||
{
|
|
||||||
return new BitSet(A | other.A, B | other.B, C | other.C, D | other.D);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitSet Not()
|
|
||||||
{
|
|
||||||
return new BitSet(~A, ~B, ~C, ~D);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitSet Set(int index)
|
|
||||||
{
|
|
||||||
if (index < VectorLength)
|
|
||||||
{
|
|
||||||
return new BitSet(A | VectorBuilder.Build(index % VectorLength), B, C, D);
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 2)
|
|
||||||
{
|
|
||||||
return new BitSet(A, B | VectorBuilder.Build(index % VectorLength), C, D);
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 3)
|
|
||||||
{
|
|
||||||
return new BitSet(A, B, C | VectorBuilder.Build(index % VectorLength), D);
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 4)
|
|
||||||
{
|
|
||||||
return new BitSet(A, B, C, D | VectorBuilder.Build(index % VectorLength));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new System.ArgumentOutOfRangeException(nameof(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitSet UnSet(int index)
|
|
||||||
{
|
|
||||||
if (index < VectorLength)
|
|
||||||
{
|
|
||||||
return new BitSet(A & ~VectorBuilder.Build(index % VectorLength), B, C, D);
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 2)
|
|
||||||
{
|
|
||||||
return new BitSet(A, B & ~VectorBuilder.Build(index % VectorLength), C, D);
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 3)
|
|
||||||
{
|
|
||||||
return new BitSet(A, B, C & ~VectorBuilder.Build(index % VectorLength), D);
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 4)
|
|
||||||
{
|
|
||||||
return new BitSet(A, B, C, D & ~VectorBuilder.Build(index % VectorLength));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new System.ArgumentOutOfRangeException(nameof(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Get(int index)
|
|
||||||
{
|
|
||||||
var vectorIndex = index % VectorLength;
|
|
||||||
if (index < VectorLength)
|
|
||||||
{
|
|
||||||
return (A[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 2)
|
|
||||||
{
|
|
||||||
return (B[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 3)
|
|
||||||
{
|
|
||||||
return (C[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
|
||||||
}
|
|
||||||
else if (index < VectorLength * 4)
|
|
||||||
{
|
|
||||||
return (D[vectorIndex / 32] & (uint)(1 << vectorIndex % 32)) != 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new System.ArgumentOutOfRangeException(nameof(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AllTrue()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < Vector<uint>.Count; i++)
|
|
||||||
{
|
|
||||||
if (A[i] != uint.MaxValue) { return false; }
|
|
||||||
if (B[i] != uint.MaxValue) { return false; }
|
|
||||||
if (C[i] != uint.MaxValue) { return false; }
|
|
||||||
if (D[i] != uint.MaxValue) { return false; }
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AllFalse()
|
|
||||||
{
|
|
||||||
for (var i = 0; i < Vector<uint>.Count; i++)
|
|
||||||
{
|
|
||||||
if (A[i] != 0) { return false; }
|
|
||||||
if (B[i] != 0) { return false; }
|
|
||||||
if (C[i] != 0) { return false; }
|
|
||||||
if (D[i] != 0) { return false; }
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,12 @@
|
||||||
using Encompass.Collections;
|
using MoonTools.FastCollections;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Encompass
|
namespace Encompass
|
||||||
{
|
{
|
||||||
internal class ComponentBitSet
|
internal class ComponentBitSet
|
||||||
{
|
{
|
||||||
Dictionary<int, BitSet> entities = new Dictionary<int, BitSet>();
|
Dictionary<int, BitSet512> entities = new Dictionary<int, BitSet512>();
|
||||||
Dictionary<Type, int> TypeToIndex { get; }
|
Dictionary<Type, int> TypeToIndex { get; }
|
||||||
|
|
||||||
public ComponentBitSet(Dictionary<Type, int> typeToIndex)
|
public ComponentBitSet(Dictionary<Type, int> typeToIndex)
|
||||||
|
@ -22,7 +21,7 @@ namespace Encompass
|
||||||
|
|
||||||
public void AddEntity(int entityID)
|
public void AddEntity(int entityID)
|
||||||
{
|
{
|
||||||
entities.Add(entityID, BitSetBuilder.Zeroes());
|
entities.Add(entityID, BitSet512.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set<TComponent>(int entityID) where TComponent : struct, IComponent
|
public void Set<TComponent>(int entityID) where TComponent : struct, IComponent
|
||||||
|
@ -47,9 +46,9 @@ namespace Encompass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitSet EntityBitArray(int entityID)
|
public BitSet512 EntityBitArray(int entityID)
|
||||||
{
|
{
|
||||||
return entities.ContainsKey(entityID) ? entities[entityID] : BitSetBuilder.Zeroes();
|
return entities.ContainsKey(entityID) ? entities[entityID] : BitSet512.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
using Encompass.Collections;
|
using MoonTools.FastCollections;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace Encompass
|
||||||
return Stores.ContainsKey(type) && Stores[type].Has(entityID);
|
return Stores.ContainsKey(type) && Stores[type].Has(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitSet EntityBitArray(int entityID)
|
public BitSet512 EntityBitArray(int entityID)
|
||||||
{
|
{
|
||||||
return ComponentBitSet.EntityBitArray(entityID);
|
return ComponentBitSet.EntityBitArray(entityID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Reflection;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Encompass.Exceptions;
|
using Encompass.Exceptions;
|
||||||
using Encompass.Collections;
|
using MoonTools.FastCollections;
|
||||||
|
|
||||||
namespace Encompass
|
namespace Encompass
|
||||||
{
|
{
|
||||||
|
@ -686,36 +686,36 @@ namespace Encompass
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal void BuildEntityQuery()
|
internal void BuildEntityQuery()
|
||||||
{
|
{
|
||||||
var withMask = BitSetBuilder.Zeroes();
|
var withMask = BitSet512.Zero;
|
||||||
foreach (var type in queryWithTypes)
|
foreach (var type in queryWithTypes)
|
||||||
{
|
{
|
||||||
withMask = withMask.Set(componentUpdateManager.TypeToIndex[type]);
|
withMask = withMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var withoutMask = BitSetBuilder.Zeroes();
|
var withoutMask = BitSet512.Zero;
|
||||||
foreach (var type in queryWithoutTypes)
|
foreach (var type in queryWithoutTypes)
|
||||||
{
|
{
|
||||||
withoutMask = withoutMask.Set(componentUpdateManager.TypeToIndex[type]);
|
withoutMask = withoutMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var immediateMask = BitSetBuilder.Zeroes();
|
var immediateMask = BitSet512.Zero;
|
||||||
foreach (var type in readImmediateTypes)
|
foreach (var type in readImmediateTypes)
|
||||||
{
|
{
|
||||||
immediateMask = immediateMask.Set(componentUpdateManager.TypeToIndex[type]);
|
immediateMask = immediateMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var existingMask = BitSetBuilder.Zeroes();
|
var existingMask = BitSet512.Zero;
|
||||||
foreach (var type in readTypes)
|
foreach (var type in readTypes)
|
||||||
{
|
{
|
||||||
existingMask = existingMask.Set(componentUpdateManager.TypeToIndex[type]);
|
existingMask = existingMask.Set(componentUpdateManager.TypeToIndex[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
entityQuery = new EntitySetQuery(
|
entityQuery = new EntitySetQuery(
|
||||||
withMask.And(immediateMask),
|
withMask & immediateMask,
|
||||||
withMask.And(existingMask),
|
withMask & existingMask,
|
||||||
withoutMask.And(immediateMask),
|
withoutMask & immediateMask,
|
||||||
withoutMask.And(existingMask),
|
withoutMask & existingMask,
|
||||||
withMask.Not()
|
~withMask
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
using System.Collections;
|
using MoonTools.FastCollections;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Encompass.Collections;
|
|
||||||
|
|
||||||
namespace Encompass
|
namespace Encompass
|
||||||
{
|
{
|
||||||
internal struct EntitySetQuery
|
internal struct EntitySetQuery
|
||||||
{
|
{
|
||||||
private BitSet WithImmediateMask { get; }
|
private BitSet512 WithImmediateMask { get; }
|
||||||
private BitSet WithExistingMask { get; }
|
private BitSet512 WithExistingMask { get; }
|
||||||
private BitSet WithoutImmediateMask { get; }
|
private BitSet512 WithoutImmediateMask { get; }
|
||||||
private BitSet WithoutExistingMask { get; }
|
private BitSet512 WithoutExistingMask { get; }
|
||||||
private BitSet NotWithMask { get; }
|
private BitSet512 NotWithMask { get; }
|
||||||
|
|
||||||
internal EntitySetQuery(BitSet withImmediateMask, BitSet withExistingMask, BitSet withoutImmediateMask, BitSet withoutExistingMask, BitSet notWithMask)
|
internal EntitySetQuery(BitSet512 withImmediateMask, BitSet512 withExistingMask, BitSet512 withoutImmediateMask, BitSet512 withoutExistingMask, BitSet512 notWithMask)
|
||||||
{
|
{
|
||||||
WithImmediateMask = withImmediateMask;
|
WithImmediateMask = withImmediateMask;
|
||||||
WithExistingMask = withExistingMask;
|
WithExistingMask = withExistingMask;
|
||||||
|
@ -24,11 +22,11 @@ namespace Encompass
|
||||||
public bool CheckEntity(Entity entity, ComponentBitSet componentBitSet)
|
public bool CheckEntity(Entity entity, ComponentBitSet componentBitSet)
|
||||||
{
|
{
|
||||||
var existingBits = componentBitSet.EntityBitArray(entity.ID);
|
var existingBits = componentBitSet.EntityBitArray(entity.ID);
|
||||||
var existing = WithExistingMask.And(existingBits).Or(NotWithMask);
|
var existing = (WithExistingMask & existingBits) | NotWithMask;
|
||||||
|
|
||||||
var existingForbidden = WithoutExistingMask.And(existingBits).Not();
|
var existingForbidden = ~(WithoutExistingMask & existingBits);
|
||||||
|
|
||||||
return existing.And(existingForbidden).AllTrue();
|
return (existing & existingForbidden).AllTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ImmediateCheckEntity(Entity entity, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup)
|
public bool ImmediateCheckEntity(Entity entity, ComponentBitSet immediateBitLookup, ComponentBitSet existingBitLookup)
|
||||||
|
@ -36,15 +34,15 @@ namespace Encompass
|
||||||
var immediateBits = immediateBitLookup.EntityBitArray(entity.ID);
|
var immediateBits = immediateBitLookup.EntityBitArray(entity.ID);
|
||||||
var existingBits = existingBitLookup.EntityBitArray(entity.ID);
|
var existingBits = existingBitLookup.EntityBitArray(entity.ID);
|
||||||
|
|
||||||
var immediate = WithImmediateMask.And(immediateBits);
|
var immediate = WithImmediateMask & immediateBits;
|
||||||
var existing = WithExistingMask.And(existingBits);
|
var existing = WithExistingMask & existingBits;
|
||||||
var withCheck = immediate.Or(existing).Or(NotWithMask);
|
var withCheck = immediate | existing | NotWithMask;
|
||||||
|
|
||||||
var immediateForbidden = WithoutImmediateMask.And(immediateBits).Not();
|
var immediateForbidden = ~(WithoutImmediateMask & immediateBits);
|
||||||
var existingForbidden = WithoutExistingMask.And(existingBits).Not();
|
var existingForbidden = ~(WithoutExistingMask & existingBits);
|
||||||
var withoutCheck = immediateForbidden.And(existingForbidden);
|
var withoutCheck = immediateForbidden & existingForbidden;
|
||||||
|
|
||||||
return withCheck.And(withoutCheck).AllTrue();
|
return (withCheck & withoutCheck).AllTrue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="MoonTools.Core.Graph" Version="1.0.0" />
|
<PackageReference Include="MoonTools.Core.Graph" Version="1.0.0" />
|
||||||
|
<PackageReference Include="MoonTools.FastCollections" Version="1.0.0" />
|
||||||
<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
|
<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -1,62 +0,0 @@
|
||||||
using Encompass.Collections;
|
|
||||||
using FluentAssertions;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Tests
|
|
||||||
{
|
|
||||||
public class BitSetTest
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void Zeroes()
|
|
||||||
{
|
|
||||||
var bitSet = BitSetBuilder.Zeroes();
|
|
||||||
bitSet.AllFalse().Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Ones()
|
|
||||||
{
|
|
||||||
var bitSet = BitSetBuilder.Ones();
|
|
||||||
bitSet.AllTrue().Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Set()
|
|
||||||
{
|
|
||||||
var bitSet = BitSetBuilder.Zeroes().Set(5);
|
|
||||||
bitSet.AllFalse().Should().BeFalse();
|
|
||||||
|
|
||||||
bitSet = BitSetBuilder.Zeroes().Set(132);
|
|
||||||
bitSet.AllFalse().Should().BeFalse();
|
|
||||||
|
|
||||||
bitSet = BitSetBuilder.Zeroes().Set(268);
|
|
||||||
bitSet.AllFalse().Should().BeFalse();
|
|
||||||
|
|
||||||
bitSet = BitSetBuilder.Zeroes().Set(450);
|
|
||||||
bitSet.AllFalse().Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void UnSet()
|
|
||||||
{
|
|
||||||
var bitSet = BitSetBuilder.Ones().UnSet(285);
|
|
||||||
bitSet.Get(285).Should().BeFalse();
|
|
||||||
bitSet.Set(285).AllTrue().Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Get()
|
|
||||||
{
|
|
||||||
var bitSet = BitSetBuilder.Zeroes().Set(359);
|
|
||||||
bitSet.Get(359).Should().BeTrue();
|
|
||||||
bitSet.UnSet(359).AllFalse().Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Not()
|
|
||||||
{
|
|
||||||
var bitSet = BitSetBuilder.Ones().Not();
|
|
||||||
bitSet.AllFalse().Should().BeTrue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue