starting replay system to avoid replaying every component every frame

pull/5/head
Evan Hemsley 2019-12-29 16:28:22 -08:00
parent 1eb72874c1
commit a8669a6c67
7 changed files with 126 additions and 46 deletions

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
namespace Encompass
{
internal class ComponentDeltaStore : ComponentStore
{
private readonly Dictionary<Type, Replayer> _replayers = new Dictionary<Type, Replayer>();
private readonly HashSet<Replayer> _currentReplayers = new HashSet<Replayer>();
public IEnumerable<Replayer> CurrentReplayers { get { return _currentReplayers; } }
public ComponentDeltaStore(Dictionary<Type, int> typeToIndex) : base(typeToIndex)
{
}
public override void RegisterComponentType<TComponent>()
{
base.RegisterComponentType<TComponent>();
if (!_replayers.ContainsKey(typeof(TComponent)))
{
_replayers.Add(typeof(TComponent), new Replayer<TComponent>(this));
}
}
public override bool Set<TComponent>(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<TComponent>(int entityID, int priority)
{
var result = base.Remove<TComponent>(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();
}
}
}

View File

@ -22,7 +22,7 @@ namespace Encompass
}
}
public void RegisterComponentType<TComponent>() where TComponent : struct, IComponent
public virtual void RegisterComponentType<TComponent>() where TComponent : struct, IComponent
{
if (!Stores.ContainsKey(typeof(TComponent)))
{
@ -63,7 +63,7 @@ namespace Encompass
ComponentBitSet.Set<TComponent>(entityID);
}
public bool Set<TComponent>(int entityID, TComponent component, int priority) where TComponent : struct, IComponent
public virtual bool Set<TComponent>(int entityID, TComponent component, int priority) where TComponent : struct, IComponent
{
if (Lookup<TComponent>().Set(entityID, component, priority))
{
@ -73,7 +73,7 @@ namespace Encompass
return false;
}
public bool Remove<TComponent>(int entityID, int priority) where TComponent : struct, IComponent
public virtual bool Remove<TComponent>(int entityID, int priority) where TComponent : struct, IComponent
{
if (Lookup<TComponent>().Remove(entityID, priority))
{
@ -123,7 +123,7 @@ namespace Encompass
Lookup<TComponent>().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);
}
}
}
}

View File

@ -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<TComponent> : Replayer where TComponent : struct, IComponent
{
private readonly ComponentDeltaStore _deltaStore;
private readonly HashSet<int> _removals = new HashSet<int>();
public Replayer(ComponentDeltaStore componentStore)
{
_deltaStore = componentStore;
}
public override void Replay(ComponentStore store)
{
foreach (var (component, entityID) in _deltaStore.All<TComponent>())
{
store.Set(entityID, component);
}
foreach (var entityID in _removals)
{
store.ForceRemove<TComponent>(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);
}
}
}

View File

@ -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<Type, int> 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();
}

View File

@ -250,14 +250,6 @@ namespace Encompass
}
}
internal IEnumerable<(TComponent, Entity)> InternalRead<TComponent>() where TComponent : struct, IComponent
{
foreach (var (component, id) in componentManager.GetComponentsIncludingEntity<TComponent>())
{
yield return (component, entityManager.GetEntity(id));
}
}
private (TComponent, int) ReadComponentHelper<TComponent>() where TComponent : struct, IComponent
{
var immediateRead = readImmediateTypes.Contains(typeof(TComponent));
@ -490,11 +482,6 @@ namespace Encompass
messageManager.AddMessageIgnoringTimeDilation(message, time);
}
internal void AddExistingComponent<TComponent>(int entityID, TComponent component) where TComponent : struct, IComponent
{
componentManager.AddExistingComponent(entityID, component);
}
/// <summary>
/// Reads all messages of the specified Type.
/// </summary>

View File

@ -1,13 +0,0 @@
namespace Encompass
{
internal class ComponentEmitter<TComponent> : Engine where TComponent : struct, IComponent
{
public override void Update(double dt)
{
foreach (var (component, entity) in InternalRead<TComponent>())
{
AddExistingComponent(entity.ID, component);
}
}
}
}

View File

@ -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);