From cb0f56b0fb88aa9e10cd1be3ff91bc2cafacc42d Mon Sep 17 00:00:00 2001 From: Mergul Date: Mon, 17 Sep 2018 14:46:30 +0200 Subject: [PATCH] -EntityAllocator fixed issue with not initialized block pointer -deffered adding entities -deffered adding and removeing components --- source/ecs/entity_allocator.d | 15 +- source/ecs/manager.d | 267 +++++++++++++++++++++++++--------- tests/tests.d | 9 +- 3 files changed, 214 insertions(+), 77 deletions(-) diff --git a/source/ecs/entity_allocator.d b/source/ecs/entity_allocator.d index a23ad7d..9c9b0ff 100644 --- a/source/ecs/entity_allocator.d +++ b/source/ecs/entity_allocator.d @@ -11,19 +11,24 @@ struct EntityAllocator void* getBlock() { - if(next_block is null)allocBlock(); + if (next_block is null) + allocBlock(); void* ret = next_block; - next_block = *cast(void**)next_block; + next_block = *cast(void**) next_block; return ret; } private void allocBlock() { - next_block = cast(void*)AlignedMallocator.instance.alignedAllocate(EntityManager.page_size * EntityManager.pages_in_block, EntityManager.page_size); - foreach(i;0..EntityManager.pages_in_block-1) + next_block = cast(void*) AlignedMallocator.instance.alignedAllocate( + EntityManager.page_size * EntityManager.pages_in_block, EntityManager.page_size); + foreach (i; 0 .. EntityManager.pages_in_block - 1) { void** pointer = cast(void**)(next_block + i * EntityManager.page_size); - *pointer = next_block + (i+1) * EntityManager.page_size; + *pointer = next_block + (i + 1) * EntityManager.page_size; } + void** pointer = cast(void**)( + next_block + (EntityManager.pages_in_block - 1) * EntityManager.page_size); + *pointer = null; } } diff --git a/source/ecs/manager.d b/source/ecs/manager.d index 5809dba..f302a81 100644 --- a/source/ecs/manager.d +++ b/source/ecs/manager.d @@ -30,14 +30,15 @@ class EntityManager static void destroy() { - foreach(ref system;instance.systems) + foreach (ref system; instance.systems) { system.disable(); } - foreach(ref system;instance.systems) + foreach (ref system; instance.systems) { - if(system.m_destroy)system.m_destroy(system.m_system_pointer); + if (system.m_destroy) + system.m_destroy(system.m_system_pointer); } Mallocator.instance.dispose(instance); @@ -64,16 +65,18 @@ class EntityManager uint i = 0; uint req = 0; uint opt = 0; - static foreach(param;(Parameters!(Sys.update))[1..$]) + static foreach (param; (Parameters!(Sys.update))[1 .. $]) { i++; - if(isPointer!param) + if (isPointer!param) { - ret ~= "cast(types[" ~ i.to!string ~ "])(optional_pointers[" ~ (opt++).to!string ~ "]),"; + ret ~= "cast(types[" ~ i.to!string ~ "])(optional_pointers[" ~ (opt++) + .to!string ~ "]),"; } else { - ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (req++).to!string ~ "]),"; + ret ~= "*cast(types[" ~ i.to!string ~ "]*)(pointers[" ~ (req++) + .to!string ~ "]),"; } } ret ~= ");"; @@ -86,10 +89,12 @@ class EntityManager foreach (i; 1 .. (Parameters!(Sys.update)).length) { ret ~= " - static if(isPointer!(types[" ~ i.to!string ~ "]))opt++; + static if(isPointer!(types[" ~ i.to!string + ~ "]))opt++; else static if(storages[" ~ i.to!string ~ "] == STC.ref_)req++;\n else static assert(0,\"Can't register system \\\"" ~ Sys.stringof - ~ "\\\". Unsupported parameter type \\\"\"~types[" ~ i.to!string ~ "].stringof~\"\\\".\");"; + ~ "\\\". Unsupported parameter type \\\"\"~types[" + ~ i.to!string ~ "].stringof~\"\\\".\");"; } ret ~= "system.m_components = Mallocator.instance.makeArray!ushort(req);"; ret ~= "system.m_optional_components = Mallocator.instance.makeArray!ushort(opt);"; @@ -97,18 +102,21 @@ class EntityManager foreach (i; 1 .. (Parameters!(Sys.update)).length) { ret ~= " - static if(isPointer!(types[" ~ i.to!string ~ "])) + static if(isPointer!(types[" ~ i.to!string + ~ "])) { comp = components_map.get(PointerTarget!(types[" ~ i.to!string ~ "]).stringof, ushort.max);\n if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof - ~ "\\\" due to non existing component \\\"\"~types[" ~ i.to!string ~ "].stringof~\"\\\".\"); + ~ "\\\" due to non existing component \\\"\"~types[" ~ i.to!string ~ "].stringof~\"\\\".\"); system.m_optional_components[opt++] = comp; } - else static if(storages[" ~ i.to!string ~ "] == STC.ref_) + else static if(storages[" + ~ i.to!string ~ "] == STC.ref_) { comp = components_map.get(types[" ~ i.to!string ~ "].stringof, ushort.max);\n - if(comp == ushort.max)assert(0,\"Can't register system \\\"" ~ Sys.stringof - ~ "\\\" due to non existing component \\\"\"~types[" ~ i.to!string ~ "].stringof~\"\\\".\"); + if(comp == ushort.max)assert(0,\"Can't register system \\\"" + ~ Sys.stringof ~ "\\\" due to non existing component \\\"\"~types[" + ~ i.to!string ~ "].stringof~\"\\\".\"); system.m_components[req++] = comp; }"; } @@ -117,17 +125,18 @@ class EntityManager static string catchFunc()(string member, string func) { - string ret = - "static if (hasMember!(Sys, \""~func~"\")) + string ret = "static if (hasMember!(Sys, \"" ~ func ~ "\")) { - static void call"~func~"(void* system_pointer) + static void call" ~ func + ~ "(void* system_pointer) { Sys* s = cast(Sys*) system_pointer; - s."~func~"(); + s." ~ func ~ "(); } - system."~member~" = &call"~func~"; + system." + ~ member ~ " = &call" ~ func ~ "; }"; return ret; } @@ -140,30 +149,38 @@ class EntityManager { Sys* s = cast(Sys*) data.system.m_system_pointer; - void*[] pointers = (cast(void**)alloca(data.system.m_components.length * (void*).sizeof))[0 .. data.system.m_components.length]; - void*[] optional_pointers = (cast(void**)alloca(data.system.m_optional_components.length * (void*).sizeof))[0 .. data.system.m_optional_components.length]; + void*[] pointers = (cast(void**) alloca(data.system.m_components.length * (void*) + .sizeof))[0 .. data.system.m_components.length]; + void*[] optional_pointers = (cast(void**) alloca( + data.system.m_optional_components.length * (void*).sizeof))[0 + .. data.system.m_optional_components.length]; EntitiesBlock* block = data.info.first_block; while (block !is null) { uint size = block.type_data.size; void* data_pointer = block.dataBegin(); - foreach(i, ref pointer;pointers) + foreach (i, ref pointer; pointers) { pointer = data_pointer + data.deltas[i]; } - foreach(i, ref pointer;optional_pointers) + foreach (i, ref pointer; optional_pointers) { uint ind = cast(uint)(i + pointers.length); - if(data.deltas[ind] != uint.max)pointer = data_pointer + data.deltas[ind]; - else pointer = null; + if (data.deltas[ind] != uint.max) + pointer = data_pointer + data.deltas[ind]; + else + pointer = null; } foreach (i; 0 .. block.entities_count) { mixin(genCall()); - data_pointer += size;//data.info.size; - foreach(ref pointer;pointers)pointer += size; - foreach(ref pointer;optional_pointers)if(pointer != null)pointer += size; + data_pointer += size; //data.info.size; + foreach (ref pointer; pointers) + pointer += size; + foreach (ref pointer; optional_pointers) + if (pointer != null) + pointer += size; } block = block.next_block; } @@ -174,12 +191,12 @@ class EntityManager system.m_update = &callUpdate; } - mixin(catchFunc("m_enable","onEnable")); - mixin(catchFunc("m_disable","onDisable")); - mixin(catchFunc("m_create","onCreate")); - mixin(catchFunc("m_destroy","onDestroy")); - mixin(catchFunc("m_begin","onBegin")); - mixin(catchFunc("m_end","onEnd")); + mixin(catchFunc("m_enable", "onEnable")); + mixin(catchFunc("m_disable", "onDisable")); + mixin(catchFunc("m_create", "onCreate")); + mixin(catchFunc("m_destroy", "onDestroy")); + mixin(catchFunc("m_begin", "onBegin")); + mixin(catchFunc("m_end", "onEnd")); system.m_system_pointer = cast(void*) Mallocator.instance.make!Sys; system.m_priority = priority; @@ -189,7 +206,8 @@ class EntityManager systems.add(system); - if(system.m_create)system.m_create(system.m_system_pointer); + if (system.m_create) + system.m_create(system.m_system_pointer); systems[$ - 1].enable(); @@ -219,6 +237,7 @@ class EntityManager { (cast(Comp*) pointer).onDestroy(); } + info.destroy_callback = &callDestroy; } @@ -355,8 +374,7 @@ class EntityManager uint delta_id = 0; ushort[] cmp_array = system.m_components; - add_deltas: - foreach (id; cmp_array) + add_deltas: foreach (id; cmp_array) { deltas[delta_id] = ushort.max; foreach (i2, id2; entity.components) @@ -374,14 +392,14 @@ class EntityManager } delta_id++; } - if(deltas is null)return; - if(cmp_array.ptr == system.m_components.ptr) + if (deltas is null) + return; + if (cmp_array.ptr == system.m_components.ptr) { cmp_array = system.m_optional_components; goto add_deltas; } - call_data.deltas = Mallocator.instance.makeArray(deltas); //Mallocator.instance.makeArray!ushort(system.m_components.length); uint index = 0; @@ -400,6 +418,15 @@ class EntityManager } void removeComponents(EntityID entity_id, ushort[] del_ids) + { + uint num = cast(uint) del_ids.length; + 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); + } + + void __removeComponents(EntityID entity_id, ushort[] del_ids) { Entity* entity = id_manager.getEntityPointer(entity_id); EntitiesBlock* block = getMetaData(entity); @@ -412,7 +439,7 @@ class EntityManager uint j = 0; uint k = 0; - foreach (id;info.components) + foreach (id; info.components) { while (k < del_ids.length && del_ids[k] < id) k++; @@ -459,54 +486,57 @@ class EntityManager del_ids[i] = comp.component_id; } - removeComponents(entity_id,del_ids); + /*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); } - void addComponents(Components...)(EntityID entity_id, Components comps) + void __addComponents(EntityID entity_id, ushort[] new_ids, void*[] data_pointers) { - const uint num = Components.length; + uint num = cast(uint) new_ids.length; Entity* entity = id_manager.getEntityPointer(entity_id); EntitiesBlock* block = getMetaData(entity); EntityInfo* info = block.type_data; ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0 .. info.components.length + num]; - ushort[num] new_ids; + /*ushort[num] new_ids; static foreach (i, comp; Components) { new_ids[i] = comp.component_id; - } + }*/ - void*[num] pointers; + /*void*[num] pointers; static foreach (i, comp; comps) { pointers[i] = ∁ - } + }*/ - foreach(int i;0..new_ids.length) + foreach (int i; 0 .. num) { ushort min = new_ids[i]; int pos = i; - foreach(int j;i..new_ids.length) + foreach (int j; i .. num) { - if(new_ids[j] < min) + if (new_ids[j] < min) { min = new_ids[j]; pos = j; } } - if(pos != i) + if (pos != i) { ushort id = new_ids[i]; new_ids[i] = new_ids[pos]; new_ids[pos] = id; - void* ptr = pointers[i]; - pointers[i] = pointers[pos]; - pointers[pos] = ptr; + void* ptr = data_pointers[i]; + data_pointers[i] = data_pointers[pos]; + data_pointers[pos] = ptr; } } - uint j = 0; uint k = 0; @@ -559,13 +589,13 @@ class EntityManager else if (j >= info.components.length) { memcpy(cast(void*) new_entity + new_info.deltas[id], - pointers[k], components[new_ids[k]].size); //id = new_ids[k++]; + data_pointers[k], components[new_ids[k]].size); //id = new_ids[k++]; k++; } else if (id == new_ids[k]) { memcpy(cast(void*) new_entity + new_info.deltas[id], - pointers[k], components[new_ids[k]].size); //id = new_ids[k++]; + data_pointers[k], components[new_ids[k]].size); //id = new_ids[k++]; k++; } else @@ -580,6 +610,40 @@ class EntityManager removeEntityNoID(entity, block); } + void addComponents(Components...)(EntityID entity_id, Components comps) + { + const uint num = Components.length; + Entity* entity = id_manager.getEntityPointer(entity_id); + EntitiesBlock* block = getMetaData(entity); + EntityInfo* info = block.type_data; + ushort[] ids = (cast(ushort*) alloca(ushort.sizeof * (info.components.length + num)))[0 + .. info.components.length + num]; + ushort[num] new_ids; + + static foreach (i, comp; Components) + { + new_ids[i] = comp.component_id; + } + + /*void*[num] pointers; + + static foreach (i, comp; comps) + { + pointers[i] = ∁ + }*/ + + change_entities_list.add(1); + 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[]) new_ids); + static foreach (i, comp; comps) + { + change_entities_list.add((cast(ubyte*)&comp)[0 .. comp.sizeof]); + } + + //__addComponents(entity_id, new_ids, pointers); + } + void freeTemplate(EntityTemplate* template_) { Mallocator.instance.dispose(template_.entity_data); @@ -590,13 +654,18 @@ class EntityManager { EntitiesBlock* block = findBlockWithFreeSpace(tmpl.info); - void* start = block.dataBegin() + block.entities_count * tmpl.info.size; + void* start = block.dataBegin() + (block.entities_count + block.added_count) + * tmpl.info.size; memcpy(start, tmpl.entity_data.ptr, tmpl.info.size); + if (!block.added_count) + blocks_to_update.add(block); + Entity* entity = cast(Entity*) start; entity.id = id_manager.getNewID(); entity.updateID(); - block.entities_count++; + block.added_count++; + //block.entities_count++; return *entity; } @@ -625,7 +694,8 @@ class EntityManager break; // new block certainly has free space } // check if there is enought space - if (block.dataDelta() + (block.entities_count + 1) * info.size > page_size) + if (block.dataDelta() + ( + block.entities_count + block.added_count + 1) * info.size > page_size) { previous_block = block; block = block.next_block; @@ -706,9 +776,57 @@ class EntityManager return cast(EntitiesBlock*)(cast(size_t) pointer & (~cast(size_t)(page_size - 1))); } - void removeEntites() + void changeEntites() { - foreach(id;entities_to_remove) + uint index = 0; + uint len = cast(uint) change_entities_list.length; + while (index < len) + { + if (!change_entities_list[index++]) + { + EntityID id = *cast(EntityID*)&change_entities_list[index]; + index += EntityID.sizeof; + uint num = *cast(uint*)&change_entities_list[index]; + index += uint.sizeof; + ushort[] ids = (cast(ushort*) alloca(num * ushort.sizeof))[0 .. num]; + ids[0 .. $] = (cast(ushort*)&change_entities_list[index])[0 .. num]; + index += ushort.sizeof * num; + __removeComponents(id, ids); + } + else + { + EntityID id = *cast(EntityID*)&change_entities_list[index]; + index += EntityID.sizeof; + uint num = *cast(uint*)&change_entities_list[index]; + index += uint.sizeof; + ushort[] ids = (cast(ushort*) alloca(num * ushort.sizeof))[0 .. num]; + ids[0 .. $] = (cast(ushort*)&change_entities_list[index])[0 .. num]; + index += ushort.sizeof * num; + void*[] pointers = (cast(void**) alloca(num * (void*).sizeof))[0 .. num]; + foreach (i; 0 .. num) + { + pointers[i] = &change_entities_list[index]; + index += components[ids[i]].size; + } + __addComponents(id, ids, pointers); + } + } + change_entities_list.clear(); + } + + void updateBlocks() + { + foreach (block; blocks_to_update) + { + block.entities_count += block.added_count; + block.added_count = 0; + } + blocks_to_update.clear(); + } + + void removeEntities() + { + foreach (id; entities_to_remove) { __removeEntity(id); } @@ -717,19 +835,26 @@ class EntityManager void begin() { - foreach(ref system;instance.systems) + updateBlocks(); + changeEntites(); + removeEntities(); + foreach (ref system; instance.systems) { - if(system.m_begin)system.m_begin(system.m_system_pointer); + if (system.m_begin) + system.m_begin(system.m_system_pointer); } } void end() { - foreach(ref system;instance.systems) + foreach (ref system; instance.systems) { - if(system.m_end)system.m_end(system.m_system_pointer); + if (system.m_end) + system.m_end(system.m_system_pointer); } - removeEntites(); + updateBlocks(); + changeEntites(); + removeEntities(); } struct ComponentInfo @@ -785,7 +910,9 @@ class EntityManager ///pointer to Entity type info EntityInfo* type_data; ///number of entities in block - uint entities_count; + ushort entities_count; + ///number of new entities in block + ushort added_count; ///block id uint id; ///pointer to next block/page @@ -819,6 +946,8 @@ class EntityManager EntityAllocator allocator; Vector!EntityID entities_to_remove; + Vector!(EntitiesBlock*) blocks_to_update; + Vector!ubyte change_entities_list; HashMap!(ushort[], EntityInfo*) entities_infos; HashMap!(string, ushort) components_map; diff --git a/tests/tests.d b/tests/tests.d index 739562c..c0f9b05 100644 --- a/tests/tests.d +++ b/tests/tests.d @@ -120,7 +120,8 @@ int main() test2.a = 8; //writeln("Jakis tekst! ",test2.b); //writeln("Low priority tekst! "); - if(test3)test3.gg = 200; + if (test3) + test3.gg = 200; } void handleEvent(Event event, ref TestComp comp) @@ -278,21 +279,23 @@ int main() gEM.addEntity(tmpl); gEM.addComponents(entity.id, TestComp3()); - pp = gEM.getEntity(entity.id); gEM.begin(); gEM.update(); gEM.end(); + pp = gEM.getEntity(entity.id); + writeln((cast(uint*) pp)[0 .. 14], " ", pp); gEM.removeComponents!(TestComp)(entity.id); - pp = gEM.getEntity(entity.id); gEM.begin(); gEM.update(); gEM.end(); + pp = gEM.getEntity(entity.id); + writeln((cast(uint*) pp)[0 .. 14], " ", pp); //import std.stdio;