From 6d1b510ac1a7b3f20217fe383ff0504ec2c261cc Mon Sep 17 00:00:00 2001 From: Misaki Date: Sun, 12 Oct 2025 19:49:05 +0900 Subject: [PATCH] Improve ecs query performance; --- Ghost.Core/Ghost.Core.csproj | 5 + Ghost.Entities.Test/EntityTest.cs | 105 +- Ghost.Entities/Components/ComponentStorage.cs | 71 +- Ghost.Entities/Components/ScriptComponent.cs | 16 +- Ghost.Entities/Ghost.Entities.csproj | 14 + Ghost.Entities/Query/QueryBuilder.cs | 42 + Ghost.Entities/Query/QueryFilter.cs | 146 +- Ghost.Entities/Query/QueryTypeParameter.cs | 7 +- Ghost.Entities/Template/ForEach.cs | 12 + Ghost.Entities/Template/ForEach.tt | 16 + Ghost.Entities/Template/QueryEnumerable.cs | 1701 ++++++++++------- Ghost.Entities/Template/QueryEnumerable.tt | 81 +- Ghost.Entities/Template/QueryItem.cs | 72 +- Ghost.Entities/Template/World.Query.cs | 137 ++ Ghost.Entities/Template/World.Query.tt | 18 + Ghost.Entities/World.cs | 39 +- Ghost.FMOD/Ghost.FMOD.csproj | 4 +- .../{ => runtime/win-x64/native}/fmod.dll | Bin .../win-x64/native}/fmodstudio.dll | Bin Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs | 21 +- .../D3D12/Utilities/Win32Utility.cs | 5 +- Ghost.Graphics/Ghost.Graphics.csproj | 1 - Ghost.Test.Core/ITest.cs | 4 + Ghost.Test.Core/TestRunner.cs | 17 + .../Ghost.Zeux.MeshOptimizer.csproj | 2 +- .../win-x64/native}/meshoptimizer_native.dll | Bin GhostEngine.sln | 2 + 27 files changed, 1546 insertions(+), 992 deletions(-) create mode 100644 Ghost.Entities/Query/QueryBuilder.cs create mode 100644 Ghost.Entities/Template/ForEach.cs create mode 100644 Ghost.Entities/Template/ForEach.tt rename Ghost.FMOD/{ => runtime/win-x64/native}/fmod.dll (100%) rename Ghost.FMOD/{ => runtime/win-x64/native}/fmodstudio.dll (100%) rename Ghost.Zeux.MeshOptimizer/{ => runtime/win-x64/native}/meshoptimizer_native.dll (100%) diff --git a/Ghost.Core/Ghost.Core.csproj b/Ghost.Core/Ghost.Core.csproj index bf47a20..db00b21 100644 --- a/Ghost.Core/Ghost.Core.csproj +++ b/Ghost.Core/Ghost.Core.csproj @@ -7,6 +7,10 @@ True + + + + ..\..\Class\Misaki.HighPerformance\Misaki.HighPerformance.LowLevel\bin\Release\net9.0\Misaki.HighPerformance.LowLevel.dll @@ -17,4 +21,5 @@ + diff --git a/Ghost.Entities.Test/EntityTest.cs b/Ghost.Entities.Test/EntityTest.cs index bb59ca9..f20d850 100644 --- a/Ghost.Entities.Test/EntityTest.cs +++ b/Ghost.Entities.Test/EntityTest.cs @@ -1,4 +1,5 @@ using Ghost.Entities.Components; +using Ghost.Entities.Query; using Ghost.Entities.Systems; using Ghost.Test.Core; using System.Numerics; @@ -7,50 +8,62 @@ namespace Ghost.Entities.Test; public partial class EntityTest : ITest { + private World _world = null!; + + public void Setup() + { + _world = World.Create(); + } + public void Run() { - var world = World.Create(); + var entity1 = _world.EntityManager.CreateEntity(); + var entity2 = _world.EntityManager.CreateEntity(); + var entity3 = _world.EntityManager.CreateEntity(); - var entity1 = world.EntityManager.CreateEntity(); - var entity2 = world.EntityManager.CreateEntity(); - var entity3 = world.EntityManager.CreateEntity(); + _world.EntityManager.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) }); + _world.EntityManager.AddComponent(entity1, new Mesh { index = 42 }); + _world.EntityManager.AddScript(entity1); + _world.EntityManager.AddScript(entity1); - world.EntityManager.AddComponent(entity1, new Transform { position = new Vector3(1, 2, 3) }); - world.EntityManager.AddComponent(entity1, new Mesh { index = 42 }); - world.EntityManager.AddScript(entity1); - world.EntityManager.AddScript(entity1); + _world.EntityManager.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) }); + _world.EntityManager.AddComponent(entity2, new Mesh { index = 43 }); + _world.EntityManager.AddScript(entity2); - world.EntityManager.AddComponent(entity2, new Transform { position = new Vector3(4, 5, 6) }); - world.EntityManager.AddComponent(entity2, new Mesh { index = 43 }); - world.EntityManager.AddScript(entity2); + _world.EntityManager.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) }); + _world.EntityManager.AddScript(entity3); - world.EntityManager.AddComponent(entity3, new Transform { position = new Vector3(7, 8, 9) }); - world.EntityManager.AddScript(entity3); - - foreach (var (_, transform) in world.Query()) + foreach (var (_, transform) in _world.Query()) { transform.ValueRW.position += new Vector3(1, 1, 1); } - foreach (var (_, mesh) in world.Query()) + var filter = new QueryBuilder() + .WithAll() + .Build(); + + foreach (var (_, mesh) in _world.QueryFilter(in filter)) { mesh.ValueRW.index += 1; } - world.EntityManager.RemoveEntity(ref entity2); + _world.EntityManager.RemoveEntity(ref entity2); - var entity4 = world.EntityManager.CreateEntity(); - world.EntityManager.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) }); - world.EntityManager.AddComponent(entity4, new Mesh { index = 44 }); - world.EntityManager.AddScript(entity4); + var entity4 = _world.EntityManager.CreateEntity(); + _world.EntityManager.AddComponent(entity4, new Transform { position = new Vector3(10, 11, 12) }); + _world.EntityManager.AddComponent(entity4, new Mesh { index = 45 }); + _world.EntityManager.AddScript(entity4); - world.SystemStorage.AddSystem(); - world.SystemStorage.AddSystem(); + _world.SystemStorage.AddSystem(); + _world.SystemStorage.AddSystem(); - world.SystemStorage.CreateSystems(); - world.SystemStorage.UpdateSystems(); + _world.SystemStorage.CreateSystems(); + _world.SystemStorage.UpdateSystems(); + } - world.Dispose(); + public void Cleanup() + { + _world.Dispose(); } } @@ -62,9 +75,9 @@ public class TestSystem : ISystem public void OnUpdate(in SystemState state) { - foreach (var (entity, transform) in state.World.Query().WithAbsent()) + foreach (var (entity, transform) in state.World.Query()) { - Console.WriteLine($"Entity {entity.ID}: Transform Position = {transform.ValueRO.position}"); + Console.WriteLine($"Entity {entity}: Transform Position = {transform.ValueRO.position}"); } } @@ -84,7 +97,7 @@ public class TestSystem2 : ISystem { foreach (var (entity, mesh) in state.World.Query()) { - Console.WriteLine($"Entity {entity.ID}: Mesh Index = {mesh.ValueRO.index}"); + Console.WriteLine($"Entity {entity}: Mesh Index = {mesh.ValueRO.index}"); } } @@ -109,19 +122,35 @@ public class UserScript : ScriptComponent { public override int ExecutionOrder => -1; + public override void OnEnable() + { + Console.WriteLine("UserScript enabled for entity: " + Owner); + EntityManager.GetComponent(Owner).ValueRW.position += new Vector3(10, 10, 10); + } + + override public void OnDisable() + { + Console.WriteLine("UserScript disabled for entity: " + Owner); + } + + public override void Initialize() + { + Console.WriteLine("UserScript initialized for entity: " + Owner); + } + public override void Start() { - Console.WriteLine("UserScript started for entity: " + Owner.ID); + Console.WriteLine("UserScript started for entity: " + Owner); } public override void Update() { - Console.WriteLine("UserScript updating for entity: " + Owner.ID); + Console.WriteLine("UserScript updating for entity: " + Owner); } public override void OnDestroy() { - Console.WriteLine("UserScript destroyed for entity: " + Owner.ID); + Console.WriteLine("UserScript destroyed for entity: " + Owner); } } @@ -129,17 +158,17 @@ public class UIManager : ScriptComponent { public override void Start() { - Console.WriteLine("UIManager started for entity: " + Owner.ID); + Console.WriteLine("UIManager started for entity: " + Owner); } public override void Update() { - Console.WriteLine("UIManager updating for entity: " + Owner.ID); + Console.WriteLine("UIManager updating for entity: " + Owner); } public override void OnDestroy() { - Console.WriteLine("UIManager destroyed for entity: " + Owner.ID); + Console.WriteLine("UIManager destroyed for entity: " + Owner); } } @@ -147,16 +176,16 @@ public class EventManager : ScriptComponent { public override void Start() { - Console.WriteLine("EventManager started for entity: " + Owner.ID); + Console.WriteLine("EventManager started for entity: " + Owner); } public override void Update() { - Console.WriteLine("EventManager updating for entity: " + Owner.ID); + Console.WriteLine("EventManager updating for entity: " + Owner); } public override void OnDestroy() { - Console.WriteLine("EventManager destroyed for entity: " + Owner.ID); + Console.WriteLine("EventManager destroyed for entity: " + Owner); } } \ No newline at end of file diff --git a/Ghost.Entities/Components/ComponentStorage.cs b/Ghost.Entities/Components/ComponentStorage.cs index fb1ec1c..fc00d26 100644 --- a/Ghost.Entities/Components/ComponentStorage.cs +++ b/Ghost.Entities/Components/ComponentStorage.cs @@ -64,7 +64,8 @@ internal class ComponentPool : IComponentPool _lookup.AsSpan().Fill(Entity.INVALID_ID); } - public ComponentPool() : this(16) + public ComponentPool() + : this(16) { } @@ -217,12 +218,19 @@ internal class ScriptComponentPool : IComponentPool private Dictionary>? _scriptComponents; private List? _executionList; + private readonly World _world; + internal IReadOnlyDictionary>? ScriptComponents => _scriptComponents; internal IReadOnlyList? ExecutionList => _executionList; public bool IsInitialized => _scriptComponents != null; public int Count => _scriptComponents?.Keys.Count ?? 0; + public ScriptComponentPool(World world) + { + _world = world; + } + internal void Initialize(int capacity = 16) { _scriptComponents ??= new(capacity); @@ -263,14 +271,15 @@ internal class ScriptComponentPool : IComponentPool Initialize(); } - if (!_scriptComponents!.TryGetValue(entity, out var scriptList)) - { - scriptList = new(); - _scriptComponents[entity] = scriptList; - } + ref var scriptList = ref CollectionsMarshal.GetValueRefOrAddDefault(_scriptComponents!, entity, out var exists); + scriptList ??= new List(); scriptList.Add(component); + component.Owner = entity; + component._world = _world; + component.Enable = true; + component.Initialize(); } public bool Remove(Entity entity) @@ -472,22 +481,23 @@ internal struct ComponentStorage : IDisposable private int _currentCapacity = 16; private IComponentPool?[] _componentPools = new IComponentPool[16]; - private UnsafeBitSet?[] _componentEntityMasks = new UnsafeBitSet?[16]; + private UnsafeBitSet[] _componentEntityMasks = new UnsafeBitSet[16]; private readonly Dictionary _typeIDMap = new(16); private readonly Dictionary _typeHandleMap = new(16); - private readonly ScriptComponentPool _scriptComponentPool = new(); + private readonly ScriptComponentPool _scriptComponentPool; private readonly World _world; internal ComponentStorage(World world) { _world = world; + _scriptComponentPool = new ScriptComponentPool(world); } internal readonly IReadOnlyList ComponentPools => _componentPools; - internal readonly IReadOnlyList ComponentEntityMasks => _componentEntityMasks; + internal readonly IReadOnlyList ComponentEntityMasks => _componentEntityMasks; internal readonly ScriptComponentPool ScriptComponentPool => _scriptComponentPool; [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -641,29 +651,7 @@ internal struct ComponentStorage : IDisposable return TryGetMask(TypeHandle.Get(), out bitSet); } - public UnsafeBitSet GetOrCreateMask() - where T : unmanaged, IComponentData - { - var typeHandle = TypeHandle.Get(); - if (!_typeIDMap.TryGetValue(typeHandle, out var id)) - { - id = GetTypeID(); - _typeIDMap[typeHandle] = id; - _typeHandleMap[id] = typeHandle; - } - - if (id >= _currentCapacity) - { - Resize(_currentCapacity * 2); - } - - ref var set = ref _componentEntityMasks[id]; - set ??= new UnsafeBitSet(); - - return set.Value; - } - - public UnsafeBitSet GetOrCreateMask(TypeHandle typeHandle) + public ref UnsafeBitSet GetOrCreateMask(TypeHandle typeHandle) { if (!_typeIDMap.TryGetValue(typeHandle, out var id)) { @@ -678,14 +666,23 @@ internal struct ComponentStorage : IDisposable } ref var set = ref _componentEntityMasks[id]; - set ??= new UnsafeBitSet(); + if (!set.IsCreated) + { + set = new UnsafeBitSet(); + } - return set.Value; + return ref set; } - public UnsafeBitSet GetOrCreateMask(Type type) + public ref UnsafeBitSet GetOrCreateMask() + where T : unmanaged, IComponentData { - return GetOrCreateMask(TypeHandle.Get(type)); + return ref GetOrCreateMask(TypeHandle.Get()); + } + + public ref UnsafeBitSet GetOrCreateMask(Type type) + { + return ref GetOrCreateMask(TypeHandle.Get(type)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -710,7 +707,7 @@ internal struct ComponentStorage : IDisposable foreach (var bitSet in _componentEntityMasks) { - bitSet?.Dispose(); + bitSet.Dispose(); } _scriptComponentPool.Dispose(); diff --git a/Ghost.Entities/Components/ScriptComponent.cs b/Ghost.Entities/Components/ScriptComponent.cs index 33f0788..00e982a 100644 --- a/Ghost.Entities/Components/ScriptComponent.cs +++ b/Ghost.Entities/Components/ScriptComponent.cs @@ -2,7 +2,9 @@ public abstract class ScriptComponent : IComponentData { - private bool _enable = true; + private bool _enable; + + internal World _world = null!; /// /// Gets or sets a value indicating whether this script component is enabled. @@ -38,6 +40,11 @@ public abstract class ScriptComponent : IComponentData internal set; } + /// + /// Gets the EntityManager instance associated with the current world. + /// + protected EntityManager EntityManager => _world.EntityManager; + /// /// Gets or sets the priority of the script component. /// Change this during runtime does not affect the execution order. @@ -58,6 +65,13 @@ public abstract class ScriptComponent : IComponentData { } + /// + /// Called when the script component is initialized. + /// + public virtual void Initialize() + { + } + /// /// Called when the script component is started. /// diff --git a/Ghost.Entities/Ghost.Entities.csproj b/Ghost.Entities/Ghost.Entities.csproj index 478d9d8..f024e17 100644 --- a/Ghost.Entities/Ghost.Entities.csproj +++ b/Ghost.Entities/Ghost.Entities.csproj @@ -8,6 +8,11 @@ + + True + True + ForEach.tt + True True @@ -32,6 +37,10 @@ + + TextTemplatingFileGenerator + ForEach.cs + TextTemplatingFileGenerator QueryEnumerable.cs @@ -59,6 +68,11 @@ + + True + True + ForEach.tt + True True diff --git a/Ghost.Entities/Query/QueryBuilder.cs b/Ghost.Entities/Query/QueryBuilder.cs new file mode 100644 index 0000000..028a5f5 --- /dev/null +++ b/Ghost.Entities/Query/QueryBuilder.cs @@ -0,0 +1,42 @@ +using Ghost.Core; + +namespace Ghost.Entities.Query; + +public struct QueryBuilder +{ + private QueryFilter _filter; + + public QueryBuilder() + { + _filter = new QueryFilter(); + } + + public QueryBuilder WithAll() + { + _filter._all.Add(TypeHandle.Get()); + return this; + } + + public QueryBuilder WithAny() + { + _filter._any.Add(TypeHandle.Get()); + return this; + } + + public QueryBuilder WithAbsent() + { + _filter._absent.Add(TypeHandle.Get()); + return this; + } + + public QueryBuilder WithDisabled() + { + _filter._disabled.Add(TypeHandle.Get()); + return this; + } + + public readonly QueryFilter Build() + { + return _filter; + } +} \ No newline at end of file diff --git a/Ghost.Entities/Query/QueryFilter.cs b/Ghost.Entities/Query/QueryFilter.cs index e951cbc..5c57328 100644 --- a/Ghost.Entities/Query/QueryFilter.cs +++ b/Ghost.Entities/Query/QueryFilter.cs @@ -1,98 +1,98 @@ using Ghost.Core; +using Ghost.Entities.Components; using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections; -using System.Runtime.CompilerServices; namespace Ghost.Entities.Query; -[Flags] -internal enum FilterMode +public struct QueryFilter : IDisposable { - All = 1 << 0, - Any = 1 << 1, - Absent = 1 << 2, - Disabled = 1 << 3, -} + private readonly Stack.Scope _scope; -internal readonly struct FilterEntry(TypeHandle id, FilterMode mode) -{ - public readonly TypeHandle typeHandle = id; - public readonly FilterMode mode = mode; -} + internal UnsafeList _all; + internal UnsafeList _any; + internal UnsafeList _absent; + internal UnsafeList _disabled; -internal struct QueryFilter() -{ - internal List _all = new(6); - internal List _any = new(6); - internal List _absent = new(6); - internal List _disabled = new(6); + public QueryFilter() + { + _scope = AllocationManager.CreateStackScope(); - public readonly UnsafeBitSet ComputeFilterBitMask(World world) + _all = new UnsafeList(4, Allocator.Stack); + _any = new UnsafeList(4, Allocator.Stack); + _absent = new UnsafeList(4, Allocator.Stack); + _disabled = new UnsafeList(4, Allocator.Stack); + } + + public readonly UnsafeBitSet ComputeFilterBitMask(World world, Allocator allocator) { UnsafeBitSet allMask = default; UnsafeBitSet anyMask = default; UnsafeBitSet absentMask = default; - using var scope = AllocationManager.CreateStackScope(); - - foreach (var typeHandle in _all) - { - var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); - - if (!allMask.IsCreated) - { - allMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.Clear); - allMask.SetAll(); - } - - allMask.AndOperation(mask); - } - - foreach (var typeHandle in _any) - { - var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); - - if (!anyMask.IsCreated) - { - anyMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.Clear); - } - - anyMask.OrOperation(mask); - } - - foreach (var typeHandle in _absent) - { - var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); - - if (!absentMask.IsCreated) - { - absentMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.Clear); - } - - absentMask.OrOperation(mask); - } - - var result = new UnsafeBitSet(world.EntityManager.EntityCount, Allocator.Persistent); + var result = new UnsafeBitSet(world.EntityManager.EntityCount, allocator); result.SetAll(); - if (allMask.IsCreated) + using (AllocationManager.CreateStackScope()) { - result.AndOperation(allMask); - allMask.Dispose(); - } + foreach (var typeHandle in _all) + { + var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); - if (anyMask.IsCreated) - { - result.AndOperation(anyMask); - anyMask.Dispose(); - } + if (!allMask.IsCreated) + { + allMask = new UnsafeBitSet(mask.Length, Allocator.Stack, AllocationOption.None); + allMask.SetAll(); + } - if (absentMask.IsCreated) - { - result.AndOperation(~absentMask); - absentMask.Dispose(); + allMask.AndOperation(mask); + } + + foreach (var typeHandle in _any) + { + var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); + + if (!anyMask.IsCreated) + { + anyMask = new UnsafeBitSet(mask.Length, Allocator.Stack); + } + + anyMask.OrOperation(mask); + } + + foreach (var typeHandle in _absent) + { + var mask = world.ComponentStorage.GetOrCreateMask(typeHandle); + + if (!absentMask.IsCreated) + { + absentMask = new UnsafeBitSet(mask.Length, Allocator.Stack); + } + + absentMask.OrOperation(mask); + } + + if (allMask.IsCreated) + { + result.AndOperation(allMask); + } + + if (anyMask.IsCreated) + { + result.AndOperation(anyMask); + } + + if (absentMask.IsCreated) + { + result.AndOperation(~absentMask); + } } return result; } + + public readonly void Dispose() + { + _scope.Dispose(); + } } \ No newline at end of file diff --git a/Ghost.Entities/Query/QueryTypeParameter.cs b/Ghost.Entities/Query/QueryTypeParameter.cs index 3357afc..10fc357 100644 --- a/Ghost.Entities/Query/QueryTypeParameter.cs +++ b/Ghost.Entities/Query/QueryTypeParameter.cs @@ -3,11 +3,12 @@ using System.Runtime.CompilerServices; namespace Ghost.Entities.Query; -public interface IQueryTypeParameter +public interface IQueryTypeParameter + where T : IComponentData { } -public ref struct CompRef : IQueryTypeParameter +public ref struct CompRef : IQueryTypeParameter where T : IComponentData { internal ref T _value; @@ -42,7 +43,7 @@ public ref struct CompRef : IQueryTypeParameter } } -public ref struct CompRO : IQueryTypeParameter +public readonly ref struct CompRO : IQueryTypeParameter where T : IComponentData { internal readonly ref T _value; diff --git a/Ghost.Entities/Template/ForEach.cs b/Ghost.Entities/Template/ForEach.cs new file mode 100644 index 0000000..284f72c --- /dev/null +++ b/Ghost.Entities/Template/ForEach.cs @@ -0,0 +1,12 @@ + + +namespace Ghost.Entities; + +public delegate void ForEach(ref T0 t0Component); +public delegate void ForEach(ref T0 t0Component,ref T1 t1Component); +public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component); +public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component); +public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component); +public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component); +public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component); +public delegate void ForEach(ref T0 t0Component,ref T1 t1Component,ref T2 t2Component,ref T3 t3Component,ref T4 t4Component,ref T5 t5Component,ref T6 t6Component,ref T7 t7Component); diff --git a/Ghost.Entities/Template/ForEach.tt b/Ghost.Entities/Template/ForEach.tt new file mode 100644 index 0000000..045c196 --- /dev/null +++ b/Ghost.Entities/Template/ForEach.tt @@ -0,0 +1,16 @@ +<#@ template language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ include file="Helpers.ttinclude" #> + +namespace Ghost.Entities; + +<# for (var i = 1; i <= Amount; i++) +{ + var generics = AppendGenerics(i); + var compGenerics = AppendGenericRefParameters(i); +#> +public delegate void ForEach<<#= generics #>>(<#= compGenerics #>); +<# } #> \ No newline at end of file diff --git a/Ghost.Entities/Template/QueryEnumerable.cs b/Ghost.Entities/Template/QueryEnumerable.cs index c08ab56..8202e18 100644 --- a/Ghost.Entities/Template/QueryEnumerable.cs +++ b/Ghost.Entities/Template/QueryEnumerable.cs @@ -3,46 +3,60 @@ using Ghost.Core; using Ghost.Entities.Components; using Ghost.Entities.Query; +using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections; namespace Ghost.Entities; -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -50,16 +64,19 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -67,153 +84,175 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0 || _index >= _entities.Length) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; _pool1 = pool1; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + _pool1 = pool1; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -221,17 +260,20 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _pool1 = pool1; _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -239,116 +281,126 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0, _pool1); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; @@ -356,11 +408,13 @@ public struct QueryEnumerable private readonly ComponentPool _pool2; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; @@ -368,28 +422,39 @@ public struct QueryEnumerable _pool2 = pool2; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + _pool1 = pool1; + _pool2 = pool2; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; private readonly ComponentPool _pool2; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -397,10 +462,14 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _pool1 = pool1; @@ -408,7 +477,6 @@ public struct QueryEnumerable _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -416,116 +484,126 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; @@ -534,11 +612,14 @@ public struct QueryEnumerable private readonly ComponentPool _pool3; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; @@ -547,20 +628,33 @@ public struct QueryEnumerable _pool3 = pool3; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + _pool1 = pool1; + _pool2 = pool2; + _pool3 = pool3; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; @@ -568,9 +662,7 @@ public struct QueryEnumerable private readonly ComponentPool _pool3; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -578,10 +670,14 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _pool1 = pool1; @@ -590,7 +686,6 @@ public struct QueryEnumerable _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -598,116 +693,126 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; @@ -717,11 +822,15 @@ public struct QueryEnumerable private readonly ComponentPool _pool4; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; @@ -731,21 +840,34 @@ public struct QueryEnumerable _pool4 = pool4; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + _pool1 = pool1; + _pool2 = pool2; + _pool3 = pool3; + _pool4 = pool4; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; @@ -754,9 +876,7 @@ public struct QueryEnumerable private readonly ComponentPool _pool4; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -764,10 +884,14 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _pool1 = pool1; @@ -777,7 +901,6 @@ public struct QueryEnumerable _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -785,116 +908,126 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; @@ -905,11 +1038,16 @@ public struct QueryEnumerable private readonly ComponentPool _pool5; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; @@ -920,22 +1058,35 @@ public struct QueryEnumerable _pool5 = pool5; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + _pool1 = pool1; + _pool2 = pool2; + _pool3 = pool3; + _pool4 = pool4; + _pool5 = pool5; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; @@ -945,9 +1096,7 @@ public struct QueryEnumerable private readonly ComponentPool _pool5; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -955,10 +1104,14 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _pool1 = pool1; @@ -969,7 +1122,6 @@ public struct QueryEnumerable _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -977,116 +1129,126 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4, _pool5); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; @@ -1098,11 +1260,17 @@ public struct QueryEnumerable private readonly ComponentPool _pool6; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; @@ -1114,23 +1282,36 @@ public struct QueryEnumerable _pool6 = pool6; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + _pool1 = pool1; + _pool2 = pool2; + _pool3 = pool3; + _pool4 = pool4; + _pool5 = pool5; + _pool6 = pool6; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; @@ -1141,9 +1322,7 @@ public struct QueryEnumerable private readonly ComponentPool _pool6; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -1151,10 +1330,14 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _pool1 = pool1; @@ -1166,7 +1349,6 @@ public struct QueryEnumerable _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -1174,116 +1356,126 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } -public struct QueryEnumerable +public unsafe ref struct QueryEnumerable where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData { + private QueryFilter _filter; + private readonly World _world; private readonly ComponentPool _pool0; @@ -1296,11 +1488,18 @@ public struct QueryEnumerable private readonly ComponentPool _pool7; private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7, int count) { + _filter = new(); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _world = world; _pool0 = pool0; @@ -1313,24 +1512,37 @@ public struct QueryEnumerable _pool7 = pool7; _count = count; - - _filters = new(); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); } - public readonly Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _pool7, _count, _filters); + internal QueryEnumerable(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + + _pool0 = pool0; + _pool1 = pool1; + _pool2 = pool2; + _pool3 = pool3; + _pool4 = pool4; + _pool5 = pool5; + _pool6 = pool6; + _pool7 = pool7; + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _pool7, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; private readonly ComponentPool _pool0; private readonly ComponentPool _pool1; @@ -1342,9 +1554,7 @@ public struct QueryEnumerable private readonly ComponentPool _pool7; private int _index; - private readonly int _count; - - private UnsafeBitSet _filterMask; + private int _count; public QueryItem Current { @@ -1352,10 +1562,14 @@ public struct QueryEnumerable private set; } - internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7, int count, QueryFilter filters) + internal Enumerator(World world, ComponentPool pool0, ComponentPool pool1, ComponentPool pool2, ComponentPool pool3, ComponentPool pool4, ComponentPool pool5, ComponentPool pool6, ComponentPool pool7, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; _pool0 = pool0; _pool1 = pool1; @@ -1368,7 +1582,6 @@ public struct QueryEnumerable _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -1376,110 +1589,118 @@ public struct QueryEnumerable public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem(_entities[_index], _pool0, _pool1, _pool2, _pool3, _pool4, _pool5, _pool6, _pool7); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAll() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); - _filters._all.Add(TypeHandle.Get()); + public QueryEnumerable WithAll() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); + _filter._all.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAny() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); - _filters._any.Add(TypeHandle.Get()); + public QueryEnumerable WithAny() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); + _filter._any.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithAbsent() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); - _filters._absent.Add(TypeHandle.Get()); + public QueryEnumerable WithAbsent() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); + _filter._absent.Add(TypeHandle.Get()); return this; - } + } - public readonly QueryEnumerable WithDisabled() - where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData - { - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); - _filters._disabled.Add(TypeHandle.Get()); + public QueryEnumerable WithDisabled() + where TComponent0 : unmanaged, IComponentData where TComponent1 : unmanaged, IComponentData where TComponent2 : unmanaged, IComponentData + { + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); + _filter._disabled.Add(TypeHandle.Get()); return this; - } + } } diff --git a/Ghost.Entities/Template/QueryEnumerable.tt b/Ghost.Entities/Template/QueryEnumerable.tt index 923a4fa..3ae5136 100644 --- a/Ghost.Entities/Template/QueryEnumerable.tt +++ b/Ghost.Entities/Template/QueryEnumerable.tt @@ -8,6 +8,7 @@ using Ghost.Core; using Ghost.Entities.Components; using Ghost.Entities.Query; +using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Collections; namespace Ghost.Entities; @@ -23,9 +24,11 @@ var constructorParams = Enumerable.Range(0, arity) .Aggregate((a, b) => a + ", " + b); #> -public struct QueryEnumerable<<#= generics #>> +public unsafe ref struct QueryEnumerable<<#= generics #>> <#= restrictions #> { + private QueryFilter _filter; + private readonly World _world; <# for (int i = 0; i < arity; i++){ #> @@ -33,11 +36,13 @@ public struct QueryEnumerable<<#= generics #>> <# } #> private readonly int _count; - private QueryFilter _filters; - internal readonly QueryFilter Filters => _filters; - internal QueryEnumerable(World world, <#= poolParams #>, int count) { + _filter = new(); +<# for (int i = 0; i < arity; i++) {#> + _filter._all.Add(TypeHandle.Get>()); +<# } #> + _world = world; <# for (int i = 0; i < arity; i++) { #> @@ -45,39 +50,54 @@ public struct QueryEnumerable<<#= generics #>> <# } #> _count = count; - - _filters = new(); -<# for (int i = 0; i < arity; i++) {#> - _filters._all.Add(TypeHandle.Get>()); -<# } #> } - public readonly Enumerator GetEnumerator() => new (_world, <#= constructorParams #>, _count, _filters); + internal QueryEnumerable(World world, <#= poolParams #>, int count, ref readonly QueryFilter filter) + { + _filter = filter; + + _world = world; + +<# for (int i = 0; i < arity; i++) { #> + _pool<#= i #> = pool<#= i #>; +<# } #> + + _count = count; + } + +#pragma warning disable CS9084 // Struct member returns 'this' or other instance members by reference + public Enumerator GetEnumerator() => new(_world, <#= constructorParams #>, _count, ref _filter); +#pragma warning restore CS9084 // Struct member returns 'this' or other instance members by reference public ref struct Enumerator { - private readonly World _world; + private ref QueryFilter _filter; + private UnsafeBitSet _filterMask; + private readonly ReadOnlySpan _entities; + private readonly Stack.Scope _stackScope; <# for (int i = 0; i < arity; i++){ #> private readonly ComponentPool> _pool<#= i #>; <# } #> private int _index; - private readonly int _count; + private int _count; - private UnsafeBitSet _filterMask; - public QueryItem<<#= generics #>> Current { get; private set; } - internal Enumerator(World world, <#= poolParams #>, int count, QueryFilter filters) + internal Enumerator(World world, <#= poolParams #>, int count, ref QueryFilter filter) { - _world = world; - _entities = _world.EntityManager.Entities; + _stackScope = AllocationManager.CreateStackScope(); + + _filter = ref filter; + _filterMask = _filter.ComputeFilterBitMask(world, Allocator.Stack); + + _entities = world.EntityManager.Entities; <# for (int i = 0; i < arity; i++){ #> _pool<#= i #> = pool<#= i #>; @@ -85,7 +105,6 @@ public struct QueryEnumerable<<#= generics #>> _count = count; _index = -1; - _filterMask = filters.ComputeFilterBitMask(_world); Current = default; } @@ -93,52 +112,60 @@ public struct QueryEnumerable<<#= generics #>> public bool MoveNext() { _index = _filterMask.NextSetBit(_index + 1); - if (_index < 0 || _index >= _world.EntityManager.EntityCount) + if (_index < 0 || _count <= 0) { return false; } + _count--; Current = new QueryItem<<#= generics #>>(_entities[_index], <#= constructorParams #>); + return true; } + + public readonly void Dispose() + { + _stackScope.Dispose(); + _filter.Dispose(); + } } <# for (int i = 1; i <= ExtensionAmount; i++) { var compGenerics = AppendGenerics(i, "TComponent"); var compRestrictions = AppendGenericRestrictions(i, "TComponent", "unmanaged, IComponentData"); #> - public readonly QueryEnumerable<<#= generics #>> WithAll<<#= compGenerics #>>() + public QueryEnumerable<<#= generics #>> WithAll<<#= compGenerics #>>() <#= compRestrictions #> { <# for (int j = 0; j < i; j++) {#> - _filters._all.Add(TypeHandle.Get>()); + _filter._all.Add(TypeHandle.Get>()); <# } #> return this; } - public readonly QueryEnumerable<<#= generics #>> WithAny<<#= compGenerics #>>() + public QueryEnumerable<<#= generics #>> WithAny<<#= compGenerics #>>() <#= compRestrictions #> { <# for (int j = 0; j < i; j++) {#> - _filters._any.Add(TypeHandle.Get>()); + _filter._any.Add(TypeHandle.Get>()); <# } #> return this; } - public readonly QueryEnumerable<<#= generics #>> WithAbsent<<#= compGenerics #>>() + public QueryEnumerable<<#= generics #>> WithAbsent<<#= compGenerics #>>() <#= compRestrictions #> { <# for (int j = 0; j < i; j++) {#> - _filters._absent.Add(TypeHandle.Get>()); + _filter._absent.Add(TypeHandle.Get>()); <# } #> return this; } - public readonly QueryEnumerable<<#= generics #>> WithDisabled<<#= compGenerics #>>() + public QueryEnumerable<<#= generics #>> WithDisabled<<#= compGenerics #>>() <#= compRestrictions #> { <# for (int j = 0; j < i; j++) {#> - _filters._disabled.Add(TypeHandle.Get>()); + _filter._disabled.Add(TypeHandle.Get>()); <# } #> return this; } diff --git a/Ghost.Entities/Template/QueryItem.cs b/Ghost.Entities/Template/QueryItem.cs index 8b67a34..f74128f 100644 --- a/Ghost.Entities/Template/QueryItem.cs +++ b/Ghost.Entities/Template/QueryItem.cs @@ -26,7 +26,7 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); } } @@ -54,8 +54,8 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); - c1 = new(ref _pool1.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); + c1 = new (ref _pool1.GetRef(_entity)); } } @@ -86,9 +86,9 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); - c1 = new(ref _pool1.GetRef(_entity)); - c2 = new(ref _pool2.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); + c1 = new (ref _pool1.GetRef(_entity)); + c2 = new (ref _pool2.GetRef(_entity)); } } @@ -122,10 +122,10 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); - c1 = new(ref _pool1.GetRef(_entity)); - c2 = new(ref _pool2.GetRef(_entity)); - c3 = new(ref _pool3.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); + c1 = new (ref _pool1.GetRef(_entity)); + c2 = new (ref _pool2.GetRef(_entity)); + c3 = new (ref _pool3.GetRef(_entity)); } } @@ -162,11 +162,11 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); - c1 = new(ref _pool1.GetRef(_entity)); - c2 = new(ref _pool2.GetRef(_entity)); - c3 = new(ref _pool3.GetRef(_entity)); - c4 = new(ref _pool4.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); + c1 = new (ref _pool1.GetRef(_entity)); + c2 = new (ref _pool2.GetRef(_entity)); + c3 = new (ref _pool3.GetRef(_entity)); + c4 = new (ref _pool4.GetRef(_entity)); } } @@ -206,12 +206,12 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); - c1 = new(ref _pool1.GetRef(_entity)); - c2 = new(ref _pool2.GetRef(_entity)); - c3 = new(ref _pool3.GetRef(_entity)); - c4 = new(ref _pool4.GetRef(_entity)); - c5 = new(ref _pool5.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); + c1 = new (ref _pool1.GetRef(_entity)); + c2 = new (ref _pool2.GetRef(_entity)); + c3 = new (ref _pool3.GetRef(_entity)); + c4 = new (ref _pool4.GetRef(_entity)); + c5 = new (ref _pool5.GetRef(_entity)); } } @@ -254,13 +254,13 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); - c1 = new(ref _pool1.GetRef(_entity)); - c2 = new(ref _pool2.GetRef(_entity)); - c3 = new(ref _pool3.GetRef(_entity)); - c4 = new(ref _pool4.GetRef(_entity)); - c5 = new(ref _pool5.GetRef(_entity)); - c6 = new(ref _pool6.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); + c1 = new (ref _pool1.GetRef(_entity)); + c2 = new (ref _pool2.GetRef(_entity)); + c3 = new (ref _pool3.GetRef(_entity)); + c4 = new (ref _pool4.GetRef(_entity)); + c5 = new (ref _pool5.GetRef(_entity)); + c6 = new (ref _pool6.GetRef(_entity)); } } @@ -306,14 +306,14 @@ public readonly struct QueryItem { entity = _entity; - c0 = new(ref _pool0.GetRef(_entity)); - c1 = new(ref _pool1.GetRef(_entity)); - c2 = new(ref _pool2.GetRef(_entity)); - c3 = new(ref _pool3.GetRef(_entity)); - c4 = new(ref _pool4.GetRef(_entity)); - c5 = new(ref _pool5.GetRef(_entity)); - c6 = new(ref _pool6.GetRef(_entity)); - c7 = new(ref _pool7.GetRef(_entity)); + c0 = new (ref _pool0.GetRef(_entity)); + c1 = new (ref _pool1.GetRef(_entity)); + c2 = new (ref _pool2.GetRef(_entity)); + c3 = new (ref _pool3.GetRef(_entity)); + c4 = new (ref _pool4.GetRef(_entity)); + c5 = new (ref _pool5.GetRef(_entity)); + c6 = new (ref _pool6.GetRef(_entity)); + c7 = new (ref _pool7.GetRef(_entity)); } } diff --git a/Ghost.Entities/Template/World.Query.cs b/Ghost.Entities/Template/World.Query.cs index 9f108d3..4faac04 100644 --- a/Ghost.Entities/Template/World.Query.cs +++ b/Ghost.Entities/Template/World.Query.cs @@ -1,6 +1,7 @@  using Ghost.Entities.Components; +using Ghost.Entities.Query; namespace Ghost.Entities; @@ -10,7 +11,9 @@ public partial class World where T0 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0))) + { return default; + } return new QueryEnumerable( this, @@ -18,11 +21,28 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, + pool0.Count, + in filter); + } + public QueryEnumerable Query() where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1))) + { return default; + } return new QueryEnumerable( this, @@ -30,11 +50,28 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, pool1, + pool0.Count, + in filter); + } + public QueryEnumerable Query() where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2))) + { return default; + } return new QueryEnumerable( this, @@ -42,11 +79,28 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, pool1, pool2, + pool0.Count, + in filter); + } + public QueryEnumerable Query() where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3))) + { return default; + } return new QueryEnumerable( this, @@ -54,11 +108,28 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, pool1, pool2, pool3, + pool0.Count, + in filter); + } + public QueryEnumerable Query() where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4))) + { return default; + } return new QueryEnumerable( this, @@ -66,11 +137,28 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, pool1, pool2, pool3, pool4, + pool0.Count, + in filter); + } + public QueryEnumerable Query() where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5))) + { return default; + } return new QueryEnumerable( this, @@ -78,11 +166,28 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, pool1, pool2, pool3, pool4, pool5, + pool0.Count, + in filter); + } + public QueryEnumerable Query() where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6))) + { return default; + } return new QueryEnumerable( this, @@ -90,11 +195,28 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, pool1, pool2, pool3, pool4, pool5, pool6, + pool0.Count, + in filter); + } + public QueryEnumerable Query() where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData { if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6) && _componentStorage.TryGetPool(out var pool7))) + { return default; + } return new QueryEnumerable( this, @@ -102,4 +224,19 @@ public partial class World pool0.Count); } + public QueryEnumerable QueryFilter(ref readonly QueryFilter filter) + where T0 : unmanaged, IComponentData where T1 : unmanaged, IComponentData where T2 : unmanaged, IComponentData where T3 : unmanaged, IComponentData where T4 : unmanaged, IComponentData where T5 : unmanaged, IComponentData where T6 : unmanaged, IComponentData where T7 : unmanaged, IComponentData + { + if (!(_componentStorage.TryGetPool(out var pool0) && _componentStorage.TryGetPool(out var pool1) && _componentStorage.TryGetPool(out var pool2) && _componentStorage.TryGetPool(out var pool3) && _componentStorage.TryGetPool(out var pool4) && _componentStorage.TryGetPool(out var pool5) && _componentStorage.TryGetPool(out var pool6) && _componentStorage.TryGetPool(out var pool7))) + { + return default; + } + + return new QueryEnumerable( + this, + pool0, pool1, pool2, pool3, pool4, pool5, pool6, pool7, + pool0.Count, + in filter); + } + } \ No newline at end of file diff --git a/Ghost.Entities/Template/World.Query.tt b/Ghost.Entities/Template/World.Query.tt index 950bebd..e6abd39 100644 --- a/Ghost.Entities/Template/World.Query.tt +++ b/Ghost.Entities/Template/World.Query.tt @@ -6,6 +6,7 @@ <#@ include file="Helpers.ttinclude" #> using Ghost.Entities.Components; +using Ghost.Entities.Query; namespace Ghost.Entities; @@ -24,7 +25,9 @@ public partial class World <#= restrictions #> { if (!(<#= tryGetPools #>)) + { return default; + } return new QueryEnumerable<<#= generics #>>( this, @@ -32,5 +35,20 @@ public partial class World <#= countSource #>); } + public QueryEnumerable<<#= generics #>> QueryFilter<<#= generics #>>(ref readonly QueryFilter filter) + <#= restrictions #> + { + if (!(<#= tryGetPools #>)) + { + return default; + } + + return new QueryEnumerable<<#= generics #>>( + this, + <#= poolParams #>, + <#= countSource #>, + in filter); + } + <# } #> } \ No newline at end of file diff --git a/Ghost.Entities/World.cs b/Ghost.Entities/World.cs index fa6dfbe..f773511 100644 --- a/Ghost.Entities/World.cs +++ b/Ghost.Entities/World.cs @@ -1,6 +1,7 @@ using Ghost.Entities.Components; using Ghost.Entities.Query; using Ghost.Entities.Systems; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -51,6 +52,8 @@ public partial class World : IDisposable, IEquatable private readonly ComponentStorage _componentStorage; private readonly SystemStorage _systemStorage; + private bool _isDisposed = false; + internal ComponentStorage ComponentStorage => _componentStorage; public WorldID ID => _id; @@ -67,6 +70,11 @@ public partial class World : IDisposable, IEquatable _systemStorage = new SystemStorage(this); } + ~World() + { + Dispose(); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public CompRef GetSingleton() where T : unmanaged, IComponentData @@ -87,29 +95,20 @@ public partial class World : IDisposable, IEquatable } [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Conditional("GHOST_EDITOR")] public void NotifyComponentChanged(Entity entity, Type type) { - //#if GHOST_EDITOR ComponentChanged?.Invoke(this, entity, type); - //#endif } [MethodImpl(MethodImplOptions.AggressiveInlining)] + [Conditional("GHOST_EDITOR")] public void NotifyComponentChanged(Entity entity) where T : unmanaged, IComponentData { NotifyComponentChanged(entity, typeof(T)); } - public void Dispose() - { - _entityManager.Dispose(); - _componentStorage.Dispose(); - _systemStorage.Dispose(); - - s_freeWorldSlots.Enqueue(_id); - } - public bool Equals(World? other) { if (other is null) @@ -144,4 +143,22 @@ public partial class World : IDisposable, IEquatable { return !(left == right); } + + public void Dispose() + { + if (_isDisposed) + { + return; + } + + _entityManager.Dispose(); + _componentStorage.Dispose(); + _systemStorage.Dispose(); + + s_freeWorldSlots.Enqueue(_id); + + _isDisposed = true; + + GC.SuppressFinalize(this); + } } \ No newline at end of file diff --git a/Ghost.FMOD/Ghost.FMOD.csproj b/Ghost.FMOD/Ghost.FMOD.csproj index 4b5e694..c24c596 100644 --- a/Ghost.FMOD/Ghost.FMOD.csproj +++ b/Ghost.FMOD/Ghost.FMOD.csproj @@ -12,10 +12,10 @@ - + PreserveNewest - + PreserveNewest diff --git a/Ghost.FMOD/fmod.dll b/Ghost.FMOD/runtime/win-x64/native/fmod.dll similarity index 100% rename from Ghost.FMOD/fmod.dll rename to Ghost.FMOD/runtime/win-x64/native/fmod.dll diff --git a/Ghost.FMOD/fmodstudio.dll b/Ghost.FMOD/runtime/win-x64/native/fmodstudio.dll similarity index 100% rename from Ghost.FMOD/fmodstudio.dll rename to Ghost.FMOD/runtime/win-x64/native/fmodstudio.dll diff --git a/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs b/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs index fa73ee1..d1b5c7f 100644 --- a/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs +++ b/Ghost.Graphics/D3D12/D3D12ShaderCompiler.cs @@ -149,21 +149,11 @@ internal unsafe static class D3D12ShaderCompiler // Get compiled bytecode using ComPtr bytecodeBlob = default; - result.Get()->GetResult(bytecodeBlob.GetAddressOf()); - - if (bytecodeBlob.Get() == null) - { - throw new Exception("DXC compilation succeeded but no bytecode was produced"); - } + ThrowIfFailed(result.Get()->GetResult(bytecodeBlob.GetAddressOf())); // Get reflection data using DXC API using ComPtr reflectionBlob = default; - result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof(), reflectionBlob.GetVoidAddressOf(), null); - - if (reflectionBlob.Get() == null) - { - throw new Exception("DXC compilation succeeded but no reflection data was produced"); - } + ThrowIfFailed(result.Get()->GetOutput(DXC_OUT_KIND.DXC_OUT_REFLECTION, __uuidof(), reflectionBlob.GetVoidAddressOf(), null)); var bytecodeSize = bytecodeBlob.Get()->GetBufferSize(); var bytecode = new UnsafeArray((int)bytecodeSize, Misaki.HighPerformance.LowLevel.Buffer.Allocator.Persistent); @@ -210,12 +200,7 @@ internal unsafe static class D3D12ShaderCompiler }; using ComPtr reflection = default; - utils.Get()->CreateReflection(&reflectionData, __uuidof(), reflection.GetVoidAddressOf()); - - if (reflection.Get() == null) - { - throw new Exception("Failed to create shader reflection from DXC output"); - } + ThrowIfFailed(utils.Get()->CreateReflection(&reflectionData, __uuidof(), reflection.GetVoidAddressOf())); D3D12_SHADER_DESC shaderDesc; reflection.Get()->GetDesc(&shaderDesc); diff --git a/Ghost.Graphics/D3D12/Utilities/Win32Utility.cs b/Ghost.Graphics/D3D12/Utilities/Win32Utility.cs index 9bb1206..d8a732e 100644 --- a/Ghost.Graphics/D3D12/Utilities/Win32Utility.cs +++ b/Ghost.Graphics/D3D12/Utilities/Win32Utility.cs @@ -7,10 +7,7 @@ internal unsafe static class Win32Utility { public static void ThrowIfFailed(this HRESULT hr) { - if (hr.FAILED) - { - throw new InvalidOperationException($"Operation failed with HRESULT: 0x{hr.Value:X8}"); - } + Windows.ThrowIfFailed(hr); } public static void** GetVoidAddressOf(this ComPtr comPtr) diff --git a/Ghost.Graphics/Ghost.Graphics.csproj b/Ghost.Graphics/Ghost.Graphics.csproj index 6a0a847..d7603b4 100644 --- a/Ghost.Graphics/Ghost.Graphics.csproj +++ b/Ghost.Graphics/Ghost.Graphics.csproj @@ -19,7 +19,6 @@ - diff --git a/Ghost.Test.Core/ITest.cs b/Ghost.Test.Core/ITest.cs index 9e90435..7365876 100644 --- a/Ghost.Test.Core/ITest.cs +++ b/Ghost.Test.Core/ITest.cs @@ -2,5 +2,9 @@ public interface ITest { + public void Setup(); + public void Run(); + + public void Cleanup(); } diff --git a/Ghost.Test.Core/TestRunner.cs b/Ghost.Test.Core/TestRunner.cs index 2566adf..ac01dbd 100644 --- a/Ghost.Test.Core/TestRunner.cs +++ b/Ghost.Test.Core/TestRunner.cs @@ -6,6 +6,23 @@ public class TestRunner where T : ITest, new() { var test = new T(); + test.Setup(); test.Run(); + test.Cleanup(); + } + + public static void Run(int iteration) + where T : ITest, new() + { + var test = new T(); + test.Setup(); + + iteration = iteration < 1 ? 1 : iteration; + for (var i = 0; i < iteration; i++) + { + test.Run(); + } + + test.Cleanup(); } } \ No newline at end of file diff --git a/Ghost.Zeux.MeshOptimizer/Ghost.Zeux.MeshOptimizer.csproj b/Ghost.Zeux.MeshOptimizer/Ghost.Zeux.MeshOptimizer.csproj index aca78cf..b9e39e0 100644 --- a/Ghost.Zeux.MeshOptimizer/Ghost.Zeux.MeshOptimizer.csproj +++ b/Ghost.Zeux.MeshOptimizer/Ghost.Zeux.MeshOptimizer.csproj @@ -16,7 +16,7 @@ - + PreserveNewest diff --git a/Ghost.Zeux.MeshOptimizer/meshoptimizer_native.dll b/Ghost.Zeux.MeshOptimizer/runtime/win-x64/native/meshoptimizer_native.dll similarity index 100% rename from Ghost.Zeux.MeshOptimizer/meshoptimizer_native.dll rename to Ghost.Zeux.MeshOptimizer/runtime/win-x64/native/meshoptimizer_native.dll diff --git a/GhostEngine.sln b/GhostEngine.sln index 1173a96..0c945b8 100644 --- a/GhostEngine.sln +++ b/GhostEngine.sln @@ -252,7 +252,9 @@ Global {1ED62E09-8F36-4671-896B-16C1C1530202} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70} {0D626DAF-EF18-435C-A85C-EEA1B141E8B5} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221} {8A1C494B-2888-4D0D-8325-9F5C8D1D1955} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70} + {996ABECC-1C5A-4F07-B8AC-D063F91962CB} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221} {4179873E-8174-4D17-9584-8C223BA71366} = {43E76E46-0E5F-4429-83C8-157689885174} + {337D9110-76FC-453C-9481-757052A216E5} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70} {222A4E83-D902-423A-8E99-8321BBFC604C} = {4E666310-F835-4A49-A1A3-AE7CB3FB0221} {F55831B1-2ADE-4CEB-8023-F92C7ABF57FE} = {6051DF88-C573-4BC4-BF98-3C5E807F4D70} {C3AB43A4-88D8-49F8-B738-A738C8BCEE3F} = {43E76E46-0E5F-4429-83C8-157689885174}