Specialize iterator

This commit is contained in:
Ukendio 2024-07-31 18:48:34 +02:00
parent c486e85d43
commit 7476952f89
2 changed files with 212 additions and 121 deletions

View file

@ -739,7 +739,6 @@ do
local lastArchetype: number
local archetype: Archetype
local queryOutput: { any }
local queryLength: number
local entities: { number }
local i: number
@ -747,7 +746,7 @@ do
local ids: { number }
local columns
local A, B, C, D, E, F, G, H
local A, B, C, D, E, F, G, H, I
local a, b, c, d, e, f, g, h
local init
@ -820,7 +819,11 @@ do
end
end
local function world_query_iter_next(): any
local world_query_iter_next
local function world_query_iter_create()
if not B then
function world_query_iter_next(): any
local entityId = entities[i]
while entityId == nil do
lastArchetype += 1
@ -837,21 +840,119 @@ do
entityId = entities[i]
columns = archetype.columns
local records = archetype.records
if not B then
a = columns[records[A]]
end
local row = i
i-=1
return entityId, a[row]
end
elseif not C then
function world_query_iter_next(): any
local entityId = entities[i]
while entityId == nil do
lastArchetype += 1
archetype = compatible_archetypes[lastArchetype]
if not archetype then
return nil
end
entities = archetype.entities
i = #entities
if i == 0 then
continue
end
entityId = entities[i]
columns = archetype.columns
local records = archetype.records
a = columns[records[A]]
b = columns[records[B]]
end
local row = i
i-=1
return entityId, a[row], b[row]
end
elseif not D then
function world_query_iter_next(): any
local entityId = entities[i]
while entityId == nil do
lastArchetype += 1
archetype = compatible_archetypes[lastArchetype]
if not archetype then
return nil
end
entities = archetype.entities
i = #entities
if i == 0 then
continue
end
entityId = entities[i]
columns = archetype.columns
local records = archetype.records
a = columns[records[A]]
b = columns[records[B]]
c = columns[records[C]]
end
local row = i
i-=1
return entityId, a[row], b[row], c[row]
end
elseif not E then
function world_query_iter_next(): any
local entityId = entities[i]
while entityId == nil do
lastArchetype += 1
archetype = compatible_archetypes[lastArchetype]
if not archetype then
return nil
end
entities = archetype.entities
i = #entities
if i == 0 then
continue
end
entityId = entities[i]
columns = archetype.columns
local records = archetype.records
a = columns[records[A]]
b = columns[records[B]]
c = columns[records[C]]
d = columns[records[D]]
elseif not F then
end
local row = i
i-=1
return entityId, a[row], b[row], c[row], d[row]
end
else
function world_query_iter_next(): any
local entityId = entities[i]
while entityId == nil do
lastArchetype += 1
archetype = compatible_archetypes[lastArchetype]
if not archetype then
return nil
end
entities = archetype.entities
i = #entities
if i == 0 then
continue
end
entityId = entities[i]
columns = archetype.columns
local records = archetype.records
if not F then
a = columns[records[A]]
b = columns[records[B]]
c = columns[records[C]]
@ -886,48 +987,14 @@ do
local row = i
i-=1
if queryLength == 1 then
return entityId, a[row]
elseif queryLength == 2 then
return entityId, a[row], b[row]
elseif queryLength == 3 then
return entityId, a[row], b[row], c[row]
elseif queryLength == 4 then
return entityId, a[row], b[row], c[row], d[row]
elseif queryLength == 5 then
return entityId,
a[row],
b[row],
c[row],
d[row],
e[row]
elseif queryLength == 6 then
return entityId,
a[row],
b[row],
c[row],
d[row],
e[row],
f[row]
elseif queryLength == 7 then
return entityId,
a[row],
b[row],
c[row],
d[row],
e[row],
f[row],
g[row]
elseif queryLength == 8 then
return entityId,
a[row],
b[row],
c[row],
d[row],
e[row],
f[row],
g[row],
h[row]
if not F then
return entityId, a[row], b[row], c[row], d[row], e[row]
elseif not G then
return entityId, a[row], b[row], c[row], d[row], e[row], f[row]
elseif not H then
return entityId, a[row], b[row], c[row], d[row], e[row], f[row], g[row]
elseif not I then
return entityId, a[row], b[row], c[row], d[row], e[row], f[row], g[row], h[row]
end
local field = archetype.records
@ -935,7 +1002,9 @@ do
queryOutput[j] = columns[field[id]][row]
end
return entityId, unpack(queryOutput, 1, queryLength)
return entityId, unpack(queryOutput)
end
end
end
local function world_query_without(self, ...)
@ -977,23 +1046,23 @@ do
local columns = archetype.columns
local tr = archetype.records
for row in archetype.entities do
if queryLength == 1 then
if not B then
local va = columns[tr[A]]
local pa = fn(va[row])
va[row] = pa
elseif queryLength == 2 then
elseif not C then
local va = columns[tr[A]]
local vb = columns[tr[B]]
va[row], vb[row] = fn(va[row], vb[row])
elseif queryLength == 3 then
elseif not D then
local va = columns[tr[A]]
local vb = columns[tr[B]]
local vc = columns[tr[C]]
va[row], vb[row], vc[row] = fn(va[row], vb[row], vc[row])
elseif queryLength == 4 then
elseif not E then
local va = columns[tr[A]]
local vb = columns[tr[B]]
local vc = columns[tr[C]]
@ -1088,7 +1157,8 @@ do
local length = 0
local components = { ... } :: any
A, B, C, D, E, F, G, H = ...
A, B, C, D, E, F, G, H, I = ...
local archetypes = world.archetypes
local firstArchetypeMap: ArchetypeMap
@ -1131,6 +1201,8 @@ do
init = false
ids = components
world_query_iter_create()
return it
end
end

View file

@ -516,6 +516,25 @@ TEST("world:query()", function()
CHECK(count == 2)
end
do CASE "despawning while iterating"
local world = jecs.World.new()
local A = world:component()
local B = world:component()
local e1 = world:entity()
local e2 = world:entity()
world:add(e1, A)
world:add(e2, A)
world:add(e2, B)
local count = 0
for id in world:query(A) do
world:clear(id)
count += 1
end
CHECK(count == 2)
end
do CASE "iterator invalidation"
do CASE "adding"
SKIP()