ECS core imprevement

-Adedd function to resize array to Mallocator
-significant speed up for first time ID allocation by using resizeArray instead of makeArray
-fix: onUpdate called with zero length arrays
-call updateBlocks before updateEvents (it's more accurate behaviour)
-some minore fixes
-fixed meson.build for GDC
This commit is contained in:
Mergul 2020-06-06 22:26:59 +02:00
parent 66860b9042
commit 13e6ed8fd5
4 changed files with 83 additions and 36 deletions

View file

@ -52,8 +52,8 @@ endif
if betterC_opt if betterC_opt
if comp_id == 'gcc' if comp_id == 'gcc'
args += ['-flto','-fno-druntime'] args += ['-fno-druntime']
link_args += ['-flto','-fno-druntime'] link_args += ['-fno-druntime']
else else
args += '-betterC' args += '-betterC'
link_args += '-betterC' link_args += '-betterC'

View file

@ -177,15 +177,9 @@ struct IDManager
if (m_last_id > m_ids_array.length) if (m_last_id > m_ids_array.length)
{ {
uint begin = cast(uint) m_ids_array.length; uint begin = cast(uint) m_ids_array.length;
Data[] new_array = Mallocator.makeArray!Data(begin + (m_blocks_count << 16));
memcpy(new_array.ptr, m_ids_array.ptr, m_ids_array.length * Data.sizeof);
Mallocator.dispose(m_ids_array);
m_ids_array = new_array;
uint[] new_stack = Mallocator.makeArray!uint(m_ids_array.length); m_ids_array = Mallocator.resizeArray(m_ids_array, begin + (m_blocks_count << 16));
memcpy(new_stack.ptr, m_free_stack.ptr, m_free_stack.length * uint.sizeof); m_free_stack = Mallocator.resizeArray(m_free_stack, m_ids_array.length);
Mallocator.dispose(m_free_stack);
m_free_stack = new_stack;
foreach (block; m_blocks[0 .. m_blocks_count - 1]) foreach (block; m_blocks[0 .. m_blocks_count - 1])
{ {

View file

@ -456,7 +456,7 @@ export struct EntityManager
uint writable_dep = 1; uint writable_dep = 1;
} }
static ComponentsCounts getComponentsCounts()() static ComponentsCounts getComponentsCounts()
{ {
ComponentsCounts components_counts; ComponentsCounts components_counts;
@ -679,7 +679,7 @@ export struct EntityManager
} }
static ComponentsIndices!component_counts getComponentsInfo()() static ComponentsIndices!component_counts getComponentsInfo()
{ {
ComponentsIndices!component_counts components_info; ComponentsIndices!component_counts components_info;
@ -786,7 +786,7 @@ export struct EntityManager
enum ComponentsIndices!component_counts components_info = getComponentsInfo(); enum ComponentsIndices!component_counts components_info = getComponentsInfo();
static void genCompList()(ref System system, ref HashMap!(char[], ushort) components_map) static void genCompList(ref System system, ref HashMap!(char[], ushort) components_map)
{ {
foreach (member; __traits(allMembers, Sys.EntitiesData)) foreach (member; __traits(allMembers, Sys.EntitiesData))
@ -885,7 +885,7 @@ export struct EntityManager
} }
} }
static void fillInputData()(ref Sys.EntitiesData input_data, EntityInfo* info, static void fillInputData(ref Sys.EntitiesData input_data, EntityInfo* info,
EntitiesBlock* block, uint offset, uint entities_count, System* system) EntitiesBlock* block, uint offset, uint entities_count, System* system)
{ {
//enum ComponentsIndices components_info = getComponentsInfo(); //enum ComponentsIndices components_info = getComponentsInfo();
@ -907,7 +907,8 @@ export struct EntityManager
}//*/ }//*/
///FIXME: should be "components_info.req()" but it's not compile with GCC ///FIXME: should be "components_info.req()" but it's not compile with GCC
static foreach (iii, comp_info; components_info.m_req[0 .. components_info.m_req_counter]) static foreach (iii, comp_info; components_info.m_req[0
.. components_info.m_req_counter])
{ {
__traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember, __traits(getMember, input_data, comp_info.name) = (cast(ForeachType!(typeof(__traits(getMember,
Sys.EntitiesData, comp_info.name)))*)( Sys.EntitiesData, comp_info.name)))*)(
@ -915,7 +916,8 @@ export struct EntityManager
.. entities_count]; .. entities_count];
} }
static foreach (iii, comp_info; components_info.m_optional[0 .. components_info.m_optional_counter]) static foreach (iii, comp_info; components_info.m_optional[0
.. components_info.m_optional_counter])
{ {
if (system.m_optional_components[iii] < info.deltas.length if (system.m_optional_components[iii] < info.deltas.length
&& info.deltas[system.m_optional_components[iii]] != 0) && info.deltas[system.m_optional_components[iii]] != 0)
@ -929,7 +931,7 @@ export struct EntityManager
} }
} }
/*bool checkOnUpdateParams()() /*bool checkOnUpdateParams()
{ {
bool ret = false; bool ret = false;
foreach (func; __traits(getOverloads, Sys, "onUpdate")) foreach (func; __traits(getOverloads, Sys, "onUpdate"))
@ -1006,6 +1008,8 @@ export struct EntityManager
else else
entities_count = block.entities_count; entities_count = block.entities_count;
if (entities_count > 0)
{
assert(entities_count <= block.entities_count assert(entities_count <= block.entities_count
&& offset <= block.entities_count); && offset <= block.entities_count);
@ -1013,8 +1017,8 @@ export struct EntityManager
static if (hasMember!(Sys.EntitiesData, "thread_id")) static if (hasMember!(Sys.EntitiesData, "thread_id"))
{ {
input_data.thread_id = cast(typeof(input_data.thread_id)) data input_data.thread_id = cast(
.thread_id; typeof(input_data.thread_id)) data.thread_id;
} }
static if (hasMember!(Sys.EntitiesData, "job_id")) static if (hasMember!(Sys.EntitiesData, "job_id"))
@ -1024,8 +1028,9 @@ export struct EntityManager
//s.onUpdate(input_data); //s.onUpdate(input_data);
(cast(typeof(&__traits(getOverloads, s, (cast(typeof(&__traits(getOverloads, s,
"onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(input_data); "onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(
input_data);
}
block = block.next_block; block = block.next_block;
offset = 0; offset = 0;
blocks--; blocks--;
@ -1339,10 +1344,12 @@ export struct EntityManager
export void callEntitiesFunction(Sys, T)(T func) export void callEntitiesFunction(Sys, T)(T func)
{ {
//TODO: check if onUpdate function is good
Sys* s; Sys* s;
static assert(isDelegate!func, "Function must be delegate."); static assert(isDelegate!func, "Function must be delegate.");
static assert(__traits(hasMember, Sys, "EntitiesData"), static assert(__traits(hasMember, Sys, "EntitiesData"),
"Can't call function with system which hasn't EntitesData structure."); "Can't call function with system which hasn't EntitesData structure.");
///TODO: make possibly to call function to group without system with onUpdate function
static assert(__traits(hasMember, Sys, "onUpdate"), static assert(__traits(hasMember, Sys, "onUpdate"),
"Can't call function with system which hasn't onUpdate function callback."); "Can't call function with system which hasn't onUpdate function callback.");
// static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate), // static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate),
@ -1353,6 +1360,8 @@ export struct EntityManager
System* system = getSystem(Sys.system_id); System* system = getSystem(Sys.system_id);
assert(system != null, assert(system != null,
"System must be registered in EntityManager before any funcion can be called."); "System must be registered in EntityManager before any funcion can be called.");
if (!system.m_any_system_caller)
return;
foreach (info; system.m_any_system_caller.infos) foreach (info; system.m_any_system_caller.infos)
{ {
@ -3101,7 +3110,7 @@ export struct EntityManager
swapData(); swapData();
has_work = false; has_work = false;
// has_work |= updateBlocks(); has_work |= updateBlocks();
// has_work |= changeEntities(); // has_work |= changeEntities();
// has_work |= removeEntities(); // has_work |= removeEntities();
has_work |= updateEvents(); has_work |= updateEvents();

View file

@ -152,6 +152,50 @@ else
static struct Mallocator static struct Mallocator
{ {
static T[] resizeArray(T)(T[] array, size_t length) nothrow @nogc
{
T[] ret;
if(length > array.length)
{
ret = (cast(T*) realloc(array.ptr, T.sizeof * length))[0 .. length];
static if (__traits(isPOD, T))
{
__gshared immutable T init = T.init;
foreach (i; array.length .. ret.length)
{
memcpy(&ret[i], &init, T.sizeof);
}
}
else
{
static import std.conv;
foreach (i; array.length .. ret.length)
{
std.conv.emplace(&ret[i]);
}
}
}
else
{
static if (__traits(hasMember, T, "__xdtor"))
foreach (i; length .. array.length)
{
array[i].__xdtor();
}
else static if (__traits(hasMember, T, "__dtor"))
foreach (i; length .. array.length)
{
array[i].__dtor();
}
ret = (cast(T*) realloc(array.ptr, T.sizeof * length))[0 .. length];
}
return ret;
}
static T[] makeArray(T)(size_t length) nothrow @nogc static T[] makeArray(T)(size_t length) nothrow @nogc
{ {
T[] ret = (cast(T*) malloc(T.sizeof * length))[0 .. length]; T[] ret = (cast(T*) malloc(T.sizeof * length))[0 .. length];