summaryrefslogtreecommitdiff
path: root/src/ecs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ecs.cpp')
-rw-r--r--src/ecs.cpp214
1 files changed, 113 insertions, 101 deletions
diff --git a/src/ecs.cpp b/src/ecs.cpp
index cdf125b..dd521ce 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -29,19 +29,13 @@ struct ECS {
*
* Used to build the other "removal" lists.
*/
-pk_arr_t<Entity_Base *> entitiesMarkedForRemoval;
-/*
- * Public list of entities that will be removed next tick
- *
- * Entity or child of entity that had ECS_MarkForRemoval called
- */
-pk_arr_t<Entity_Base *> EntitiesToBeRemoved;
+pk_arr_t<Entity_Base *> entitiesMarkedForRemoval{};
/*
* The entities being removed this tick
*
* Each of these entities has gone a full tick in the "to be removed" state
*/
-pk_arr_t<Entity_Base *> entitiesYetToBeRemoved;
+pk_arr_t<EntityHandle> entitiesYetToBeRemoved{};
/*
* Entities that have more instances registered than their current
@@ -55,6 +49,10 @@ bool ecs_pk_arr_find_first_matching_pointer(void *search_ptr, void *list_ptr) {
return search_ptr == list_ptr;
}
+bool ecs_pk_arr_find_first_matching_handle(void *search_ptr, void *list_ptr) {
+ return *reinterpret_cast<EntityHandle*>(search_ptr) == *reinterpret_cast<EntityHandle*>(list_ptr);
+}
+
void ECS_GetEntity_Inner(EntityHandle entHandle, Entity_Base*& ent) {
assert(pk_bkt_arr_handle_validate(&ecs.bc.entityPtrs, entHandle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID);
ent = ecs.bc.entityPtrs[entHandle];
@@ -68,7 +66,6 @@ void ECS_Init() {
new (&ecs.bc.instances) pk_bkt_arr_t<CompInstance>{ pk_bkt_arr_handle_MAX_constexpr, ecs.bkt, ecs.bkt };
new (&ecs.bc.ev_mgrs) pk_bkt_arr_t<pke_component_event>{ pk_bkt_arr_handle_MAX_constexpr, ecs.bkt, ecs.bkt };
pk_arr_reserve(&entitiesMarkedForRemoval, 16);
- pk_arr_reserve(&EntitiesToBeRemoved, 16);
pk_arr_reserve(&entitiesYetToBeRemoved, 16);
pk_arr_reserve(&EntitiesWithExcessInstances, 16);
pk_ev_create_mgr();
@@ -129,18 +126,15 @@ pk_bkt_arr *ECS_GetEntities() {
void ECS_Tick_Early(double delta) {
// these reserves might happen 1 tick early, but that's fine
(void)delta;
- bool b;
- pk_iter_t<Entity_Base> iter_ent{};
- pk_arr_clear(&EntitiesToBeRemoved);
- bool shouldRun = entitiesMarkedForRemoval.next > 0 || EntitiesToBeRemoved.next > 0 || entitiesYetToBeRemoved.next > 0;
- pk_arr_reserve(&entitiesYetToBeRemoved, entitiesMarkedForRemoval.reserved);
- pk_arr_reserve(&EntitiesToBeRemoved, entitiesMarkedForRemoval.reserved);
- memcpy(EntitiesToBeRemoved.data, entitiesMarkedForRemoval.data, sizeof(void *) * entitiesMarkedForRemoval.next);
-
- pk_arr_clear(&entitiesYetToBeRemoved);
+ bool b, any;
+ pk_iter_t<Entity_Base> iter_ent_obj{};
+ pk_iter_t<Entity_Base*> iter_ent{};
+ pk_iter_t<CompGrBinds> iter_grbinds{};
+ pk_iter_t<pke_component_event> iter_comp_ev{};
+ pk_iter_t<CompInstance> iter_inst{};
+ Entity_Base *parentEnt;
+ bool shouldRun = entitiesMarkedForRemoval.next > 0 || entitiesYetToBeRemoved.next > 0;
if (!shouldRun) return;
- EntitiesToBeRemoved.next = entitiesMarkedForRemoval.next;
- pk_arr_clear(&entitiesMarkedForRemoval);
// this has the potential to be slow as balls
// TODO 2025-05-29 JCB PERF
@@ -153,24 +147,91 @@ void ECS_Tick_Early(double delta) {
// That may or may not have implications about this logic.
// Might need to do several passes?
- b = pk_bkt_arr_iter_begin(&ecs.bc.entityPtrs, &iter_ent);
+ pk_arr_reserve(&entitiesYetToBeRemoved, entitiesMarkedForRemoval.reserved);
+ pk_arr_clear(&entitiesYetToBeRemoved);
+
+ b = pk_arr_iter_begin(&entitiesMarkedForRemoval, &iter_ent);
+ while (b == true) {
+ (*iter_ent)->isMarkedForRemoval = true;
+ pk_arr_append_t(&entitiesYetToBeRemoved, (*iter_ent)->handle);
+ b = pk_arr_iter_increment(&entitiesMarkedForRemoval, &iter_ent);
+ }
+ pk_arr_clear(&entitiesMarkedForRemoval);
+
+ do {
+ any = false;
+ b = pk_bkt_arr_iter_begin(&ecs.bc.entityPtrs, &iter_ent);
+ while (b == true) {
+ if ((*iter_ent)->isMarkedForRemoval == true) {
+ b = pk_bkt_arr_iter_increment(&ecs.bc.entityPtrs, &iter_ent);
+ continue;
+ }
+
+ if ((*iter_ent)->parentHandle == EntityHandle_MAX) {
+ b = pk_bkt_arr_iter_increment(&ecs.bc.entityPtrs, &iter_ent);
+ continue;
+ }
+
+ parentEnt = ecs.bc.entityPtrs[(*iter_ent)->parentHandle];
+ if (pk_arr_find_first_index(&entitiesYetToBeRemoved, &parentEnt->handle, ecs_pk_arr_find_first_matching_handle) != uint32_t(-1)) {
+ any = true;
+ (*iter_ent)->isMarkedForRemoval = true;
+ pk_arr_append_t(&entitiesYetToBeRemoved, (*iter_ent)->handle);
+ }
+
+ b = pk_bkt_arr_iter_increment(&ecs.bc.entityPtrs, &iter_ent);
+ }
+ } while (any == true);
+
+ b = pk_bkt_arr_iter_begin(&ecs.bc.grBinds, &iter_grbinds);
while (b == true) {
- Entity_Base *parentEnt = nullptr;
- if (iter_ent->parentHandle != EntityHandle_MAX) {
- parentEnt = ecs.bc.entityPtrs[iter_ent->parentHandle];
+ Entity_Base *ent = ecs.bc.entityPtrs[iter_grbinds->entHandle];
+ if (ent->isMarkedForRemoval) {
+ /*
+ * 2023-09-05 JB note - the Vulkan assets (device memory, buffers,
+ * pipeline layout, and descriptor set) are unloaded elsewhere, just,
+ * as they were created elsewhere.
+ * 2025-09-08 JCB note - reminder that the bindings
+ */
+ pk_bkt_arr_free_handle(&ecs.bc.grBinds, iter_grbinds->grBindsHandle);
+ new (&(*iter_grbinds)) CompGrBinds{};
}
- if (iter_ent->isMarkedForRemoval) {
- pk_arr_append_t<Entity_Base*>(&entitiesYetToBeRemoved, iter_ent);
- iter_ent->handle = EntityHandle_MAX;
- iter_ent->parentHandle = EntityHandle_MAX;
- iter_ent->isMarkedForRemoval = false;
- } else if (pk_arr_find_first_index(&EntitiesToBeRemoved, iter_ent, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) {
- iter_ent->isMarkedForRemoval = true;
- } else if (parentEnt != nullptr && pk_arr_find_first_index(&EntitiesToBeRemoved, parentEnt, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) {
- iter_ent->isMarkedForRemoval = true;
- pk_arr_append_t<Entity_Base*>(&EntitiesToBeRemoved, iter_ent);
+ b = pk_bkt_arr_iter_increment(&ecs.bc.grBinds, &iter_grbinds);
+ }
+
+ b = pk_bkt_arr_iter_begin(&ecs.bc.ev_mgrs, &iter_comp_ev);
+ while (b == true) {
+ Entity_Base *ent = ecs.bc.entityPtrs[iter_comp_ev->entity_handle];
+ if (ent->isMarkedForRemoval) {
+ pk_ev_destroy_mgr(iter_comp_ev->ev_mgr_id);
+ pk_bkt_arr_free_handle(&ecs.bc.ev_mgrs, iter_comp_ev->entity_handle);
+ new (&(*iter_comp_ev)) pke_component_event{};
}
- b = pk_bkt_arr_iter_increment(&ecs.bc.entityPtrs, &iter_ent);
+ b = pk_bkt_arr_iter_increment(&ecs.bc.ev_mgrs, &iter_comp_ev);
+ }
+
+ b = pk_bkt_arr_iter_begin(&ecs.bc.instances, &iter_inst);
+ while (b == true) {
+ Entity_Base *ent = ecs.bc.entityPtrs[iter_inst->entHandle];
+ if (ent->isMarkedForRemoval) {
+ BtDynamicsWorld->removeRigidBody(iter_inst->bt.rigidBody);
+ pk_delete<btDefaultMotionState>(iter_inst->bt.motionState, MemBkt_Bullet);
+ pk_delete<btRigidBody>(iter_inst->bt.rigidBody, MemBkt_Bullet);
+ iter_inst->bt.rigidBody = CAFE_BABE(btRigidBody);
+ iter_inst->bt.motionState = CAFE_BABE(btDefaultMotionState);
+
+ pk_bkt_arr_free_handle(&ecs.bc.instances, iter_inst->instanceHandle);
+ new (&(*iter_inst)) CompInstance{};
+ }
+ b = pk_bkt_arr_iter_increment(&ecs.bc.instances, &iter_inst);
+ }
+
+ b = pk_bkt_arr_iter_begin(&ecs.bc.generics, &iter_ent_obj);
+ while (b == true) {
+ if (iter_ent_obj->isMarkedForRemoval == true) {
+ pk_bkt_arr_free_handle(&ecs.bc.generics, pk_bkt_arr_handle { iter_ent_obj.id.bkt.b, iter_ent_obj.id.bkt.i });
+ }
+ b = pk_bkt_arr_iter_increment(&ecs.bc.generics, &iter_ent_obj);
}
}
@@ -189,24 +250,21 @@ void ECS_Tick(double delta) {
bool b;
pk_iter_t<CompInstance> iter_inst{};
pk_iter_t<CompGrBinds> iter_grbinds{};
- pk_iter_t<pke_component_event> iter_comp_ev{};
int32_t physicsTickCount = Physics_Tick(delta);
uint32_t entityRemovalCount = entitiesYetToBeRemoved.next;
if (physicsTickCount == 0 && entityRemovalCount == 0) return;
- using InstIterFn = pk_tmpln_1<void, CompInstance *, void *>;
- using GrBindsIterFn = pk_tmpln_1<void, CompGrBinds *, void *>;
- using CompEvMgrIterFn = pk_tmpln_1<void, pke_component_event *, void *>;
- InstIterFn inst_iter_cb{};
- GrBindsIterFn grbinds_iter_cb{};
- CompEvMgrIterFn comp_ev_mgr_iter_cb{};
-
pk_arr_t<updateGrBindsAfter> updateGrBinds;
updateGrBinds.bkt = pkeSettings.mem_bkt.game_transient;
b = pk_bkt_arr_iter_begin(&ecs.bc.instances, &iter_inst);
while (b == true) {
+ Entity_Base *ent = ecs.bc.entityPtrs[iter_inst->entHandle];
+ if (ent->isMarkedForRemoval) {
+ b = pk_bkt_arr_iter_increment(&ecs.bc.instances, &iter_inst);
+ continue;
+ }
CompInstance &inst = *iter_inst;
auto activationState = inst.bt.rigidBody->getActivationState();
if (activationState == ISLAND_SLEEPING || activationState == DISABLE_SIMULATION || activationState == WANTS_DEACTIVATION) {
@@ -214,36 +272,6 @@ void ECS_Tick(double delta) {
} else {
inst.isNeedingUpdated = true;
}
- Entity_Base *ent = ecs.bc.entityPtrs[inst.entHandle];
- if (entityRemovalCount > 0 && pk_arr_find_first_index(&entitiesYetToBeRemoved, ent, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) {
- if (inst.grBindsHandle != GrBindsHandle_MAX) {
- uint32_t afterIndex = pk_arr_find_first_index(&updateGrBinds, &inst.grBindsHandle, ecs_pk_arr_find_by_gr_binds_handle);
- updateGrBindsAfter *after = nullptr;
- if (afterIndex != uint32_t(-1)) {
- after = &updateGrBinds[afterIndex];
- } else {
- struct updateGrBindsAfter tmp{};
- tmp.grBindsHandle = inst.grBindsHandle;
- tmp.count = 0;
- pk_arr_append_t(&updateGrBinds, tmp);
- after = &updateGrBinds[updateGrBinds.next-1];
- }
- after->count += 1;
- }
-
- inst.entHandle = EntityHandle_MAX;
- inst.grBindsHandle = GrBindsHandle_MAX;
- inst.index = ECS_UNSET_VAL_32;
- inst.instanceHandle = InstanceHandle_MAX;
- inst.isNeedingUpdated = false;
- BtDynamicsWorld->removeRigidBody(inst.bt.rigidBody);
- pk_delete<btDefaultMotionState>(inst.bt.motionState, MemBkt_Bullet);
- pk_delete<btRigidBody>(inst.bt.rigidBody, MemBkt_Bullet);
- inst.bt.rigidBody = CAFE_BABE(btRigidBody);
- inst.bt.motionState = CAFE_BABE(btDefaultMotionState);
- b = pk_bkt_arr_iter_increment(&ecs.bc.instances, &iter_inst);
- continue;
- }
if (updateGrBinds.next > 0 && inst.instanceHandle != InstanceHandle_MAX) {
uint32_t afterIndex = pk_arr_find_first_index(&updateGrBinds, &inst.grBindsHandle, ecs_pk_arr_find_by_gr_binds_handle);
if (afterIndex != uint32_t(-1)) {
@@ -258,36 +286,18 @@ void ECS_Tick(double delta) {
b = pk_bkt_arr_iter_begin(&ecs.bc.grBinds, &iter_grbinds);
while ((entityRemovalCount > 0 || updateGrBinds.next > 0) && b == true) {
CompGrBinds &grBinds = *iter_grbinds;
- uint32_t afterIndex = pk_arr_find_first_index(&updateGrBinds, &grBinds.grBindsHandle, ecs_pk_arr_find_by_gr_binds_handle);
Entity_Base *ent = ecs.bc.entityPtrs[grBinds.entHandle];
- if (pk_arr_find_first_index(&entitiesYetToBeRemoved, ent, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) {
- grBinds.entHandle = EntityHandle_MAX;
- grBinds.grBindsHandle = GrBindsHandle_MAX;
- grBinds.vkPipelineLayout = VK_NULL_HANDLE;
- grBinds.graphicsPipeline = VK_NULL_HANDLE;
- grBinds.collisionCallback = PkeCallback{};
- /*
- * 2023-09-05 JB note - the Vulkan assets (device memory, buffers,
- * pipeline layout, and descriptor set) are unloaded elsewhere, just,
- * as they were created elsewhere.
- */
+ if (ent->isMarkedForRemoval) {
+ b = pk_bkt_arr_iter_increment(&ecs.bc.grBinds, &iter_grbinds);
+ continue;
}
+ uint32_t afterIndex = pk_arr_find_first_index(&updateGrBinds, &grBinds.grBindsHandle, ecs_pk_arr_find_by_gr_binds_handle);
if (afterIndex != uint32_t(-1)) {
auto &after = updateGrBinds[afterIndex];
grBinds.instanceCounter -= after.count;
}
b = pk_bkt_arr_iter_increment(&ecs.bc.grBinds, &iter_grbinds);
}
-
- b = pk_bkt_arr_iter_begin(&ecs.bc.ev_mgrs, &iter_comp_ev);
- while (entityRemovalCount > 0 && b == true) {
- Entity_Base *ent = ecs.bc.entityPtrs[iter_comp_ev->entity_handle];
- if (pk_arr_find_first_index(&entitiesYetToBeRemoved, ent, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) {
- pk_ev_destroy_mgr(iter_comp_ev->ev_mgr_id);
- pk_bkt_arr_free_handle(&ecs.bc.ev_mgrs, iter_comp_ev->pke_event_handle);
- }
- b = pk_bkt_arr_iter_increment(&ecs.bc.ev_mgrs, &iter_comp_ev);
- }
}
struct InstanceBufferCopyChunk {
@@ -302,17 +312,14 @@ struct InstanceBufferCopy {
pk_arr_t<InstanceBufferCopyChunk> chunks;
};
void ECS_Tick_Late(double delta) {
+ (void)delta;
bool b;
+ pk_iter_t<EntityHandle> iter_ent_handle{};
pk_iter_t<CompInstance> iter_inst{};
- // using a pointer here avoids calling the destructor when the object goes out of scope
- (void)delta;
PKVK_TmpBufferDetails tmpBufferDetails{};
pk_arr_t<InstanceBufferCopy> bufferUpdates;
bufferUpdates.bkt = pkeSettings.mem_bkt.game_transient;
- using InstIterFn = pk_tmpln_1<void, CompInstance*, void*>;
- InstIterFn inst_iter_cb{};
-
b = pk_bkt_arr_iter_begin(&ecs.bc.instances, &iter_inst);
while (b == true) {
CompInstance &inst = *iter_inst;
@@ -381,6 +388,12 @@ void ECS_Tick_Late(double delta) {
b = pk_bkt_arr_iter_increment(&ecs.bc.instances, &iter_inst);
}
+ b = pk_arr_iter_begin(&entitiesYetToBeRemoved, &iter_ent_handle);
+ while (b == true) {
+ pk_bkt_arr_free_handle(&ecs.bc.entityPtrs, *iter_ent_handle);
+ b = pk_arr_iter_increment(&entitiesYetToBeRemoved, &iter_ent_handle);
+ }
+
while (bufferUpdates.next > 0) {
InstanceBufferCopy &ibc = bufferUpdates[bufferUpdates.next - 1];
@@ -646,7 +659,6 @@ pk_bkt_arr *ECS_GetEvs() {
void ECS_Teardown() {
pk_arr_reset(&EntitiesWithExcessInstances);
pk_arr_reset(&entitiesYetToBeRemoved);
- pk_arr_reset(&EntitiesToBeRemoved);
pk_arr_reset(&entitiesMarkedForRemoval);
ecs.bc.ev_mgrs.~pk_bkt_arr_t<pke_component_event>();
ecs.bc.instances.~pk_bkt_arr_t<CompInstance>();