From d8a5cd6493518c441a2e865242301b9dc1ab0552 Mon Sep 17 00:00:00 2001 From: evan Date: Mon, 16 Dec 2019 19:55:27 -0800 Subject: [PATCH] message JIT preload --- encompass-cs/Engines/ComponentEmitter.cs | 7 +------ encompass-cs/UberEngine.cs | 26 ++++++++++++++++++++++-- encompass-cs/WorldBuilder.cs | 17 ++++++++++++---- 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/encompass-cs/Engines/ComponentEmitter.cs b/encompass-cs/Engines/ComponentEmitter.cs index b1f7f64..95b61b0 100644 --- a/encompass-cs/Engines/ComponentEmitter.cs +++ b/encompass-cs/Engines/ComponentEmitter.cs @@ -1,12 +1,7 @@ -namespace Encompass +namespace Encompass { internal class ComponentEmitter : Engine where TComponent : struct, IComponent { - public ComponentEmitter() - { - sendTypes.Add(typeof(TComponent)); - } - public override void Update(double dt) { foreach (var (component, entity) in InternalRead()) diff --git a/encompass-cs/UberEngine.cs b/encompass-cs/UberEngine.cs index 035d2ef..18840c7 100644 --- a/encompass-cs/UberEngine.cs +++ b/encompass-cs/UberEngine.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; namespace Encompass @@ -7,13 +8,17 @@ namespace Encompass internal class UberEngine : Engine { private IEnumerable _componentTypes; + private IEnumerable _messageTypes; private Entity _entity; - public UberEngine(Entity entity, IEnumerable componentTypes) + public UberEngine(Entity entity, IEnumerable componentTypes, IEnumerable messageTypes) { _componentTypes = componentTypes; + _messageTypes = messageTypes; readTypes.UnionWith(componentTypes); writeTypes.UnionWith(componentTypes); + sendTypes.UnionWith(messageTypes); + receiveTypes.UnionWith(messageTypes); _entity = entity; } @@ -43,6 +48,16 @@ namespace Encompass CallGenericMethod(type, "DestroyWith", null); CallGenericMethod(type, "DestroyAllWith", null); } + + foreach (var type in _messageTypes) + { + CallGenericMethod(type, "SendMessageIgnoringTimeDilation", new object[] { Activator.CreateInstance(type), 1 }); + CallGenericMethod(type, "SendMessage", 1, new object[] { Activator.CreateInstance(type) }); + CallGenericMethod(type, "SendMessage", 2, new object[] { Activator.CreateInstance(type), 1 }); + CallGenericMethod(type, "ReadMessage", null); + CallGenericMethod(type, "ReadMessages", null); + CallGenericMethod(type, "SomeMessage", null); + } } private void CallGenericMethod(Type type, string methodName, object[] parameters) @@ -58,5 +73,12 @@ namespace Encompass var genericReadComponentMethod = readComponentMethod.MakeGenericMethod(type); genericReadComponentMethod.Invoke(this, parameters); } + + private void CallGenericMethod(Type type, string methodName, int argumentNum, object[] parameters) + { + var method = typeof(Engine).GetRuntimeMethods().Where(m => m.Name == methodName && m.GetParameters().Length == argumentNum).First(); + var genericMethod = method.MakeGenericMethod(type); + genericMethod.Invoke(this, parameters); + } } } diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs index 0eb7a08..0a8dce2 100644 --- a/encompass-cs/WorldBuilder.cs +++ b/encompass-cs/WorldBuilder.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Reflection; using System.Linq; @@ -37,6 +37,8 @@ namespace Encompass private readonly HashSet componentTypesToRegister = new HashSet(); + private readonly HashSet messageTypes = new HashSet(); + public WorldBuilder() { drawLayerManager = new DrawLayerManager(); @@ -98,6 +100,11 @@ namespace Encompass startingComponentStoreForComponentUpdateManager.RegisterComponentType(); } + internal void RegisterMessageTypes(IEnumerable types) + { + messageTypes.UnionWith(types); + } + internal void AddComponentTypeToRegister(Type componentType) { componentTypesToRegister.Add(componentType); @@ -121,6 +128,8 @@ namespace Encompass var messageReceiveTypes = engine.receiveTypes; var messageSendTypes = engine.sendTypes; + RegisterMessageTypes(engine.receiveTypes.Union(engine.sendTypes)); + foreach (var writePendingType in engine.writePendingTypes.Intersect(engine.readPendingTypes)) { throw new EngineSelfCycleException("Engine {0} both writes and reads pending Component {1}", engine.GetType().Name, writePendingType.Name); @@ -352,7 +361,7 @@ namespace Encompass engineOrder.Add(emitterEngine); } - PreloadJIT(componentTypesToRegister); + PreloadJIT(componentTypesToRegister, messageTypes); foreach (var engine in engineGraph.TopologicalSort()) { @@ -379,7 +388,7 @@ namespace Encompass /// This is necessary because Encompass heavily uses generic methods with value types, /// so the first time any code path runs the JIT gets smashed. This method warms up the runtime. /// - private void PreloadJIT(IEnumerable componentTypes) + private void PreloadJIT(IEnumerable componentTypes, IEnumerable messageTypes) { var dummyTimeManager = new TimeManager(); var dummyMessageManager = new MessageManager(dummyTimeManager); @@ -390,7 +399,7 @@ namespace Encompass var dummyRenderManager = new RenderManager(dummyDrawLayerManager); var prepEngineOrder = new List(); - var uberEngine = new UberEngine(dummyEntityManager.CreateEntity(), componentTypes); + var uberEngine = new UberEngine(dummyEntityManager.CreateEntity(), componentTypes, messageTypes); uberEngine.AssignEntityManager(dummyEntityManager); uberEngine.AssignComponentManager(dummyComponentManager);