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 comp_id == 'gcc'
args += ['-flto','-fno-druntime']
link_args += ['-flto','-fno-druntime']
args += ['-fno-druntime']
link_args += ['-fno-druntime']
else
args += '-betterC'
link_args += '-betterC'

View file

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

View file

@ -456,7 +456,7 @@ export struct EntityManager
uint writable_dep = 1;
}
static ComponentsCounts getComponentsCounts()()
static ComponentsCounts getComponentsCounts()
{
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;
@ -786,7 +786,7 @@ export struct EntityManager
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))
@ -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)
{
//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
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,
Sys.EntitiesData, comp_info.name)))*)(
@ -915,7 +916,8 @@ export struct EntityManager
.. 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
&& info.deltas[system.m_optional_components[iii]] != 0)
@ -929,7 +931,7 @@ export struct EntityManager
}
}
/*bool checkOnUpdateParams()()
/*bool checkOnUpdateParams()
{
bool ret = false;
foreach (func; __traits(getOverloads, Sys, "onUpdate"))
@ -1006,26 +1008,29 @@ export struct EntityManager
else
entities_count = block.entities_count;
assert(entities_count <= block.entities_count
&& offset <= block.entities_count);
fillInputData(input_data, info, block, offset, entities_count, system);
static if (hasMember!(Sys.EntitiesData, "thread_id"))
if (entities_count > 0)
{
input_data.thread_id = cast(typeof(input_data.thread_id)) data
.thread_id;
assert(entities_count <= block.entities_count
&& offset <= block.entities_count);
fillInputData(input_data, info, block, offset, entities_count, system);
static if (hasMember!(Sys.EntitiesData, "thread_id"))
{
input_data.thread_id = cast(
typeof(input_data.thread_id)) data.thread_id;
}
static if (hasMember!(Sys.EntitiesData, "job_id"))
{
input_data.job_id = cast(typeof(input_data.job_id)) data.job_id;
}
//s.onUpdate(input_data);
(cast(typeof(&__traits(getOverloads, s,
"onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(
input_data);
}
static if (hasMember!(Sys.EntitiesData, "job_id"))
{
input_data.job_id = cast(typeof(input_data.job_id)) data.job_id;
}
//s.onUpdate(input_data);
(cast(typeof(&__traits(getOverloads, s,
"onUpdate")[OnUpdateOverloadNum])) data.update_delegate)(input_data);
block = block.next_block;
offset = 0;
blocks--;
@ -1339,10 +1344,12 @@ export struct EntityManager
export void callEntitiesFunction(Sys, T)(T func)
{
//TODO: check if onUpdate function is good
Sys* s;
static assert(isDelegate!func, "Function must be delegate.");
static assert(__traits(hasMember, Sys, "EntitiesData"),
"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"),
"Can't call function with system which hasn't onUpdate function callback.");
// static assert(is(SetFunctionAttributes!(T, functionLinkage!(s.onUpdate),
@ -1353,6 +1360,8 @@ export struct EntityManager
System* system = getSystem(Sys.system_id);
assert(system != null,
"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)
{
@ -3101,7 +3110,7 @@ export struct EntityManager
swapData();
has_work = false;
// has_work |= updateBlocks();
has_work |= updateBlocks();
// has_work |= changeEntities();
// has_work |= removeEntities();
has_work |= updateEvents();

View file

@ -152,6 +152,50 @@ else
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
{
T[] ret = (cast(T*) malloc(T.sizeof * length))[0 .. length];