diff --git a/develop/all.lua b/develop/all.lua index c1f6d56..b2cc3b6 100644 --- a/develop/all.lua +++ b/develop/all.lua @@ -3,12 +3,11 @@ require 'develop.samples.systems' require 'develop.testing.multi_spawn_tests' require 'develop.testing.name_tests' require 'develop.testing.requires_fragment_tests' -require 'develop.testing.scheme_tests' require 'develop.testing.system_as_query_tests' require 'develop.benchmarks.multi_clone_bmarks' require 'develop.benchmarks.multi_spawn_bmarks' -require 'develop.benchmarks.scheme_bmarks' +require 'develop.benchmarks.process_bmarks' require 'develop.untests' diff --git a/develop/benchmarks/process_bmarks.lua b/develop/benchmarks/process_bmarks.lua new file mode 100644 index 0000000..d85e2f6 --- /dev/null +++ b/develop/benchmarks/process_bmarks.lua @@ -0,0 +1,102 @@ +local evo = require 'evolved' +local basics = require 'develop.basics' + +evo.debug_mode(false) + +local N = 10000 + +print '----------------------------------------' + +basics.describe_bench(string.format('Scheme Benchmarks: Evolved AoS Processing | %d entities', N), + function(w) + evo.process(w) + end, + + function() + local wf = evo.builder() + :set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) + :spawn() + + local pf = evo.builder():set(wf):spawn() + local vf = evo.builder():set(wf):spawn() + + evo.multi_spawn(N, { + [wf] = true, + [pf] = { x = 0, y = 0, z = 0, w = 0 }, + [vf] = { x = 0, y = 0, z = 0, w = 0 }, + }) + + evo.builder() + :set(wf) + :set(evo.GROUP, wf) + :set(evo.QUERY, evo.builder():set(wf):include(pf, vf):spawn()) + :set(evo.EXECUTE, function(chunk, _, entity_count) + local ps, vs = chunk:components(pf, vf) + + for i = 1, entity_count do + local p, s = ps[i], vs[i] + p.x = p.x + s.x + p.y = p.y + s.y + end + end) + :spawn() + + return wf + end, + + function(w) + evo.destroy(w) + end) + +basics.describe_bench(string.format('Scheme Benchmarks: Evolved SoA Processing | %d entities', N), + function(w) + evo.process(w) + end, + + function() + local wf = evo.builder() + :set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) + :spawn() + + local pxf = evo.builder():set(wf):spawn() + local pyf = evo.builder():set(wf):spawn() + local pzf = evo.builder():set(wf):spawn() + local pwf = evo.builder():set(wf):spawn() + local vxf = evo.builder():set(wf):spawn() + local vyf = evo.builder():set(wf):spawn() + local vzf = evo.builder():set(wf):spawn() + local vwf = evo.builder():set(wf):spawn() + + evo.multi_spawn(N, { + [wf] = true, + [pxf] = 0, + [pyf] = 0, + [pzf] = 0, + [pwf] = 0, + [vxf] = 0, + [vyf] = 0, + [vzf] = 0, + [vwf] = 0, + }) + + evo.builder() + :set(wf) + :set(evo.GROUP, wf) + :set(evo.QUERY, evo.builder():set(wf):include(pxf, pyf, vxf, vyf):spawn()) + :set(evo.EXECUTE, function(chunk, _, entity_count) + local pxs, pys = chunk:components(pxf, pyf) + local vxs, vys = chunk:components(vxf, vyf) + + for i = 1, entity_count do + pxs[i] = pxs[i] + vxs[i] + pys[i] = pys[i] + vys[i] + end + end) + :spawn() + + return wf + end, + + function(w) + evo.destroy(w) + end) diff --git a/develop/benchmarks/scheme_bmarks.lua b/develop/benchmarks/scheme_bmarks.lua deleted file mode 100644 index aaada63..0000000 --- a/develop/benchmarks/scheme_bmarks.lua +++ /dev/null @@ -1,205 +0,0 @@ -local evo = require 'evolved' -local basics = require 'develop.basics' - -evo.debug_mode(false) - -local N = 10000 - -print '----------------------------------------' - -basics.describe_bench(string.format('Scheme Benchmarks: Evolved AoS Processing | %d entities', N), - function(w) - evo.process(w) - end, - - function() - local wf = evo.builder() - :set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local pf = evo.builder():set(wf):spawn() - local vf = evo.builder():set(wf):spawn() - - evo.multi_spawn(N, { - [wf] = true, - [pf] = { x = 0, y = 0, z = 0, w = 0 }, - [vf] = { x = 0, y = 0, z = 0, w = 0 }, - }) - - evo.builder() - :set(wf) - :set(evo.GROUP, wf) - :set(evo.QUERY, evo.builder():set(wf):include(pf, vf):spawn()) - :set(evo.EXECUTE, function(chunk, _, entity_count) - local ps, vs = chunk:components(pf, vf) - - for i = 1, entity_count do - local p, s = ps[i], vs[i] - p.x = p.x + s.x - p.y = p.y + s.y - end - end) - :spawn() - - return wf - end, - - function(w) - evo.destroy(w) - end) - -basics.describe_bench(string.format('Scheme Benchmarks: Evolved SoA Processing | %d entities', N), - function(w) - evo.process(w) - end, - - function() - local wf = evo.builder() - :set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local pxf = evo.builder():set(wf):spawn() - local pyf = evo.builder():set(wf):spawn() - local pzf = evo.builder():set(wf):spawn() - local pwf = evo.builder():set(wf):spawn() - local vxf = evo.builder():set(wf):spawn() - local vyf = evo.builder():set(wf):spawn() - local vzf = evo.builder():set(wf):spawn() - local vwf = evo.builder():set(wf):spawn() - - evo.multi_spawn(N, { - [wf] = true, - [pxf] = 0, - [pyf] = 0, - [pzf] = 0, - [pwf] = 0, - [vxf] = 0, - [vyf] = 0, - [vzf] = 0, - [vwf] = 0, - }) - - evo.builder() - :set(wf) - :set(evo.GROUP, wf) - :set(evo.QUERY, evo.builder():set(wf):include(pxf, pyf, vxf, vyf):spawn()) - :set(evo.EXECUTE, function(chunk, _, entity_count) - local pxs, pys = chunk:components(pxf, pyf) - local vxs, vys = chunk:components(vxf, vyf) - - for i = 1, entity_count do - pxs[i] = pxs[i] + vxs[i] - pys[i] = pys[i] + vys[i] - end - end) - :spawn() - - return wf - end, - - function(w) - evo.destroy(w) - end) - -print '----------------------------------------' - -basics.describe_bench(string.format('Scheme Benchmarks: Evolved-FFI AoS Processing | %d entities', N), - function(w) - evo.process(w) - end, - - function() - local wf = evo.builder() - :set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local vector4 = evo.scheme_record { - x = evo.scheme_number(), - y = evo.scheme_number(), - z = evo.scheme_number(), - w = evo.scheme_number(), - } - - local pf = evo.builder():set(wf):set(evo.SCHEME, vector4):spawn() - local vf = evo.builder():set(wf):set(evo.SCHEME, vector4):spawn() - - evo.multi_spawn(N, { - [wf] = true, - [pf] = { x = 0, y = 0, z = 0, w = 0 }, - [vf] = { x = 0, y = 0, z = 0, w = 0 }, - }) - - evo.builder() - :set(wf) - :set(evo.GROUP, wf) - :set(evo.QUERY, evo.builder():set(wf):include(pf, vf):spawn()) - :set(evo.EXECUTE, function(chunk, _, entity_count) - local ps, vs = chunk:components(pf, vf) - - for i = 1, entity_count do - local p, s = ps[i], vs[i] - p.x = p.x + s.x - p.y = p.y + s.y - end - end) - :spawn() - - return wf - end, - - function(w) - evo.destroy(w) - end) - -basics.describe_bench(string.format('Scheme Benchmarks: Evolved-FFI SoA Processing | %d entities', N), - function(w) - evo.process(w) - end, - - function() - local wf = evo.builder() - :set(evo.DESTRUCTION_POLICY, evo.DESTRUCTION_POLICY_DESTROY_ENTITY) - :spawn() - - local pxf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - local pyf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - local pzf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - local pwf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - local vxf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - local vyf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - local vzf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - local vwf = evo.builder():set(wf):set(evo.SCHEME, evo.scheme_number()):spawn() - - evo.multi_spawn(N, { - [wf] = true, - [pxf] = 0, - [pyf] = 0, - [pzf] = 0, - [pwf] = 0, - [vxf] = 0, - [vyf] = 0, - [vzf] = 0, - [vwf] = 0, - }) - - evo.builder() - :set(wf) - :set(evo.GROUP, wf) - :set(evo.QUERY, evo.builder():set(wf):include(pxf, pyf, vxf, vyf):spawn()) - :set(evo.EXECUTE, function(chunk, _, entity_count) - local pxs, pys = chunk:components(pxf, pyf) - local vxs, vys = chunk:components(vxf, vyf) - - for i = 1, entity_count do - pxs[i] = pxs[i] + vxs[i] - pys[i] = pys[i] + vys[i] - end - end) - :spawn() - - return wf - end, - - function(w) - evo.destroy(w) - end) diff --git a/develop/testing/scheme_tests.lua b/develop/testing/scheme_tests.lua deleted file mode 100644 index 8a88309..0000000 --- a/develop/testing/scheme_tests.lua +++ /dev/null @@ -1,173 +0,0 @@ -local evo = require 'evolved' - -do - local ns1 = evo.scheme_number() - local ns2 = evo.scheme_number() - - local f1 = evo.builder():scheme(ns1):spawn() - local f2 = evo.builder():scheme(ns2):spawn() - - local e1 = evo.builder():set(f1, 1):spawn() - local e2 = evo.builder():set(f1, 3):set(f2, 4):spawn() - - do - assert(evo.get(e1, f1) == 1 and evo.get(e1, f2) == nil) - assert(evo.get(e2, f1) == 3 and evo.get(e2, f2) == 4) - end - - evo.set(e1, f2, 2) - - do - assert(evo.get(e1, f1) == 1 and evo.get(e1, f2) == 2) - assert(evo.get(e2, f1) == 3 and evo.get(e2, f2) == 4) - end - - local es = evo.builder():set(f1, 5):set(f2, 6):multi_spawn(40) - for _, e in ipairs(es) do assert(evo.get(e, f1) == 5 and evo.get(e, f2) == 6) end -end - -do - local rs1 = evo.scheme_record { v = evo.scheme_number() } - local rs2 = evo.scheme_record { v1 = evo.scheme_number(), v2 = evo.scheme_number() } - local rs3 = evo.scheme_record { n1 = rs2, n2 = rs1 } - - local f1 = evo.builder():scheme(rs1):spawn() - local f2 = evo.builder():scheme(rs2):spawn() - local f3 = evo.builder():scheme(rs3):spawn() - - local e1 = evo.builder():set(f1, { v = 42 }):spawn() - local e2 = evo.builder():set(f2, { v1 = 21, v2 = 84 }):spawn() - local e3 = evo.builder():set(f3, { n1 = { v1 = 1, v2 = 2 }, n2 = { v = 3 } }):spawn() - - assert(evo.get(e1, f1).v == 42) - assert(evo.get(e2, f2).v1 == 21 and evo.get(e2, f2).v2 == 84) - assert(evo.get(e3, f3).n1.v1 == 1 and evo.get(e3, f3).n1.v2 == 2 and evo.get(e3, f3).n2.v == 3) -end - -do - local s = evo.scheme_number() - - local f1 = evo.builder():scheme(s):spawn() - local f2 = evo.builder():scheme(s):spawn() - local f3 = evo.builder():scheme(s):spawn() - - local b = evo.builder():set(f1, 42) - - local es = {} - for i = 1, 12 do es[i] = b:spawn() end - for _, e in ipairs(es) do assert(evo.get(e, f1) == 42) end - - for _, e in ipairs(es) do evo.set(e, f2, 84) end - for _, e in ipairs(es) do assert(evo.get(e, f1) == 42 and evo.get(e, f2) == 84) end - - for _, e in ipairs(es) do evo.remove(e, f1) end - for _, e in ipairs(es) do assert(evo.get(e, f1) == nil and evo.get(e, f2) == 84) end - - local q_f2 = evo.builder():include(f2):spawn() - - evo.batch_set(q_f2, f3, 21) - for _, e in ipairs(es) do assert(evo.get(e, f2) == 84 and evo.get(e, f3) == 21) end - - evo.batch_remove(q_f2, f2) - for _, e in ipairs(es) do assert(evo.get(e, f2) == nil and evo.get(e, f3) == 21) end -end - -do - local s = evo.scheme_number() - - local f1 = evo.builder():scheme(s):spawn() - local f2 = evo.builder():scheme(s):spawn() - local f3 = evo.builder():scheme(s):spawn() - - local b = evo.builder():set(f1, 42) - - local es = {} - for i = 1, 12 do es[i] = b:spawn() end - for _, e in ipairs(es) do assert(evo.get(e, f1) == 42) end - - for _, e in ipairs(es) do evo.set(e, f2, 84) end - for _, e in ipairs(es) do assert(evo.get(e, f1) == 42 and evo.get(e, f2) == 84) end - - for _, e in ipairs(es) do evo.remove(e, f1) end - for _, e in ipairs(es) do assert(evo.get(e, f1) == nil and evo.get(e, f2) == 84) end - - local q_f2 = evo.builder():include(f2):spawn() - - do - b:remove(f1):set(f2, 84):set(f3, 21) - for _ = 1, 12 do es[#es + 1] = b:spawn() end - end - - evo.batch_set(q_f2, f3, 21) - for _, e in ipairs(es) do assert(evo.get(e, f2) == 84 and evo.get(e, f3) == 21) end - - evo.batch_remove(q_f2, f2) - for _, e in ipairs(es) do assert(evo.get(e, f2) == nil and evo.get(e, f3) == 21) end -end - -do - local s = evo.scheme_number() - - local f1 = evo.builder():scheme(s):spawn() - local f2 = evo.builder():scheme(s):spawn() - local f3 = evo.builder():scheme(s):spawn() - - local b = evo.builder():set(f1, 42) - - local es = {} - for i = 1, 12 do es[i] = b:spawn() end - for _, e in ipairs(es) do assert(evo.get(e, f1) == 42) end - - for _, e in ipairs(es) do evo.set(e, f2, 84) end - for _, e in ipairs(es) do assert(evo.get(e, f1) == 42 and evo.get(e, f2) == 84) end - - for _, e in ipairs(es) do evo.remove(e, f1) end - for _, e in ipairs(es) do assert(evo.get(e, f1) == nil and evo.get(e, f2) == 84) end - - local q_f2 = evo.builder():include(f2):spawn() - local q_f3 = evo.builder():include(f3):spawn() - - do - b:remove(f1):set(f2, 84):set(f3, 21) - b:multi_spawn(24) - evo.batch_destroy(q_f3) - end - - evo.batch_set(q_f2, f3, 21) - for _, e in ipairs(es) do assert(evo.get(e, f2) == 84 and evo.get(e, f3) == 21) end - - evo.batch_remove(q_f2, f2) - for _, e in ipairs(es) do assert(evo.get(e, f2) == nil and evo.get(e, f3) == 21) end -end - -do - local s = evo.scheme_number() - - local f1 = evo.builder():scheme(s):spawn() - local f2 = evo.builder():scheme(s):spawn() - - local ec = evo.builder():set(f1, 21):set(f2, 42):multi_spawn(11) - for _, e in ipairs(ec) do assert(evo.get(e, f1) == 21 and evo.get(e, f2) == 42) end - - local q_f1 = evo.builder():include(f1):spawn() - - evo.batch_remove(q_f1, f1) - for _, e in ipairs(ec) do assert(evo.get(e, f1) == nil and evo.get(e, f2) == 42) end -end - -do - local ns1 = evo.scheme_number() - - local f = evo.builder():scheme(ns1):spawn() - - local e = evo.builder():set(f, 42):spawn() - assert(evo.get(e, f) == 42) - - local ns2 = evo.scheme_number() - evo.set(f, evo.SCHEME, ns2) - assert(evo.get(e, f) == 42) - - local ns3 = evo.scheme_boolean() - evo.set(f, evo.SCHEME, ns3) - assert(evo.get(e, f) == true) -end diff --git a/evolved.lua b/evolved.lua index b5010cb..c0481f8 100644 --- a/evolved.lua +++ b/evolved.lua @@ -151,14 +151,12 @@ local __group_subsystems = {} ---@type table ---@field package __fragment_list evolved.fragment[] ---@field package __fragment_count integer ---@field package __component_count integer ---@field package __component_indices table ----@field package __component_schemes evolved.scheme[] ---@field package __component_storages evolved.storage[] ---@field package __component_fragments evolved.fragment[] ---@field package __with_fragment_edges table @@ -181,15 +179,6 @@ local __group_subsystems = {} ---@type table local __builder_mt = {} @@ -346,35 +335,6 @@ end)() --- --- ----@class evolved.ffi ----@field cdef fun(def: string, ...) ----@field typeof fun(ct: evolved.ffi_ct, ...): evolved.ffi_ctype ----@field sizeof fun(ct: evolved.ffi_ct): integer? ----@field new fun(ct: evolved.ffi_ct, nelem?: integer, ...): evolved.ffi_cdata ----@field metatype fun(ct: evolved.ffi_ct, mt: table): evolved.ffi_ctype ----@field copy fun(dst: evolved.ffi_cdata, src: evolved.ffi_cdata, len: integer) - ----@class evolved.ffi_cdata : userdata ----@class evolved.ffi_ctype : userdata ----@class evolved.ffi_cdecl : string - ----@alias evolved.ffi_ct evolved.ffi_cdata | evolved.ffi_ctype | evolved.ffi_cdecl - ----@type evolved.ffi? -local __lua_ffi = (function() - -- https://luajit.org/ext_ffi_api.html - -- https://forum.defold.com/t/ffi-with-editor-2-solved/13683 - - local ffi_loader = package and package.preload and package.preload['ffi'] - return ffi_loader and ffi_loader() -end)() - ---- ---- ---- ---- ---- - ---@param fmt string ---@param ... any local function __error_fmt(fmt, ...) @@ -758,7 +718,6 @@ local __UNIQUE = __acquire_id() local __EXPLICIT = __acquire_id() local __INTERNAL = __acquire_id() -local __SCHEME = __acquire_id() local __DEFAULT = __acquire_id() local __DUPLICATE = __acquire_id() @@ -873,11 +832,6 @@ local __evolved_debug_mode local __evolved_collect_garbage local __evolved_chunk - -local __evolved_scheme_boolean -local __evolved_scheme_number -local __evolved_scheme_record - local __evolved_builder --- @@ -890,9 +844,6 @@ local __id_name local __new_chunk -local __component_storage -local __component_storage_move - local __update_chunk_caches local __update_chunk_storages @@ -932,9 +883,6 @@ local __clone_entity local __multi_clone_entity local __purge_chunk -local __shrink_chunk -local __expand_chunk - local __clear_chunk_list local __destroy_entity_list local __destroy_fragment_list @@ -1022,14 +970,12 @@ function __new_chunk(chunk_parent, chunk_fragment) __child_count = 0, __entity_list = {}, __entity_count = 0, - __entity_capacity = 4, __fragment = chunk_fragment, __fragment_set = chunk_fragment_set, __fragment_list = chunk_fragment_list, __fragment_count = chunk_fragment_count, __component_count = 0, __component_indices = {}, - __component_schemes = {}, __component_storages = {}, __component_fragments = {}, __with_fragment_edges = {}, @@ -1102,48 +1048,6 @@ function __new_chunk(chunk_parent, chunk_fragment) return chunk end ----@param scheme? evolved.scheme ----@param capacity integer ----@return evolved.storage ----@nodiscard -function __component_storage(scheme, capacity) - if not __lua_ffi or not scheme then - return __lua_table_new(capacity, 0) - end - - local vla = __lua_ffi.typeof('$[?]', scheme.__typeof) - - return __lua_ffi.new(vla, capacity + 1) -end - ----@param scheme evolved.scheme ----@param a1 evolved.storage ----@param f integer ----@param e integer ----@param t integer ----@param a2? evolved.storage ----@return evolved.storage -function __component_storage_move(scheme, a1, f, e, t, a2) - if not __lua_ffi or not scheme then - return __lua_table_move(a1, f, e, t, a2) - end - - if a2 == nil then - a2 = a1 - end - - if e < f then - return a2 - end - - local dst, src = a2 + t, a1 + f - local len = (e - f + 1) * scheme.__sizeof - - __lua_ffi.copy(dst, src, len) - - return a2 -end - ---@param chunk evolved.chunk function __update_chunk_caches(chunk) local chunk_parent = chunk.__parent @@ -1199,14 +1103,12 @@ end ---@param chunk evolved.chunk function __update_chunk_storages(chunk) local entity_count = chunk.__entity_count - local entity_capacity = chunk.__entity_capacity local fragment_list = chunk.__fragment_list local fragment_count = chunk.__fragment_count local component_count = chunk.__component_count local component_indices = chunk.__component_indices - local component_schemes = chunk.__component_schemes local component_storages = chunk.__component_storages local component_fragments = chunk.__component_fragments @@ -1214,38 +1116,32 @@ function __update_chunk_storages(chunk) local fragment = fragment_list[fragment_index] local component_index = component_indices[fragment] - local fragment_tag = __evolved_has(fragment, __TAG) - local fragment_scheme = __evolved_get(fragment, __SCHEME) + local is_fragment_tag = __evolved_has(fragment, __TAG) - if component_index and fragment_tag then + if component_index and is_fragment_tag then if component_index ~= component_count then - local last_component_scheme = component_schemes[component_count] local last_component_storage = component_storages[component_count] local last_component_fragment = component_fragments[component_count] component_indices[last_component_fragment] = component_index - component_schemes[component_index] = last_component_scheme component_storages[component_index] = last_component_storage component_fragments[component_index] = last_component_fragment end component_indices[fragment] = nil - component_schemes[fragment] = nil component_storages[component_count] = nil component_fragments[component_count] = nil component_count = component_count - 1 chunk.__component_count = component_count - elseif not component_index and not fragment_tag then + elseif not component_index and not is_fragment_tag then component_count = component_count + 1 chunk.__component_count = component_count - local component_scheme = __evolved_get(fragment, __SCHEME) - local component_storage = __component_storage(component_scheme, chunk.__entity_capacity) + local component_storage = __lua_table_new(entity_count, 0) local component_storage_index = component_count component_indices[fragment] = component_storage_index - component_schemes[component_storage_index] = component_scheme component_storages[component_storage_index] = component_storage component_fragments[component_storage_index] = fragment @@ -1254,7 +1150,7 @@ function __update_chunk_storages(chunk) __evolved_get(fragment, __DEFAULT, __DUPLICATE) if fragment_duplicate then - for place = 1, chunk.__entity_count do + for place = 1, entity_count do local new_component = fragment_default if new_component ~= nil then new_component = fragment_duplicate(new_component) end if new_component == nil then new_component = true end @@ -1263,20 +1159,10 @@ function __update_chunk_storages(chunk) else local new_component = fragment_default if new_component == nil then new_component = true end - for place = 1, chunk.__entity_count do + for place = 1, entity_count do component_storage[place] = new_component end end - elseif component_index and component_schemes[component_index] ~= fragment_scheme then - local old_component_storage = component_storages[component_index] - local new_component_storage = __component_storage(fragment_scheme, entity_capacity) - - for place = 1, entity_count do - new_component_storage[place] = old_component_storage[place] - end - - component_schemes[component_index] = fragment_scheme - component_storages[component_index] = new_component_storage end end end @@ -1876,37 +1762,29 @@ function __detach_entity(chunk, place) local entity_count = chunk.__entity_count local component_count = chunk.__component_count - local component_schemes = chunk.__component_schemes local component_storages = chunk.__component_storages if place == entity_count then - entity_list[place] = nil + entity_list[entity_count] = nil for component_index = 1, component_count do - local component_scheme = component_schemes[component_index] local component_storage = component_storages[component_index] - - if not component_scheme then - component_storage[place] = nil - end + component_storage[entity_count] = nil end else local last_entity = entity_list[entity_count] - __entity_places[last_entity % 2 ^ 20] = place + local last_entity_primary = last_entity % 2 ^ 20 + + __entity_places[last_entity_primary] = place entity_list[place] = last_entity entity_list[entity_count] = nil for component_index = 1, component_count do - local component_scheme = component_schemes[component_index] local component_storage = component_storages[component_index] - - local last_component = component_storage[entity_count] - component_storage[place] = last_component - - if not component_scheme then - component_storage[entity_count] = nil - end + local last_entity_component = component_storage[entity_count] + component_storage[place] = last_entity_component + component_storage[entity_count] = nil end end @@ -1918,18 +1796,13 @@ function __detach_all_entities(chunk) local entity_list = chunk.__entity_list local component_count = chunk.__component_count - local component_schemes = chunk.__component_schemes local component_storages = chunk.__component_storages __lua_table_clear(entity_list) for component_index = 1, component_count do - local component_scheme = component_schemes[component_index] local component_storage = component_storages[component_index] - - if not component_scheme then - __lua_table_clear(component_storage) - end + __lua_table_clear(component_storage) end chunk.__entity_count = 0 @@ -1973,17 +1846,12 @@ function __spawn_entity(entity, components) local chunk_entity_list = chunk.__entity_list local chunk_entity_count = chunk.__entity_count - local chunk_entity_capacity = chunk.__entity_capacity local chunk_component_indices = chunk.__component_indices local chunk_component_storages = chunk.__component_storages local place = chunk_entity_count + 1 - if place > chunk_entity_capacity then - __expand_chunk(chunk, place) - end - do chunk.__entity_count = place __structural_changes = __structural_changes + 1 @@ -2165,7 +2033,6 @@ function __multi_spawn_entity(entity_list, entity_count, components) local chunk_entity_list = chunk.__entity_list local chunk_entity_count = chunk.__entity_count - local chunk_entity_capacity = chunk.__entity_capacity local chunk_component_indices = chunk.__component_indices local chunk_component_storages = chunk.__component_storages @@ -2173,10 +2040,6 @@ function __multi_spawn_entity(entity_list, entity_count, components) local b_place = chunk_entity_count + 1 local e_place = chunk_entity_count + entity_count - if e_place > chunk_entity_capacity then - __expand_chunk(chunk, e_place) - end - do chunk.__entity_count = e_place __structural_changes = __structural_changes + 1 @@ -2397,17 +2260,12 @@ function __clone_entity(entity, prefab, components) local chunk_entity_list = chunk.__entity_list local chunk_entity_count = chunk.__entity_count - local chunk_entity_capacity = chunk.__entity_capacity local chunk_component_indices = chunk.__component_indices local chunk_component_storages = chunk.__component_storages local place = chunk_entity_count + 1 - if place > chunk_entity_capacity then - __expand_chunk(chunk, place) - end - do chunk.__entity_count = place __structural_changes = __structural_changes + 1 @@ -2653,7 +2511,6 @@ function __multi_clone_entity(entity_list, entity_count, prefab, components) local chunk_entity_list = chunk.__entity_list local chunk_entity_count = chunk.__entity_count - local chunk_entity_capacity = chunk.__entity_capacity local chunk_component_indices = chunk.__component_indices local chunk_component_storages = chunk.__component_storages @@ -2661,10 +2518,6 @@ function __multi_clone_entity(entity_list, entity_count, prefab, components) local b_place = chunk_entity_count + 1 local e_place = chunk_entity_count + entity_count - if e_place > chunk_entity_capacity then - __expand_chunk(chunk, e_place) - end - do chunk.__entity_count = e_place __structural_changes = __structural_changes + 1 @@ -2960,80 +2813,6 @@ function __purge_chunk(chunk) chunk.__unreachable_or_collected = true end ----@param chunk evolved.chunk ----@param min_capacity integer -function __shrink_chunk(chunk, min_capacity) - if __defer_depth <= 0 then - __error_fmt('this operation should be deferred') - end - - local entity_count = chunk.__entity_count - min_capacity = math.max(min_capacity, entity_count) - - local old_capacity = chunk.__entity_capacity - if old_capacity <= min_capacity then - -- no need to shrink, we are already small enough - return - end - - local new_capacity = math.max(min_capacity, 4) - - local component_schemes = chunk.__component_schemes - local component_storages = chunk.__component_storages - - for component_index = 1, chunk.__component_count do - local component_scheme = component_schemes[component_index] - - local old_component_storage = component_storages[component_index] - local new_component_storage = __component_storage(component_scheme, new_capacity) - - __component_storage_move(component_scheme, - old_component_storage, 1, entity_count, - 1, new_component_storage) - - component_storages[component_index] = new_component_storage - end - - chunk.__entity_capacity = new_capacity -end - ----@param chunk evolved.chunk ----@param min_capacity integer -function __expand_chunk(chunk, min_capacity) - if __defer_depth <= 0 then - __error_fmt('this operation should be deferred') - end - - local entity_count = chunk.__entity_count - min_capacity = math.max(min_capacity, entity_count) - - local old_capacity = chunk.__entity_capacity - if old_capacity >= min_capacity then - -- no need to expand, we are already large enough - return - end - - local new_capacity = math.max(min_capacity, old_capacity * 2) - - local component_schemes = chunk.__component_schemes - local component_storages = chunk.__component_storages - - for component_index = 1, chunk.__component_count do - local component_scheme = component_schemes[component_index] - - local old_component_storage = component_storages[component_index] - local new_component_storage = __component_storage(component_scheme, new_capacity) - - __component_storage_move(component_scheme, - old_component_storage, 1, entity_count, - 1, new_component_storage) - - component_storages[component_index] = new_component_storage - end - - chunk.__entity_capacity = new_capacity -end - ---@param chunk_list evolved.chunk[] ---@param chunk_count integer function __clear_chunk_list(chunk_list, chunk_count) @@ -3233,7 +3012,6 @@ function __chunk_set(old_chunk, fragment, component) local old_component_count = old_chunk.__component_count local old_component_indices = old_chunk.__component_indices - local old_component_schemes = old_chunk.__component_schemes local old_component_storages = old_chunk.__component_storages local old_component_fragments = old_chunk.__component_fragments @@ -3370,10 +3148,8 @@ function __chunk_set(old_chunk, fragment, component) local new_entity_list = new_chunk.__entity_list local new_entity_count = new_chunk.__entity_count - local new_entity_capacity = new_chunk.__entity_capacity local new_component_indices = new_chunk.__component_indices - local new_component_schemes = new_chunk.__component_schemes local new_component_storages = new_chunk.__component_storages local new_chunk_has_setup_hooks = new_chunk.__has_setup_hooks @@ -3389,25 +3165,31 @@ function __chunk_set(old_chunk, fragment, component) local sum_entity_count = old_entity_count + new_entity_count - if sum_entity_count > new_entity_capacity then - __expand_chunk(new_chunk, sum_entity_count) - end + if new_entity_count == 0 then + old_chunk.__entity_list, new_chunk.__entity_list = + new_entity_list, old_entity_list + + old_entity_list, new_entity_list = + new_entity_list, old_entity_list - do for old_ci = 1, old_component_count do local old_f = old_component_fragments[old_ci] - local old_fs = old_component_schemes[old_ci] + local new_ci = new_component_indices[old_f] + + old_component_storages[old_ci], new_component_storages[new_ci] = + new_component_storages[new_ci], old_component_storages[old_ci] + end + + new_chunk.__entity_count = sum_entity_count + else + for old_ci = 1, old_component_count do + local old_f = old_component_fragments[old_ci] local old_cs = old_component_storages[old_ci] local new_ci = new_component_indices[old_f] - local new_fs = new_component_schemes[new_ci] local new_cs = new_component_storages[new_ci] - if old_fs ~= new_fs then - __error_fmt('internal error: fragment scheme mismatch') - end - - __component_storage_move(new_fs, + __lua_table_move( old_cs, 1, old_entity_count, new_entity_count + 1, new_cs) end @@ -3644,7 +3426,6 @@ function __chunk_remove(old_chunk, ...) local old_fragment_list = old_chunk.__fragment_list local old_fragment_count = old_chunk.__fragment_count local old_component_indices = old_chunk.__component_indices - local old_component_schemes = old_chunk.__component_schemes local old_component_storages = old_chunk.__component_storages if old_entity_count == 0 then @@ -3693,34 +3474,38 @@ function __chunk_remove(old_chunk, ...) if new_chunk then local new_entity_list = new_chunk.__entity_list local new_entity_count = new_chunk.__entity_count - local new_entity_capacity = new_chunk.__entity_capacity local new_component_count = new_chunk.__component_count - local new_component_schemes = new_chunk.__component_schemes local new_component_storages = new_chunk.__component_storages local new_component_fragments = new_chunk.__component_fragments local sum_entity_count = old_entity_count + new_entity_count - do - if sum_entity_count > new_entity_capacity then - __expand_chunk(new_chunk, sum_entity_count) - end + if new_entity_count == 0 then + old_chunk.__entity_list, new_chunk.__entity_list = + new_entity_list, old_entity_list + + old_entity_list, new_entity_list = + new_entity_list, old_entity_list for new_ci = 1, new_component_count do local new_f = new_component_fragments[new_ci] - local new_fs = new_component_schemes[new_ci] + local old_ci = old_component_indices[new_f] + + old_component_storages[old_ci], new_component_storages[new_ci] = + new_component_storages[new_ci], old_component_storages[old_ci] + end + + new_chunk.__entity_count = sum_entity_count + else + for new_ci = 1, new_component_count do + local new_f = new_component_fragments[new_ci] local new_cs = new_component_storages[new_ci] local old_ci = old_component_indices[new_f] - local old_fs = old_component_schemes[old_ci] local old_cs = old_component_storages[old_ci] - if new_fs ~= old_fs then - __error_fmt('internal error: fragment scheme mismatch') - end - - __component_storage_move(new_fs, + __lua_table_move( old_cs, 1, old_entity_count, new_entity_count + 1, new_cs) end @@ -5316,10 +5101,8 @@ function __evolved_set(entity, fragment, component) local new_entity_list = new_chunk.__entity_list local new_entity_count = new_chunk.__entity_count - local new_entity_capacity = new_chunk.__entity_capacity local new_component_indices = new_chunk.__component_indices - local new_component_schemes = new_chunk.__component_schemes local new_component_storages = new_chunk.__component_storages local new_chunk_has_setup_hooks = new_chunk.__has_setup_hooks @@ -5334,30 +5117,22 @@ function __evolved_set(entity, fragment, component) end local new_place = new_entity_count + 1 + new_chunk.__entity_count = new_place - if new_place > new_entity_capacity then - __expand_chunk(new_chunk, new_place) - end + new_entity_list[new_place] = entity if old_chunk then local old_component_count = old_chunk.__component_count - local old_component_schemes = old_chunk.__component_schemes local old_component_storages = old_chunk.__component_storages local old_component_fragments = old_chunk.__component_fragments for old_ci = 1, old_component_count do local old_f = old_component_fragments[old_ci] - local old_fs = old_component_schemes[old_ci] local old_cs = old_component_storages[old_ci] local new_ci = new_component_indices[old_f] - local new_fs = new_component_schemes[new_ci] local new_cs = new_component_storages[new_ci] - if old_fs ~= new_fs then - __error_fmt('internal error: fragment scheme mismatch') - end - new_cs[new_place] = old_cs[old_place] end @@ -5365,9 +5140,6 @@ function __evolved_set(entity, fragment, component) end do - new_entity_list[new_place] = entity - new_chunk.__entity_count = new_place - entity_chunks[entity_primary] = new_chunk entity_places[entity_primary] = new_place @@ -5506,7 +5278,6 @@ function __evolved_remove(entity, ...) local old_fragment_list = old_chunk.__fragment_list local old_fragment_count = old_chunk.__fragment_count local old_component_indices = old_chunk.__component_indices - local old_component_schemes = old_chunk.__component_schemes local old_component_storages = old_chunk.__component_storages if old_chunk.__has_remove_hooks then @@ -5538,37 +5309,25 @@ function __evolved_remove(entity, ...) if new_chunk then local new_entity_list = new_chunk.__entity_list local new_entity_count = new_chunk.__entity_count - local new_entity_capacity = new_chunk.__entity_capacity local new_component_count = new_chunk.__component_count - local new_component_schemes = new_chunk.__component_schemes local new_component_storages = new_chunk.__component_storages local new_component_fragments = new_chunk.__component_fragments local new_place = new_entity_count + 1 + new_chunk.__entity_count = new_place - if new_place > new_entity_capacity then - __expand_chunk(new_chunk, new_place) - end + new_entity_list[new_place] = entity for new_ci = 1, new_component_count do local new_f = new_component_fragments[new_ci] - local new_fs = new_component_schemes[new_ci] local new_cs = new_component_storages[new_ci] local old_ci = old_component_indices[new_f] - local old_fs = old_component_schemes[old_ci] local old_cs = old_component_storages[old_ci] - if old_fs ~= new_fs then - __error_fmt('internal error: fragment scheme mismatch') - end - new_cs[new_place] = old_cs[old_place] end - - new_entity_list[new_place] = entity - new_chunk.__entity_count = new_place end do @@ -6162,8 +5921,6 @@ function __evolved_collect_garbage() if is_not_pinned and should_be_purged then __purge_chunk(postorder_chunk) - else - __shrink_chunk(postorder_chunk, 4) end end @@ -6315,92 +6072,6 @@ end --- --- ----@return evolved.scheme scheme ----@nodiscard -function __evolved_scheme_boolean() - return __lua_setmetatable({ - __id = __acquire_id(), - __name = 'bool', - __cdecl = 'bool', - __sizeof = __lua_ffi and __lua_ffi.sizeof('bool'), - __typeof = __lua_ffi and __lua_ffi.typeof('bool'), - }, __scheme_mt) -end - ----@return evolved.scheme scheme ----@nodiscard -function __evolved_scheme_number() - return __lua_setmetatable({ - __id = __acquire_id(), - __name = 'double', - __cdecl = 'double', - __sizeof = __lua_ffi and __lua_ffi.sizeof('double'), - __typeof = __lua_ffi and __lua_ffi.typeof('double'), - }, __scheme_mt) -end - ----@param field_schemes table ----@return evolved.scheme scheme ----@nodiscard -function __evolved_scheme_record(field_schemes) - local record_id = __acquire_id() - local record_name = __lua_string_format('__evolved_record_%d', record_id) - - local field_list = {} ---@type {name: string, scheme: evolved.scheme}[] - local field_count = 0 ---@type integer - - for field_name, field_scheme in __lua_next, field_schemes do - field_count = field_count + 1 - field_list[field_count] = { name = field_name, scheme = field_scheme } - end - - if __lua_ffi and field_count > 0 then - __lua_table_sort(field_list, function(a, b) - local a_name, b_name = a.scheme.__name, b.scheme.__name - local a_size, b_size = a.scheme.__sizeof or 0, b.scheme.__sizeof or 0 - return a_size > b_size or (a_size == b_size and a_name < b_name) - end) - end - - local field_cdecl_list = '' - - for field_index = 1, field_count do - local field = field_list[field_index] - - if field_cdecl_list ~= '' then - field_cdecl_list = field_cdecl_list .. ' ' - end - - field_cdecl_list = field_cdecl_list .. - __lua_string_format('%s %s;', field.scheme.__name, field.name) - end - - local record_cdecl = __lua_string_format( - 'typedef struct { %s } %s;', field_cdecl_list, record_name) - - if __lua_ffi then - __lua_ffi.cdef(record_cdecl) - end - - return __lua_setmetatable({ - __id = record_id, - __name = record_name, - __cdecl = record_cdecl, - __sizeof = __lua_ffi and __lua_ffi.sizeof(record_name), - __typeof = __lua_ffi and __lua_ffi.typeof(record_name), - }, __scheme_mt) -end - -function __scheme_mt:__tostring() - return self.__cdecl -end - ---- ---- ---- ---- ---- - ---@return evolved.builder builder ---@nodiscard function __evolved_builder() @@ -6684,12 +6355,6 @@ function __builder_mt:internal() return self:set(__INTERNAL) end ----@param scheme evolved.scheme ----@return evolved.builder builder -function __builder_mt:scheme(scheme) - return self:set(__SCHEME, scheme) -end - ---@param default evolved.component ---@return evolved.builder builder function __builder_mt:default(default) @@ -6853,16 +6518,16 @@ end --- --- -__evolved_set(__ON_SET, __ON_SET, __update_major_chunks) +__evolved_set(__ON_SET, __ON_INSERT, __update_major_chunks) __evolved_set(__ON_SET, __ON_REMOVE, __update_major_chunks) -__evolved_set(__ON_ASSIGN, __ON_SET, __update_major_chunks) +__evolved_set(__ON_ASSIGN, __ON_INSERT, __update_major_chunks) __evolved_set(__ON_ASSIGN, __ON_REMOVE, __update_major_chunks) -__evolved_set(__ON_INSERT, __ON_SET, __update_major_chunks) +__evolved_set(__ON_INSERT, __ON_INSERT, __update_major_chunks) __evolved_set(__ON_INSERT, __ON_REMOVE, __update_major_chunks) -__evolved_set(__ON_REMOVE, __ON_SET, __update_major_chunks) +__evolved_set(__ON_REMOVE, __ON_INSERT, __update_major_chunks) __evolved_set(__ON_REMOVE, __ON_REMOVE, __update_major_chunks) --- @@ -6871,28 +6536,25 @@ __evolved_set(__ON_REMOVE, __ON_REMOVE, __update_major_chunks) --- --- -__evolved_set(__TAG, __ON_SET, __update_major_chunks) +__evolved_set(__TAG, __ON_INSERT, __update_major_chunks) __evolved_set(__TAG, __ON_REMOVE, __update_major_chunks) -__evolved_set(__UNIQUE, __ON_SET, __update_major_chunks) +__evolved_set(__UNIQUE, __ON_INSERT, __update_major_chunks) __evolved_set(__UNIQUE, __ON_REMOVE, __update_major_chunks) -__evolved_set(__EXPLICIT, __ON_SET, __update_major_chunks) +__evolved_set(__EXPLICIT, __ON_INSERT, __update_major_chunks) __evolved_set(__EXPLICIT, __ON_REMOVE, __update_major_chunks) -__evolved_set(__INTERNAL, __ON_SET, __update_major_chunks) +__evolved_set(__INTERNAL, __ON_INSERT, __update_major_chunks) __evolved_set(__INTERNAL, __ON_REMOVE, __update_major_chunks) -__evolved_set(__SCHEME, __ON_SET, __update_major_chunks) -__evolved_set(__SCHEME, __ON_REMOVE, __update_major_chunks) - -__evolved_set(__DEFAULT, __ON_SET, __update_major_chunks) +__evolved_set(__DEFAULT, __ON_INSERT, __update_major_chunks) __evolved_set(__DEFAULT, __ON_REMOVE, __update_major_chunks) -__evolved_set(__DUPLICATE, __ON_SET, __update_major_chunks) +__evolved_set(__DUPLICATE, __ON_INSERT, __update_major_chunks) __evolved_set(__DUPLICATE, __ON_REMOVE, __update_major_chunks) -__evolved_set(__REQUIRES, __ON_SET, __update_major_chunks) +__evolved_set(__REQUIRES, __ON_INSERT, __update_major_chunks) __evolved_set(__REQUIRES, __ON_REMOVE, __update_major_chunks) --- @@ -6908,7 +6570,6 @@ __evolved_set(__UNIQUE, __NAME, 'UNIQUE') __evolved_set(__EXPLICIT, __NAME, 'EXPLICIT') __evolved_set(__INTERNAL, __NAME, 'INTERNAL') -__evolved_set(__SCHEME, __NAME, 'SCHEME') __evolved_set(__DEFAULT, __NAME, 'DEFAULT') __evolved_set(__DUPLICATE, __NAME, 'DUPLICATE') @@ -6949,7 +6610,6 @@ __evolved_set(__UNIQUE, __INTERNAL) __evolved_set(__EXPLICIT, __INTERNAL) __evolved_set(__INTERNAL, __INTERNAL) -__evolved_set(__SCHEME, __INTERNAL) __evolved_set(__DEFAULT, __INTERNAL) __evolved_set(__DUPLICATE, __INTERNAL) @@ -7158,7 +6818,6 @@ evolved.UNIQUE = __UNIQUE evolved.EXPLICIT = __EXPLICIT evolved.INTERNAL = __INTERNAL -evolved.SCHEME = __SCHEME evolved.DEFAULT = __DEFAULT evolved.DUPLICATE = __DUPLICATE @@ -7240,11 +6899,6 @@ evolved.debug_mode = __evolved_debug_mode evolved.collect_garbage = __evolved_collect_garbage evolved.chunk = __evolved_chunk - -evolved.scheme_boolean = __evolved_scheme_boolean -evolved.scheme_number = __evolved_scheme_number -evolved.scheme_record = __evolved_scheme_record - evolved.builder = __evolved_builder ---