diff options
Diffstat (limited to 'src/ecs.cpp')
| -rw-r--r-- | src/ecs.cpp | 214 |
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>(); |
