From d3f7593afc071752f47b214c2c3e18ad3a042383 Mon Sep 17 00:00:00 2001 From: Mergul Date: Thu, 25 Oct 2018 11:46:08 +0200 Subject: [PATCH] -BlockAllocator is no longer template -Multithreaded IDManager.getNewID() *use implementation with free IDs stack (instead of classic pool) -support for multiple UpdatePasses. Passes are added by name, and must be called between begin() end() functions. -removed mutex from addEntity() -commit() function added. Used to commit all changes made while update() call. Called automatically by begin() end() functions. --- source/ecs/block_allocator.d | 5 +- source/ecs/events.d | 6 +- source/ecs/id_manager.d | 169 +++++++++++++-- source/ecs/manager.d | 397 ++++++++++++++++++++--------------- source/ecs/system.d | 4 +- tests/tests.d | 14 +- 6 files changed, 406 insertions(+), 189 deletions(-) diff --git a/source/ecs/block_allocator.d b/source/ecs/block_allocator.d index 30afcc8..29b1fb3 100644 --- a/source/ecs/block_allocator.d +++ b/source/ecs/block_allocator.d @@ -5,8 +5,11 @@ import ecs.manager; import std.experimental.allocator; import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator; -struct BlockAllocator(uint block_size, uint blocks_in_allocation) +struct BlockAllocator//(uint block_size, uint blocks_in_allocation) { + private uint block_size; + private uint blocks_in_allocation; + void* next_block = null; void* getBlock() diff --git a/source/ecs/events.d b/source/ecs/events.d index 3a09bc8..20c8c0e 100644 --- a/source/ecs/events.d +++ b/source/ecs/events.d @@ -17,10 +17,10 @@ mixin template EventManagerCode() //@disable this(); - this(EntityManager m) + /*this(EntityManager m) { manager = m; - } + }*/ void sendSelfEvent(Ev)(EntityID id, Ev event) { @@ -120,6 +120,6 @@ mixin template EventManagerCode() EventList current_events; EventList process_events; - BlockAllocator!(events_block_size, events_blocks_in_allocation) allocator; + BlockAllocator/*!(events_block_size, events_blocks_in_allocation)*/ allocator; EntityManager manager; } diff --git a/source/ecs/id_manager.d b/source/ecs/id_manager.d index cd2fbb7..1e8ebad 100644 --- a/source/ecs/id_manager.d +++ b/source/ecs/id_manager.d @@ -1,8 +1,15 @@ module ecs.id_manager; +import std.experimental.allocator; +import std.experimental.allocator.mallocator : AlignedMallocator, Mallocator; + import ecs.entity; import ecs.vector; +import core.atomic; +import core.stdc.string : memcpy; +import core.sync.mutex; + /************************************************************************************************************************ *IDManager is responsible for assignment and removing IDs. IDs are unique throughtout a whole duration of the program. */ @@ -11,17 +18,62 @@ struct IDManager /************************************************************************************************************************ *Get new ID. */ - EntityID getNewID() + pragma(inline, false) EntityID getNewID() { - if (m_next_id >= m_ids_array.length) - m_ids_array.add(Data()); + //uint current = m_next_id; + //uint next;// = m_ids_array[m_next_id].next_id; +begin: + //if (current == uint.max)//> m_last_id) + int current = m_stack_top.atomicOp!"-="(1) + 1; + if(current < 0) + { + uint add_id = m_last_id.atomicOp!"+="(1) - 1; + + if (add_id >= m_ids_array.length) + { + uint local_id = add_id - cast(uint) m_ids_array.length; + uint block_id = local_id >> 16; + if (block_id >= m_blocks_count) + { + add_mutex.lock(); + if(block_id >= m_blocks_count) + { + m_blocks[m_blocks_count].alloc(); + m_blocks_count++; + } + add_mutex.unlock(); + } + } + + EntityID id; + id.id = add_id; + id.counter = 0; + return id; + } + + + //current += 1; + uint index = m_free_stack[current]; EntityID id; - id.id = m_next_id; - id.counter = /*++*/m_ids_array[m_next_id].counter; - m_next_id = m_ids_array[m_next_id].next_id; - if (m_next_id == uint.max) - m_next_id = cast(uint) m_ids_array.length; + id.id = index; + id.counter = m_ids_array[index].counter; + //current = m_ids_array[index].next_id; return id; + + /*next = m_ids_array[current].next_id; + if(cas(&m_next_id,current,next)) + { + EntityID id; + id.id = current; + id.counter = m_ids_array[current].counter; + m_next_id = m_ids_array[current].next_id; + return id; + } + else + { + current = next; + goto begin; + }*/ } /************************************************************************************************************************ @@ -33,9 +85,12 @@ struct IDManager if (data.counter != id.counter) return; data.counter++; - data.next_id = m_next_id; + //data.next_id = m_next_id; data.entity = null; - m_next_id = id.id; + ///m_next_id = id.id; + + m_stack_top.atomicOp!"+="(1); + m_free_stack[m_stack_top] = id.id; } /************************************************************************************************************************ @@ -43,7 +98,15 @@ struct IDManager */ void update(ref Entity entity) { - if(entity.id.counter == m_ids_array[entity.id.id].counter)m_ids_array[entity.id.id].entity = &entity; + if (entity.id.id >= cast(uint) m_ids_array.length) + { + uint local_id = entity.id.id - cast(uint) m_ids_array.length; + uint block_id = local_id >> 16; + local_id -= block_id << 16; + m_blocks[block_id].data[local_id].entity = &entity; + } + else //if (entity.id.counter == m_ids_array[entity.id.id].counter) + m_ids_array[entity.id.id].entity = &entity; } /************************************************************************************************************************ @@ -51,6 +114,19 @@ struct IDManager */ export Entity* getEntityPointer(EntityID id) { + if (id.id >= m_ids_array.length) + { + uint local_id = id.id - cast(uint) m_ids_array.length; + uint block_id = local_id >> 16; + assert(block_id < m_blocks_count); + if (block_id >= m_blocks_count) + return null; + local_id -= block_id << 16; + if (m_blocks[block_id].data[local_id].counter != id.counter) + return null; + return m_blocks[block_id].data[local_id].entity; + } + Data* data = &m_ids_array[id.id]; if (data.counter != id.counter) return null; @@ -67,16 +143,81 @@ struct IDManager return data.counter == id.counter; } + void initialize() + { + m_ids_array = Mallocator.instance.makeArray!Data(65536); + m_free_stack = Mallocator.instance.makeArray!uint(65536); + m_blocks = Mallocator.instance.makeArray!Block(64); + m_blocks_count = 1; + m_blocks[0].alloc(); + + add_mutex = Mallocator.instance.make!Mutex(); + } + + void optimize() + { + if(m_stack_top < -1)m_stack_top = -1; + if(m_last_id > m_ids_array.length) + { + uint begin = cast(uint)m_ids_array.length; + Data[] new_array = Mallocator.instance.makeArray!Data(begin + (m_blocks_count << 16)); + memcpy(new_array.ptr, m_ids_array.ptr, m_ids_array.length * Data.sizeof); + Mallocator.instance.dispose(m_ids_array); + m_ids_array = new_array; + + uint[] new_stack = Mallocator.instance.makeArray!uint(m_ids_array.length); + memcpy(new_stack.ptr,m_free_stack.ptr,m_free_stack.length * uint.sizeof); + Mallocator.instance.dispose(m_free_stack); + m_free_stack = new_stack; + + foreach(block;m_blocks[0..m_blocks_count-1]) + { + memcpy(cast(void*)m_ids_array.ptr + begin * Data.sizeof, block.data.ptr, 65536 * Data.sizeof); + begin += 65536; + } + memcpy(cast(void*)m_ids_array.ptr + begin * Data.sizeof, m_blocks[m_blocks_count-1].data.ptr, (m_last_id - begin) * Data.sizeof); + foreach(block;m_blocks[1..m_blocks_count])block.free(); + m_blocks_count = 1; + } + } + + private static struct Block + { + void alloc() + { + assert(data is null); + data = Mallocator.instance.makeArray!Data(65536); + } + + void free() + { + assert(data !is null); + Mallocator.instance.dispose(data); + } + + Data[] data; //65536 + } + private static struct Data { uint counter = 0; - uint next_id = uint.max; + //uint next_id = uint.max; Entity* entity = null; } private: - uint m_next_id; - Vector!Data m_ids_array; + Mutex add_mutex; + //shared uint m_next_id = 0; + + //shared uint m_last_id = 0; + Data[] m_ids_array = null; + uint m_blocks_count = 0; + Block[] m_blocks; + //shared int m_stack_top = -1; + uint[] m_free_stack = null; + + align(64) shared uint m_last_id = 0; + align(64) shared int m_stack_top = -1; } unittest diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 9132a39..ffea30a 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -59,10 +59,30 @@ class EntityManager threads_count = 0; threads = Mallocator.instance.makeArray!ThreadData(threads_count); - add_mutex = Mallocator.instance.make!Mutex; + id_manager.initialize(); + + allocator = BlockAllocator(page_size,pages_in_block); + + //add_mutex = Mallocator.instance.make!Mutex; entity_block_alloc_mutex = Mallocator.instance.make!Mutex; //event_manager = EventManager(this); //event_manager.manager = this; + + UpdatePass* pass = Mallocator.instance.make!UpdatePass; + pass.name = Mallocator.instance.makeArray("update"); + passes.add(pass); + + passes_map.add(cast(string)pass.name, cast(ushort)(passes.length - 1)); + } + + /************************************************************************************************************************ + *Same as "void registerSystem(Sys)(int priority, int pass = 0)" but use pass name instead of id. + */ + void registerSystem(Sys)(int priority, const (char)[] pass_name) + { + ushort pass = passes_map.get(pass_name, ushort.max); + assert(pass != ushort.max); + registerSystem!(Sys)(priority, pass); } /************************************************************************************************************************ @@ -73,11 +93,14 @@ class EntityManager *params: *priority = system priority. Priority determines order of execution of systems updates. */ - void registerSystem(Sys)(int priority) + void registerSystem(Sys)(int priority, ushort pass = 0) { alias STC = ParameterStorageClass; + assert(pass < passes.length); + System system; + system.m_pass = pass; static if (!(hasMember!(Sys, "system_id")) || !is(typeof(Sys.system_id) == ushort)) { @@ -450,10 +473,6 @@ class EntityManager mixin(genCompList()); - /*if(system.m_components)qsort(system.m_components.ptr, system.m_components.length, ushort.sizeof, &compareUShorts); - if(system.m_optional_components)qsort(system.m_optional_components.ptr, system.m_optional_components.length, ushort.sizeof, &compareUShorts); - if(system.m_absent_components)qsort(system.m_absent_components.ptr, system.m_absent_components.length, ushort.sizeof, &compareUShorts);*/ - ushort sys_id = systems_map.get(Sys.stringof, ushort.max); if (sys_id < systems.length) { @@ -492,13 +511,13 @@ class EntityManager version (UpdateBySystems) { bool added = false; - foreach (i, ref caller; system_callers) + foreach (i, ref caller; passes[pass].system_callers) { if (systems[caller.system_id].priority > priority) { SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller; sys_caller.system_id = Sys.system_id; - system_callers.add(sys_caller, i); + passes[pass].system_callers.add(sys_caller, i); added = true; break; } @@ -507,7 +526,7 @@ class EntityManager { SystemCaller* sys_caller = Mallocator.instance.make!SystemCaller; sys_caller.system_id = Sys.system_id; - system_callers.add(sys_caller); + passes[pass].system_callers.add(sys_caller); } } } @@ -525,6 +544,15 @@ class EntityManager return cast(Sys*) systems[Sys.system_id].m_system_pointer; } + ushort registerPass(const (char)[] name) + { + UpdatePass* pass = Mallocator.instance.make!UpdatePass; + pass.name = Mallocator.instance.makeArray(name); + passes.add(pass); + passes_map.add(name,cast(ushort)(passes.length - 1)); + return cast(ushort)(passes.length - 1); + } + /************************************************************************************************************************ *Register component into EntityManager. */ @@ -564,7 +592,7 @@ class EntityManager { components.add(info); Comp.component_id = cast(ushort)(components.length - 1); - string name = Mallocator.instance.makeArray(Comp.stringof); + const (char)[] name = Mallocator.instance.makeArray(Comp.stringof); components_map.add(name, cast(ushort)(components.length - 1)); } } @@ -605,14 +633,25 @@ class EntityManager } } + /************************************************************************************************************************ + *Same as "void update(int pass = 0)" but use pass name instead of id. + */ + void update(const (char)[] pass_name) + { + ushort pass = passes_map.get(pass_name, ushort.max); + assert(pass != ushort.max); + update(pass); + } + /************************************************************************************************************************ *Update systems. Should be called only between begin() and end(). */ - export void update() + export void update(ushort pass = 0) { + assert(pass < passes.length); version (UpdateBySystems) { - foreach (caller; system_callers) + foreach (caller; passes[pass].system_callers) { System* sys = &systems[caller.system_id]; if (sys.enabled) @@ -644,14 +683,25 @@ class EntityManager } } - void updateMT() + /************************************************************************************************************************ + *Same as "void updateMT(int pass = 0)" but use pass name instead of id. + */ + void updateMT(const (char)[] pass_name) { + ushort pass = passes_map.get(pass_name, ushort.max); + assert(pass != ushort.max); + updateMT(pass); + } + + void updateMT(ushort pass = 0) + { + assert(pass < passes.length); assert(m_dispatch_jobs, "Can't update with multithreading without JobDispatch function. Please use setJobDispatchFunc()."); Vector!CallData tmp_datas; tmp_datas.reserve(8); - foreach (caller; system_callers) + foreach (caller; passes[pass].system_callers) { System* sys = &systems[caller.system_id]; if (sys.enabled) @@ -766,7 +816,7 @@ class EntityManager nextJob(); caller.job_group.jobs = sys.jobs[0 .. job_id]; - m_dispatch_jobs(caller.job_group);//sys.jobs[0 .. job_id]); + m_dispatch_jobs(caller.job_group); //sys.jobs[0 .. job_id]); } } } @@ -978,14 +1028,14 @@ class EntityManager } uint index = 0; - for (; index < system_callers.length; index++) + for (; index < passes[system.m_pass].system_callers.length; index++) { - if (system_callers[index].system_id == system_id) + if (passes[system.m_pass].system_callers[index].system_id == system_id) break; } - if (index < system_callers.length) - system_callers[index].infos.add(&entity); + if (index < passes[system.m_pass].system_callers.length) + passes[system.m_pass].system_callers[index].infos.add(&entity); /*for (; index < entity.callers.length; index++) { CallData* caller = &entity.callers[index]; @@ -1137,10 +1187,6 @@ class EntityManager del_ids[i] = comp.component_id; } - /*change_entities_list.add(0); - change_entities_list.add((cast(ubyte*)&entity_id)[0..8]); - change_entities_list.add((cast(ubyte*)&num)[0..4]); - change_entities_list.add(cast(ubyte[])del_ids);*/ removeComponents(entity_id, del_ids); } @@ -1361,9 +1407,9 @@ class EntityManager threads[thread_id].blocks_to_update.add(block); Entity* entity = cast(Entity*) start; - add_mutex.lock_nothrow(); + //add_mutex.lock_nothrow(); entity.id = id_manager.getNewID(); - add_mutex.unlock_nothrow(); + //add_mutex.unlock_nothrow(); entity.updateID(); return *entity; @@ -1605,28 +1651,28 @@ class EntityManager } } + export void commit() + { + id_manager.optimize(); + updateBlocks(); + removeEntities(); + changeEntities(); + } + /************************************************************************************************************************ *Begin of update process. Should be called before any update is called. */ export void begin() { - updateBlocks(); - removeEntities(); - changeEntities(); + + commit(); m_call_data_allocator.clear(); - /*version (UpdateBySystems) - { - - } - else - {*/ foreach (ref system; instance.systems) { if (system.m_begin) (cast(void function(void*)) system.m_begin)(system.m_system_pointer); } - //} } /************************************************************************************************************************ @@ -1634,22 +1680,14 @@ class EntityManager */ export void end() { - /*version (UpdateBySystems) - { - - } - else - {*/ + foreach (ref system; instance.systems) { if (system.m_end) (cast(void function(void*)) system.m_end)(system.m_system_pointer); } - //} - updateBlocks(); - removeEntities(); - changeEntities(); + commit(); //clearEvents(); } @@ -1665,140 +1703,149 @@ class EntityManager /*private */ void generateDependencies() { - foreach (caller; system_callers) + foreach(pass_id,pass;passes) { - caller.system = &systems[caller.system_id]; - if(caller.exclusion)Mallocator.instance.dispose(caller.exclusion); - if(caller.dependencies)Mallocator.instance.dispose(caller.dependencies); - } - uint index = 0; - SystemCaller*[] exclusion; - exclusion = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * system_callers.length))[0 - .. system_callers.length]; - foreach (caller; system_callers) - { - index = 0; - out_for: foreach (caller2; system_callers) + foreach (caller; pass.system_callers) { - if (/*caller.system.priority != caller2.system.priority ||*/ caller is caller2) - continue; - foreach (cmp; caller.system.m_read_only_components) - { - foreach (cmp2; caller2.system.m_modified_components) - { - if (cmp == cmp2) - { - exclusion[index++] = caller2; - continue out_for; - } - } - } - foreach (cmp; caller.system.m_modified_components) - { - foreach (cmp2; caller2.system.m_read_only_components) - { - if (cmp == cmp2) - { - exclusion[index++] = caller2; - continue out_for; - } - } - foreach (cmp2; caller2.system.m_modified_components) - { - if (cmp == cmp2) - { - exclusion[index++] = caller2; - continue out_for; - } - } - } + caller.system = &systems[caller.system_id]; + if (caller.exclusion) + Mallocator.instance.dispose(caller.exclusion); + if (caller.dependencies) + Mallocator.instance.dispose(caller.dependencies); } - - - if(index > 0)caller.exclusion = Mallocator.instance.makeArray(exclusion[0..index]); - else caller.exclusion = null; - - /*import std.stdio; - write("Exclusive systems for system ", caller.system.name, ": "); - foreach (ex; exclusion[0 .. index]) - write(ex.system.name, " "); - writeln();*/ - } - - extern (C) static int compareSystems(const void* a, const void* b) - { - SystemCaller* _a = *cast(SystemCaller**) a; - SystemCaller* _b = *cast(SystemCaller**) b; - if (_a.system.priority < _b.system.priority) - return -1; - else if (_a.system.priority == _b.system.priority) + uint index = 0; + SystemCaller*[] exclusion; + exclusion = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * pass.system_callers.length))[0 + .. pass.system_callers.length]; + foreach (caller; pass.system_callers) { - if (_a.exclusion.length < _b.exclusion.length) + index = 0; + out_for: foreach (caller2; pass.system_callers) + { + if ( /*caller.system.priority != caller2.system.priority ||*/ caller is caller2) + continue; + foreach (cmp; caller.system.m_read_only_components) + { + foreach (cmp2; caller2.system.m_modified_components) + { + if (cmp == cmp2) + { + exclusion[index++] = caller2; + continue out_for; + } + } + } + foreach (cmp; caller.system.m_modified_components) + { + foreach (cmp2; caller2.system.m_read_only_components) + { + if (cmp == cmp2) + { + exclusion[index++] = caller2; + continue out_for; + } + } + foreach (cmp2; caller2.system.m_modified_components) + { + if (cmp == cmp2) + { + exclusion[index++] = caller2; + continue out_for; + } + } + } + } + + if (index > 0) + caller.exclusion = Mallocator.instance.makeArray(exclusion[0 .. index]); + else + caller.exclusion = null; + + /*import std.stdio; + write("Exclusive systems for system ", caller.system.name, ": "); + foreach (ex; exclusion[0 .. index]) + write(ex.system.name, " "); + writeln();*/ + } + + extern (C) static int compareSystems(const void* a, const void* b) + { + SystemCaller* _a = *cast(SystemCaller**) a; + SystemCaller* _b = *cast(SystemCaller**) b; + if (_a.system.priority < _b.system.priority) return -1; - else if (_a.exclusion.length == _b.exclusion.length) - return 0; + else if (_a.system.priority == _b.system.priority) + { + if (_a.exclusion.length < _b.exclusion.length) + return -1; + else if (_a.exclusion.length == _b.exclusion.length) + return 0; + else + return 1; + } else return 1; } - else - return 1; - } - qsort(system_callers.array.ptr, system_callers.length, (SystemCaller*) - .sizeof, &compareSystems); + qsort(pass.system_callers.array.ptr, pass.system_callers.length, (SystemCaller*) + .sizeof, &compareSystems); - /*static struct CallerData - { - uint id; - //bool - }*/ - - /*caller_data = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * system_callers.length))[0 - .. system_callers.length];*/ - - foreach(uint i,caller;system_callers)caller.job_group.id = i; - - int priority = int.min; - uint beg = 0; - index = 0; - foreach(uint i,caller;system_callers) - { - /* - if(priority == int.min)priority = caller.system.priority; - if(priority != caller.system.priority) + /*static struct CallerData { - foreach(caller2;system_callers[beg..i]) - { - - } - priority = caller.system.priority; - beg = i; + uint id; + //bool }*/ + + /*caller_data = (cast(SystemCaller**) alloca((SystemCaller*).sizeof * pass.system_callers.length))[0 + .. pass.system_callers.length];*/ + + foreach (uint i, caller; pass.system_callers) + caller.job_group.id = i; + + int priority = int.min; + uint beg = 0; index = 0; - foreach(ex;caller.exclusion) + foreach (uint i, caller; pass.system_callers) { - if(ex.job_group.id > caller.job_group.id)continue; - - exclusion[index++] = ex; - } - - if(index > 0) - { - caller.dependencies = Mallocator.instance.makeArray(exclusion[0..index]); - caller.job_group.dependencies = Mallocator.instance.makeArray!(JobGroup*)(index); - - foreach(j,dep;caller.dependencies) + /* + if(priority == int.min)priority = caller.system.priority; + if(priority != caller.system.priority) { - caller.job_group.dependencies[j] = &dep.job_group; - } - } - else caller.dependencies = null; + foreach(caller2;pass.system_callers[beg..i]) + { + + } + priority = caller.system.priority; + beg = i; + }*/ + index = 0; + foreach (ex; caller.exclusion) + { + if (ex.job_group.id > caller.job_group.id) + continue; - /*import std.stdio; - write("Dependencies for system ", caller.system.name, ": "); - foreach (ex; caller.dependencies) - write(ex.system.name, " "); - writeln();*/ + exclusion[index++] = ex; + } + + if (index > 0) + { + caller.dependencies = Mallocator.instance.makeArray(exclusion[0 .. index]); + caller.job_group.dependencies = Mallocator.instance.makeArray!(JobGroup*)(index); + + foreach (j, dep; caller.dependencies) + { + caller.job_group.dependencies[j] = &dep.job_group; + } + } + else + caller.dependencies = null; + + /*import std.stdio; + write("Dependencies for system ", caller.system.name, ": "); + foreach (ex; caller.dependencies) + write(ex.system.name, " "); + writeln();*/ + } } } @@ -1963,11 +2010,24 @@ class EntityManager Vector!(EntitiesBlock*) blocks_to_update; } + struct UpdatePass + { + ~this() + { + assert(name); + if(name)Mallocator.instance.dispose(name); + } + char[] name; + Vector!(SystemCaller*) system_callers; + } + static uint thread_id; ThreadData[] threads; - Vector!(SystemCaller*) system_callers; + Vector!(UpdatePass*) passes; + + //Vector!(SystemCaller*) system_callers; alias SytemFuncType = void function(ref EntityManager.CallData data); @@ -1981,7 +2041,7 @@ class EntityManager enum pages_in_block = 128; IDManager id_manager; - BlockAllocator!(page_size, pages_in_block) allocator; + BlockAllocator/*!(page_size, pages_in_block)*/ allocator; //EventManager event_manager; mixin EventManagerCode; @@ -1995,13 +2055,14 @@ class EntityManager HashMap!(ushort[], EntityInfo*) entities_infos; HashMap!(const(char)[], ushort) systems_map; - HashMap!(string, ushort) components_map; - HashMap!(string, ushort) events_map; + HashMap!(const(char)[], ushort) components_map; + HashMap!(const(char)[], ushort) events_map; + HashMap!(const(char)[], ushort) passes_map; Vector!System systems; Vector!ComponentInfo components; Vector!EventInfo events; - Mutex add_mutex; + //Mutex add_mutex; Mutex entity_block_alloc_mutex; CallDataAllocator m_call_data_allocator; diff --git a/source/ecs/system.d b/source/ecs/system.d index 28e2e23..84d9862 100644 --- a/source/ecs/system.d +++ b/source/ecs/system.d @@ -53,6 +53,8 @@ package: int m_priority; ///pointer to system implementation void* m_system_pointer; + ///system pass index + int m_pass; ///system name const (char)[] name; @@ -66,7 +68,7 @@ package: EntityManager.Job[] jobs; - System*[] m_dependencies; + //System*[] m_dependencies; ushort[] m_read_only_components; ushort[] m_modified_components; diff --git a/tests/tests.d b/tests/tests.d index ee27305..22753eb 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -175,7 +175,7 @@ int main() void initialize(ref Entity entity, ref TestComp comp) { - + int o = 1; } void update(EntitiesData data) @@ -284,6 +284,8 @@ import std.meta; gEM.setJobDispachFunc(&dispatch); assert(gEM !is null); + gEM.registerPass("fixed"); + MonoTime time = MonoTime.currTime; gEM.registerComponent!TestComp2; @@ -299,7 +301,7 @@ import std.meta; time = MonoTime.currTime; - gEM.registerSystem!TestSystemWithHighPriority(100); + gEM.registerSystem!TestSystemWithHighPriority(100,"fixed"); gEM.registerSystem!TestSystem(0); //gEM.registerSystem!TestSystemWithHighPriority(100); //gEM.registerSystem!TestSystem2(0); @@ -346,6 +348,7 @@ import std.meta; gEM.removeEntity(idss[j]); gEM.end(); } + gEM.commit(); dur = (MonoTime.currTime - time).total!"usecs"; writeln("Entities adding: ", dur, " usecs"); @@ -373,12 +376,18 @@ import std.meta; Entity entity2; + time = MonoTime.currTime; + foreach (i; 0 .. 500_000) { entity2 = gEM.addEntity(tmpl); gEM.addEntity(tmpl2); } + gEM.commit(); + dur = (MonoTime.currTime - time).total!"usecs"; + writeln("Entities adding2: ", dur, " usecs"); + time = MonoTime.currTime; gEM.begin(); @@ -441,6 +450,7 @@ import std.meta; gEM.begin(); gEM.update(); + gEM.update("fixed"); gEM.end(); writeEntityComponents(gEM.getEntity(entity.id));