From a8669a6c670167cef5d504febd6ae2d83705f37b Mon Sep 17 00:00:00 2001 From: Evan Hemsley <2342303+ehemsley@users.noreply.github.com> Date: Sun, 29 Dec 2019 16:28:22 -0800 Subject: [PATCH] starting replay system to avoid replaying every component every frame --- .../Collections/ComponentDeltaStore.cs | 60 +++++++++++++++++++ encompass-cs/Collections/ComponentStore.cs | 16 +++-- encompass-cs/Collections/Replayer.cs | 51 ++++++++++++++++ encompass-cs/ComponentManager.cs | 6 +- encompass-cs/Engine.cs | 13 ---- encompass-cs/Engines/ComponentEmitter.cs | 13 ---- encompass-cs/WorldBuilder.cs | 13 ---- 7 files changed, 126 insertions(+), 46 deletions(-) create mode 100644 encompass-cs/Collections/ComponentDeltaStore.cs create mode 100644 encompass-cs/Collections/Replayer.cs delete mode 100644 encompass-cs/Engines/ComponentEmitter.cs diff --git a/encompass-cs/Collections/ComponentDeltaStore.cs b/encompass-cs/Collections/ComponentDeltaStore.cs new file mode 100644 index 0000000..958c3af --- /dev/null +++ b/encompass-cs/Collections/ComponentDeltaStore.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; + +namespace Encompass +{ + internal class ComponentDeltaStore : ComponentStore + { + private readonly Dictionary _replayers = new Dictionary(); + private readonly HashSet _currentReplayers = new HashSet(); + + public IEnumerable CurrentReplayers { get { return _currentReplayers; } } + + public ComponentDeltaStore(Dictionary typeToIndex) : base(typeToIndex) + { + } + + public override void RegisterComponentType() + { + base.RegisterComponentType(); + if (!_replayers.ContainsKey(typeof(TComponent))) + { + _replayers.Add(typeof(TComponent), new Replayer(this)); + } + } + + public override bool Set(int entityID, TComponent component, int priority) + { + var result = base.Set(entityID, component, priority); + if (result) + { + var replayer = _replayers[typeof(TComponent)]; + _currentReplayers.Add(replayer); + replayer.UnMarkRemoval(entityID); + } + return result; + } + + public override bool Remove(int entityID, int priority) + { + var result = base.Remove(entityID, priority); + if (result) + { + var replayer = _replayers[typeof(TComponent)]; + _currentReplayers.Add(replayer); + replayer.MarkRemoval(entityID); + } + return result; + } + + public override void ClearAll() + { + base.ClearAll(); + foreach (var replayer in _currentReplayers) + { + replayer.Clear(); + } + _currentReplayers.Clear(); + } + } +} diff --git a/encompass-cs/Collections/ComponentStore.cs b/encompass-cs/Collections/ComponentStore.cs index 03904b1..337f610 100644 --- a/encompass-cs/Collections/ComponentStore.cs +++ b/encompass-cs/Collections/ComponentStore.cs @@ -22,7 +22,7 @@ namespace Encompass } } - public void RegisterComponentType() where TComponent : struct, IComponent + public virtual void RegisterComponentType() where TComponent : struct, IComponent { if (!Stores.ContainsKey(typeof(TComponent))) { @@ -63,7 +63,7 @@ namespace Encompass ComponentBitSet.Set(entityID); } - public bool Set(int entityID, TComponent component, int priority) where TComponent : struct, IComponent + public virtual bool Set(int entityID, TComponent component, int priority) where TComponent : struct, IComponent { if (Lookup().Set(entityID, component, priority)) { @@ -73,7 +73,7 @@ namespace Encompass return false; } - public bool Remove(int entityID, int priority) where TComponent : struct, IComponent + public virtual bool Remove(int entityID, int priority) where TComponent : struct, IComponent { if (Lookup().Remove(entityID, priority)) { @@ -123,7 +123,7 @@ namespace Encompass Lookup().Clear(); } - public void ClearAll() + public virtual void ClearAll() { ComponentBitSet.Clear(); foreach (var store in Stores.Values) @@ -137,5 +137,13 @@ namespace Encompass (Stores, other.Stores) = (other.Stores, Stores); (ComponentBitSet, other.ComponentBitSet) = (other.ComponentBitSet, ComponentBitSet); } + + public void UpdateUsing(ComponentDeltaStore delta) + { + foreach (var replayer in delta.CurrentReplayers) + { + replayer.Replay(this); + } + } } } diff --git a/encompass-cs/Collections/Replayer.cs b/encompass-cs/Collections/Replayer.cs new file mode 100644 index 0000000..b5cd3f7 --- /dev/null +++ b/encompass-cs/Collections/Replayer.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; + +namespace Encompass +{ + internal abstract class Replayer + { + public abstract void Replay(ComponentStore store); + public abstract void MarkRemoval(int entityID); + public abstract void UnMarkRemoval(int entityID); + public abstract void Clear(); + } + + internal class Replayer : Replayer where TComponent : struct, IComponent + { + private readonly ComponentDeltaStore _deltaStore; + private readonly HashSet _removals = new HashSet(); + + public Replayer(ComponentDeltaStore componentStore) + { + _deltaStore = componentStore; + } + + public override void Replay(ComponentStore store) + { + foreach (var (component, entityID) in _deltaStore.All()) + { + store.Set(entityID, component); + } + + foreach (var entityID in _removals) + { + store.ForceRemove(entityID); + } + } + + public override void Clear() + { + _removals.Clear(); + } + + public override void MarkRemoval(int entityID) + { + _removals.Add(entityID); + } + + public override void UnMarkRemoval(int entityID) + { + _removals.Remove(entityID); + } + } +} diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs index a97096e..f913e70 100644 --- a/encompass-cs/ComponentManager.cs +++ b/encompass-cs/ComponentManager.cs @@ -8,7 +8,7 @@ namespace Encompass private readonly DrawLayerManager drawLayerManager; private readonly ComponentStore existingComponentStore; - private readonly ComponentStore immediateComponentStore; + private readonly ComponentDeltaStore immediateComponentStore; private ComponentStore upToDateComponentStore; public Dictionary TypeToIndex { get; } @@ -22,7 +22,7 @@ namespace Encompass { this.drawLayerManager = drawLayerManager; existingComponentStore = new ComponentStore(typeToIndex); - immediateComponentStore = new ComponentStore(typeToIndex); + immediateComponentStore = new ComponentDeltaStore(typeToIndex); upToDateComponentStore = new ComponentStore(typeToIndex); TypeToIndex = typeToIndex; } @@ -47,7 +47,7 @@ namespace Encompass internal void WriteComponents() { SetComponentStore(upToDateComponentStore); - upToDateComponentStore.ClearAll(); + upToDateComponentStore.UpdateUsing(immediateComponentStore); immediateComponentStore.ClearAll(); } diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs index ec341d7..9b2b2b0 100644 --- a/encompass-cs/Engine.cs +++ b/encompass-cs/Engine.cs @@ -250,14 +250,6 @@ namespace Encompass } } - internal IEnumerable<(TComponent, Entity)> InternalRead() where TComponent : struct, IComponent - { - foreach (var (component, id) in componentManager.GetComponentsIncludingEntity()) - { - yield return (component, entityManager.GetEntity(id)); - } - } - private (TComponent, int) ReadComponentHelper() where TComponent : struct, IComponent { var immediateRead = readImmediateTypes.Contains(typeof(TComponent)); @@ -490,11 +482,6 @@ namespace Encompass messageManager.AddMessageIgnoringTimeDilation(message, time); } - internal void AddExistingComponent(int entityID, TComponent component) where TComponent : struct, IComponent - { - componentManager.AddExistingComponent(entityID, component); - } - /// /// Reads all messages of the specified Type. /// diff --git a/encompass-cs/Engines/ComponentEmitter.cs b/encompass-cs/Engines/ComponentEmitter.cs deleted file mode 100644 index 2a7bd2d..0000000 --- a/encompass-cs/Engines/ComponentEmitter.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Encompass -{ - internal class ComponentEmitter : Engine where TComponent : struct, IComponent - { - public override void Update(double dt) - { - foreach (var (component, entity) in InternalRead()) - { - AddExistingComponent(entity.ID, component); - } - } - } -} diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 16b9ff8..5fae89a 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -371,10 +371,6 @@ namespace Encompass var method = typeof(WorldBuilder).GetMethod("RegisterComponentType", BindingFlags.NonPublic | BindingFlags.Instance); var generic = method.MakeGenericMethod(registeredComponentType); generic.Invoke(this, null); - - var emitterEngine = (Engine)Activator.CreateInstance(typeof(ComponentEmitter<>).MakeGenericType(registeredComponentType)); - AddEngine(emitterEngine); - engineOrder.Add(emitterEngine); } PreloadJIT(componentTypesToRegister, messageTypes); @@ -444,15 +440,6 @@ namespace Encompass var drawLayerManagerRegisterGenericMethod = drawLayerManagerRegisterMethod.MakeGenericMethod(type); drawLayerManagerRegisterGenericMethod.Invoke(dummyDrawLayerManager, null); } - - var emitterEngine = (Engine)Activator.CreateInstance(typeof(ComponentEmitter<>).MakeGenericType(type)); - emitterEngine.AssignEntityManager(dummyEntityManager); - emitterEngine.AssignComponentManager(dummyComponentManager); - emitterEngine.AssignMessageManager(dummyMessageManager); - emitterEngine.AssignTimeManager(dummyTimeManager); - emitterEngine.AssignTrackingManager(dummyTrackingManager); - - prepEngineOrder.Add(emitterEngine); } prepEngineOrder.Add(uberEngine);