diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-29 16:11:37 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-05-29 16:11:37 -0400 |
| commit | d9dc3559296661249f9e5f1c3d0a8320cbf8fc29 (patch) | |
| tree | 2a0203b676f15e8933960e786c8181354f73b121 /src/ecs.cpp | |
| parent | a9bc23377bd9193cd3eb3ef2e91431d088d13d5d (diff) | |
pke: ecs: BucketContainer > pk_bkt_arr_t & cleanup
Diffstat (limited to 'src/ecs.cpp')
| -rw-r--r-- | src/ecs.cpp | 459 |
1 files changed, 225 insertions, 234 deletions
diff --git a/src/ecs.cpp b/src/ecs.cpp index 20e6b49..137686b 100644 --- a/src/ecs.cpp +++ b/src/ecs.cpp @@ -12,20 +12,13 @@ #include <BulletCollision/CollisionShapes/btConvexHullShape.h> #include <glm/gtc/type_ptr.hpp> -constexpr struct { - const pk_handle_item_index_T generics = 256; - const pk_handle_item_index_T entityPtrs = 256; - const pk_handle_item_index_T grBinds = 64; - const pk_handle_item_index_T instances = 256; -} bcSizes; - struct ECS { struct pk_membucket *bkt = nullptr; struct ECSBucketContainers { - BucketContainer<Entity_Base, pk_handle, 4> generics{}; - BucketContainer<Entity_Base *, EntityHandle, 4> entityPtrs{}; - BucketContainer<CompGrBinds, GrBindsHandle, 4> grBinds{}; - BucketContainer<CompInstance, InstanceHandle, 4> instances{}; + pk_bkt_arr_t<Entity_Base> generics{}; + pk_bkt_arr_t<Entity_Base *> entityPtrs{}; + pk_bkt_arr_t<CompGrBinds> grBinds{}; + pk_bkt_arr_t<CompInstance> instances{}; } bc; } ecs; @@ -61,15 +54,15 @@ bool ecs_pk_arr_find_first_matching_pointer(void *search_ptr, void *list_ptr) { } void ECS_GetEntity_Inner(EntityHandle entHandle, Entity_Base*& ent) { - assert(pk_handle_validate(entHandle, ecs.bc.entityPtrs.pkeHandle, ecs.bc.entityPtrs.limits.itemIndex) == PK_HANDLE_VALIDATION_VALID); - ent = ecs.bc.entityPtrs.buckets[entHandle.bucketIndex][entHandle.itemIndex]; + assert(pk_bkt_arr_handle_validate(&ecs.bc.entityPtrs, entHandle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID); + ent = ecs.bc.entityPtrs[entHandle]; } void ECS_Init() { - Buckets_Init(ecs.bc.generics, bcSizes.generics); - Buckets_Init(ecs.bc.entityPtrs, bcSizes.entityPtrs); - Buckets_Init(ecs.bc.grBinds, bcSizes.grBinds); - Buckets_Init(ecs.bc.instances, bcSizes.instances); + new (&ecs.bc.generics) pk_bkt_arr_t<Entity_Base>{}; + new (&ecs.bc.entityPtrs) pk_bkt_arr_t<Entity_Base*>{}; + new (&ecs.bc.grBinds) pk_bkt_arr_t<CompGrBinds>{}; + new (&ecs.bc.instances) pk_bkt_arr_t<CompInstance>{}; pk_arr_reserve(&entitiesMarkedForRemoval, 16); pk_arr_reserve(&EntitiesToBeRemoved, 16); pk_arr_reserve(&entitiesYetToBeRemoved, 16); @@ -81,34 +74,38 @@ Entity_Base *ECS_CreateGenericEntity() { * The only place this is called immediately calls ECS_CreateEntity afterwards. * There is no need to generate a uuid */ - pk_handle newHandle{Buckets_NewHandle(ecs.bc.generics)}; - return &ecs.bc.generics.buckets[newHandle.bucketIndex][newHandle.itemIndex]; + GenericEntityHandle newHandle{pk_bkt_arr_new_handle(&ecs.bc.generics)}; + Entity_Base *ent = &ecs.bc.generics[newHandle]; + new (ent) Entity_Base{}; + return ent; } EntityHandle ECS_CreateEntity(Entity_Base *entity, Entity_Base *parentEntity) { assert(entity != nullptr); assert(entity->handle == EntityHandle_MAX && "Entity already created!"); - EntityHandle entityHandle{Buckets_NewHandle(ecs.bc.entityPtrs)}; + EntityHandle entityHandle{pk_bkt_arr_new_handle(&ecs.bc.entityPtrs)}; entity->handle = entityHandle; if (parentEntity) entity->parentHandle = parentEntity->handle; if (entity->uuid == pk_uuid_max || entity->uuid == pk_uuid_zed) entity->uuid = pk_uuid_new_v7(); - ecs.bc.entityPtrs.buckets[entityHandle.bucketIndex][entityHandle.itemIndex] = entity; + ecs.bc.entityPtrs[entityHandle] = entity; return entityHandle; } Entity_Base *ECS_GetEntity(EntityHandle handle) { - if (pk_handle_validate(handle, ecs.bc.entityPtrs.pkeHandle, ecs.bc.entityPtrs.limits.itemIndex) != PK_HANDLE_VALIDATION_VALID) return nullptr; + if (pk_bkt_arr_handle_validate(&ecs.bc.entityPtrs, handle) != PK_BKT_ARR_HANDLE_VALIDATION_VALID) return nullptr; return ecs.bc.entityPtrs[handle]; } Entity_Base *ECS_GetEntityByUUID(pk_uuid uuid) { - for (pk_handle_bucket_index_T b = 0; b <= ecs.bc.entityPtrs.pkeHandle.bucketIndex; ++b) { - for (pk_handle_item_index_T i = 0; i < ecs.bc.entityPtrs.pkeHandle.itemIndex; ++i) { - Entity_Base *bs = ecs.bc.entityPtrs.buckets[b][i]; - if (bs->uuid == uuid) return bs; - } - } - return nullptr; + auto entity_ptr_find_cb = [](void *user_data, const void *arr_user_data, const void *arr_obj_data) { + (void)user_data; + const pk_uuid &uuid = *reinterpret_cast<const pk_uuid*>(arr_user_data);; + const Entity_Base &ent = **reinterpret_cast<const Entity_Base*const*>(arr_obj_data); + return (ent.uuid == uuid); + }; + EntityHandle handle { pk_bkt_arr_find_first_handle(&ecs.bc.entityPtrs, entity_ptr_find_cb, NULL, &uuid) }; + if (handle == EntityHandle_MAX) return nullptr; + return ecs.bc.entityPtrs[handle]; } void ECS_MarkForRemoval(Entity_Base *entity) { @@ -130,27 +127,36 @@ void ECS_Tick_Early(double delta) { pk_arr_clear(&entitiesMarkedForRemoval); // this has the potential to be slow as balls - for (pk_handle_bucket_index_T b = 0; b <= ecs.bc.entityPtrs.pkeHandle.bucketIndex; ++b) { - pk_handle_item_index_T entCount = b == ecs.bc.entityPtrs.pkeHandle.bucketIndex ? ecs.bc.entityPtrs.pkeHandle.itemIndex : ecs.bc.entityPtrs.limits.itemIndex; - for (pk_handle_item_index_T e = 0; e < entCount; ++e) { - Entity_Base *ent = ecs.bc.entityPtrs.buckets[b][e]; - if (ent->handle == EntityHandle_MAX) continue; - Entity_Base *parentEnt = nullptr; - if (ent->parentHandle != EntityHandle_MAX) - parentEnt = ecs.bc.entityPtrs.buckets[ent->parentHandle.bucketIndex][ent->parentHandle.itemIndex]; - if (ent->isMarkedForRemoval) { - pk_arr_append_t(&entitiesYetToBeRemoved, ent); - ent->handle = EntityHandle_MAX; - ent->parentHandle = EntityHandle_MAX; - ent->isMarkedForRemoval = false; - } else if (pk_arr_find_first_index(&EntitiesToBeRemoved, ent, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) { - ent->isMarkedForRemoval = true; - } else if (parentEnt != nullptr && pk_arr_find_first_index(&EntitiesToBeRemoved, parentEnt, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) { - ent->isMarkedForRemoval = true; - pk_arr_append_t(&EntitiesToBeRemoved, ent); - } + // TODO 2025-05-29 JCB PERF + // Consider requiring components to register their entity containers. + // Then loop through each container individually. + // TODO 2025-05-29 JCB + // I'm replacing BucketContainer with pk_bkt_arr. + // BucketContainer could not free slots, while pk_bkt_arr can. + // Before, we unintentionally had everything sequential, with parents first. + // That may or may not have implications about this logic. + // Might need to do several passes? + + auto ent_remove_cb = [](void *user_data, void *arr_obj_data) { + (void)user_data; + Entity_Base *ent = *reinterpret_cast<Entity_Base*const*>(arr_obj_data); + Entity_Base *parentEnt = nullptr; + if (ent->parentHandle != EntityHandle_MAX) { + parentEnt = ecs.bc.entityPtrs[ent->parentHandle]; } - } + if (ent->isMarkedForRemoval) { + pk_arr_append_t(&entitiesYetToBeRemoved, ent); + ent->handle = EntityHandle_MAX; + ent->parentHandle = EntityHandle_MAX; + ent->isMarkedForRemoval = false; + } else if (pk_arr_find_first_index(&EntitiesToBeRemoved, ent, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) { + ent->isMarkedForRemoval = true; + } else if (parentEnt != nullptr && pk_arr_find_first_index(&EntitiesToBeRemoved, parentEnt, ecs_pk_arr_find_first_matching_pointer) != uint32_t(-1)) { + ent->isMarkedForRemoval = true; + pk_arr_append_t(&EntitiesToBeRemoved, ent); + } + }; + pk_bkt_arr_iterate(&ecs.bc.entityPtrs, ent_remove_cb, NULL); } struct updateGrBindsAfter { @@ -170,90 +176,85 @@ void ECS_Tick(double 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 *>; + InstIterFn inst_iter_cb{}; + GrBindsIterFn grbinds_iter_cb{}; + pk_arr_t<updateGrBindsAfter> updateGrBinds; updateGrBinds.bkt = pkeSettings.mem.bkt; - for (long b = 0; b <= ecs.bc.instances.pkeHandle.bucketIndex; ++b) { - auto &bkt = ecs.bc.instances.buckets[b]; - long count = ecs.bc.instances.pkeHandle.bucketIndex == b ? ecs.bc.instances.pkeHandle.itemIndex : ecs.bc.instances.limits.itemIndex; - for (uint32_t i = 0; i < count; ++i) { - auto &inst = bkt[i]; - if (inst.entHandle == EntityHandle_MAX) - continue; - auto activationState = inst.bt.rigidBody->getActivationState(); - if (activationState == ISLAND_SLEEPING || activationState == DISABLE_SIMULATION || activationState == WANTS_DEACTIVATION) { - // do nothing - } else { - inst.isNeedingUpdated = true; - } - Entity_Base *ent = ecs.bc.entityPtrs.buckets[inst.entHandle.bucketIndex][inst.entHandle.itemIndex]; - 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); - continue; - } - if (updateGrBinds.next > 0 && inst.instanceHandle != InstanceHandle_MAX) { + inst_iter_cb.func = [entityRemovalCount, &updateGrBinds](CompInstance *arr_obj_data) { + CompInstance &inst = *arr_obj_data; + auto activationState = inst.bt.rigidBody->getActivationState(); + if (activationState == ISLAND_SLEEPING || activationState == DISABLE_SIMULATION || activationState == WANTS_DEACTIVATION) { + // no-op + } 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)) { - auto &after = updateGrBinds[afterIndex]; - inst.index -= after.count; - inst.isNeedingUpdated = true; + 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; } - } - } - if (entityRemovalCount > 0 || updateGrBinds.next > 0) { - for (pk_handle_bucket_index_T b = 0; b <= ecs.bc.grBinds.pkeHandle.bucketIndex; ++b) { - auto &bkt = ecs.bc.grBinds.buckets[b]; - long count = ecs.bc.grBinds.pkeHandle.bucketIndex == b ? ecs.bc.grBinds.pkeHandle.itemIndex : ecs.bc.grBinds.limits.itemIndex; - for (pk_handle_item_index_T i = 0; i < count; ++i) { - auto &grBinds = bkt[i]; - if (grBinds.entHandle == EntityHandle_MAX) { - continue; - } - 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.buckets[grBinds.entHandle.bucketIndex][grBinds.entHandle.itemIndex]; - 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 (afterIndex != uint32_t(-1)) { - auto &after = updateGrBinds[afterIndex]; - grBinds.instanceCounter -= after.count; - } + 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); + return; + } + 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)) { + auto &after = updateGrBinds[afterIndex]; + inst.index -= after.count; + inst.isNeedingUpdated = true; } } + }; + pk_bkt_arr_iterate(&ecs.bc.instances, &InstIterFn::invoke, &inst_iter_cb); + + grbinds_iter_cb.func = [&updateGrBinds](CompGrBinds *arr_obj_data) { + CompGrBinds &grBinds = *arr_obj_data; + 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 (afterIndex != uint32_t(-1)) { + auto &after = updateGrBinds[afterIndex]; + grBinds.instanceCounter -= after.count; + } + }; + if (entityRemovalCount > 0 || updateGrBinds.next > 0) { + pk_bkt_arr_iterate(&ecs.bc.grBinds, &GrBindsIterFn::invoke, &grbinds_iter_cb); } } @@ -274,69 +275,71 @@ void ECS_Tick_Late(double delta) { PKVK_TmpBufferDetails tmpBufferDetails{}; pk_arr_t<InstanceBufferCopy> bufferUpdates; bufferUpdates.bkt = pkeSettings.mem.bkt; - for (long b = 0; b <= ecs.bc.instances.pkeHandle.bucketIndex; ++b) { - auto &bkt = ecs.bc.instances.buckets[b]; - long count = ecs.bc.instances.pkeHandle.bucketIndex == b ? ecs.bc.instances.pkeHandle.itemIndex : ecs.bc.instances.limits.itemIndex; - for (uint32_t i = 0; i < count; ++i) { - auto &inst = bkt[i]; - if (inst.isNeedingUpdated == false) - continue; - if (inst.entHandle == EntityHandle_MAX) - continue; - if (inst.grBindsHandle == GrBindsHandle_MAX) - continue; - - auto &grBinds = ecs.bc.grBinds.buckets[inst.grBindsHandle.bucketIndex][inst.grBindsHandle.itemIndex]; - - InstanceBufferCopy *bfrUpdate = nullptr; - for (long u = 0; u < bufferUpdates.next; ++u) { - if (bufferUpdates[u].grBinds->grBindsHandle == inst.grBindsHandle) { - bfrUpdate = &bufferUpdates[u]; - } - } - if (bfrUpdate == nullptr) { - InstanceBufferCopy tmp{}; - tmp.grBinds = &grBinds; - tmp.chunks.bkt = pkeSettings.mem.bkt; - pk_arr_append_t(&bufferUpdates, tmp); - bfrUpdate = &bufferUpdates[bufferUpdates.next-1]; - pk_arr_reserve(&bfrUpdate->chunks, 4); - } - InstanceBufferCopyChunk *chunk = nullptr; - for (long ii = 0; ii < bfrUpdate->chunks.next; ++ii) { - if (bfrUpdate->chunks[ii].endingIndex == inst.index - 1) { - chunk = &bfrUpdate->chunks[ii]; - chunk->endingIndex += 1; - break; - } + using InstIterFn = pk_tmpln_1<void, CompInstance*, void*>; + InstIterFn inst_iter_cb{}; + + inst_iter_cb.func = [&bufferUpdates](CompInstance *arr_obj_data) { + CompInstance &inst = *arr_obj_data; + if (inst.isNeedingUpdated == false) + return; + if (inst.entHandle == EntityHandle_MAX) + return; + if (inst.grBindsHandle == GrBindsHandle_MAX) + return; + + auto &grBinds = ecs.bc.grBinds[inst.grBindsHandle]; + + InstanceBufferCopy *bfrUpdate = nullptr; + for (long u = 0; u < bufferUpdates.next; ++u) { + if (bufferUpdates[u].grBinds->grBindsHandle == inst.grBindsHandle) { + bfrUpdate = &bufferUpdates[u]; } - if (chunk == nullptr) { - InstanceBufferCopyChunk tmp{}; - tmp.startingIndex = inst.index; - tmp.endingIndex = inst.index; - tmp.mats.bkt = pkeSettings.mem.bkt; - tmp.dstBufferCopy = {}; - pk_arr_append_t(&bfrUpdate->chunks, tmp); - chunk = &bfrUpdate->chunks[bfrUpdate->chunks.next-1]; - chunk->dstBufferCopy.dstOffset = sizeof(glm::mat4) * inst.index; - pk_arr_reserve(&chunk->mats, 4); + } + if (bfrUpdate == nullptr) { + InstanceBufferCopy tmp{}; + tmp.grBinds = &grBinds; + tmp.chunks.bkt = pkeSettings.mem.bkt; + pk_arr_append_t(&bufferUpdates, tmp); + bfrUpdate = &bufferUpdates[bufferUpdates.next-1]; + pk_arr_reserve(&bfrUpdate->chunks, 4); + } + + InstanceBufferCopyChunk *chunk = nullptr; + for (long ii = 0; ii < bfrUpdate->chunks.next; ++ii) { + if (bfrUpdate->chunks[ii].endingIndex == inst.index - 1) { + chunk = &bfrUpdate->chunks[ii]; + chunk->endingIndex += 1; + break; } + } + if (chunk == nullptr) { + InstanceBufferCopyChunk tmp{}; + tmp.startingIndex = inst.index; + tmp.endingIndex = inst.index; + tmp.mats.bkt = pkeSettings.mem.bkt; + tmp.dstBufferCopy = {}; + pk_arr_append_t(&bfrUpdate->chunks, tmp); + chunk = &bfrUpdate->chunks[bfrUpdate->chunks.next-1]; + chunk->dstBufferCopy.dstOffset = sizeof(glm::mat4) * inst.index; + pk_arr_reserve(&chunk->mats, 4); + } - btTransform btMatrix_posRot; - inst.bt.motionState->getWorldTransform(btMatrix_posRot); - float openglMatrix[16]; - btMatrix_posRot.getOpenGLMatrix(openglMatrix); - glm::mat4 glmMat_posRot = glm::make_mat4(openglMatrix); + btTransform btMatrix_posRot; + inst.bt.motionState->getWorldTransform(btMatrix_posRot); + float openglMatrix[16]; + btMatrix_posRot.getOpenGLMatrix(openglMatrix); + glm::mat4 glmMat_posRot = glm::make_mat4(openglMatrix); - glm::vec3 scale; - BulletToGlm(inst.bt.rigidBody->getCollisionShape()->getLocalScaling(), scale); + glm::vec3 scale; + BulletToGlm(inst.bt.rigidBody->getCollisionShape()->getLocalScaling(), scale); + + pk_arr_append_t(&chunk->mats, glm::scale(glmMat_posRot, scale)); + bfrUpdate->runningSize += sizeof(glm::mat4); + inst.isNeedingUpdated = false; + }; + pk_bkt_arr_iterate(&ecs.bc.instances, &InstIterFn::invoke, &inst_iter_cb); - pk_arr_append_t(&chunk->mats, glm::scale(glmMat_posRot, scale)); - bfrUpdate->runningSize += sizeof(glm::mat4); - inst.isNeedingUpdated = false; - } - } while (bufferUpdates.next > 0) { InstanceBufferCopy &ibc = bufferUpdates[bufferUpdates.next - 1]; @@ -422,8 +425,8 @@ void ECS_HandleCollision(CompInstance *lhsInst, CompInstance *rhsInst) { CompGrBinds *ECS_CreateGrBinds(Entity_Base *entity) { assert(entity != nullptr && entity != CAFE_BABE(Entity_Base)); - GrBindsHandle grBindsHandle{Buckets_NewHandle(ecs.bc.grBinds)}; - auto *comp = &ecs.bc.grBinds.buckets[grBindsHandle.bucketIndex][grBindsHandle.itemIndex]; + GrBindsHandle grBindsHandle{pk_bkt_arr_new_handle(&ecs.bc.grBinds)}; + auto *comp = &ecs.bc.grBinds[grBindsHandle]; comp = new (comp) CompGrBinds{}; comp->entHandle = entity->handle; comp->grBindsHandle = grBindsHandle; @@ -433,44 +436,37 @@ CompGrBinds *ECS_CreateGrBinds(Entity_Base *entity) { CompGrBinds *ECS_GetGrBinds(GrBindsHandle grBindsHandle) { if (grBindsHandle == GrBindsHandle_MAX) return nullptr; - assert(pk_handle_validate(grBindsHandle, ecs.bc.grBinds.pkeHandle, ecs.bc.grBinds.limits.itemIndex) == PK_HANDLE_VALIDATION_VALID); - return &ecs.bc.grBinds.buckets[grBindsHandle.bucketIndex][grBindsHandle.itemIndex]; + assert(pk_bkt_arr_handle_validate(&ecs.bc.grBinds, grBindsHandle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID); + return &ecs.bc.grBinds[grBindsHandle]; } void ECS_GetGrBinds(Entity_Base *entity, pk_arr_t<CompGrBinds *> &arr) { if (entity == nullptr) return; - for (pk_handle_bucket_index_T b = 0; b <= ecs.bc.grBinds.pkeHandle.bucketIndex; ++b) { - auto &bkt = ecs.bc.grBinds.buckets[b]; - long itemCount = ecs.bc.grBinds.pkeHandle.bucketIndex == b ? ecs.bc.grBinds.pkeHandle.itemIndex : ecs.bc.grBinds.limits.itemIndex; - for (pk_handle_item_index_T i = 0; i < itemCount; ++i) { - CompGrBinds *grBinds = &bkt[i]; - if (grBinds->entHandle == entity->handle) { - pk_arr_append(&arr, &grBinds); - } - } - } -} -uint64_t ECS_GetGrBinds_BucketCount() { - return ecs.bc.grBinds.pkeHandle.bucketIndex + 1; + // 2025-05-29 JCB PERF + // There's gotta be a better way to do this than looping ALL GrBinds... + // Let's leave it until it shows up in performance tests. + + using GrBindsIterFn = pk_tmpln_1<void, CompGrBinds *, void *>; + GrBindsIterFn gr_binds_iter_cb{}; + + gr_binds_iter_cb.func = [&entity, &arr](CompGrBinds *arr_obj_data) { + if (arr_obj_data->entHandle == entity->handle) { + pk_arr_append(&arr, &arr_obj_data); + } + }; + pk_bkt_arr_iterate(&ecs.bc.grBinds, &GrBindsIterFn::invoke, &gr_binds_iter_cb); } -CompGrBinds *ECS_GetGrBinds(pk_handle_bucket_index_T bucketIndex, pk_handle_item_index_T &itemCount) { - if (bucketIndex == ecs.bc.grBinds.pkeHandle.bucketIndex) { - itemCount = ecs.bc.grBinds.pkeHandle.itemIndex; - } else { - itemCount = ecs.bc.grBinds.limits.itemIndex; - } - return ecs.bc.grBinds.buckets[bucketIndex]; +pk_bkt_arr *ECS_GetGrBinds() { + return &ecs.bc.grBinds; } CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds *entityTypeGrBinds, InstPos *inst_pos) { assert(entity != nullptr && entity != CAFE_BABE(Entity_Base)); - InstanceHandle instanceHandle{Buckets_NewHandle(ecs.bc.instances)}; - - auto *instBkt = ecs.bc.instances.buckets[instanceHandle.bucketIndex]; - auto *comp = &instBkt[instanceHandle.itemIndex]; + InstanceHandle instanceHandle{pk_bkt_arr_new_handle(&ecs.bc.instances)}; + auto *comp = &ecs.bc.instances[instanceHandle]; new (comp) CompInstance{}; comp->entHandle = entity->handle; comp->instanceHandle = instanceHandle; @@ -514,24 +510,28 @@ CompInstance *ECS_CreateInstance(Entity_Base *entity, pk_uuid uuid, CompGrBinds CompInstance *ECS_GetInstance(InstanceHandle instanceHandle ) { if (instanceHandle == InstanceHandle_MAX) return nullptr; - assert(pk_handle_validate(instanceHandle, ecs.bc.instances.pkeHandle, ecs.bc.instances.limits.itemIndex) == PK_HANDLE_VALIDATION_VALID); - auto *inst = &ecs.bc.instances.buckets[instanceHandle.bucketIndex][instanceHandle.itemIndex]; + assert(pk_bkt_arr_handle_validate(&ecs.bc.instances, instanceHandle) == PK_BKT_ARR_HANDLE_VALIDATION_VALID); + auto *inst = &ecs.bc.instances[instanceHandle]; return inst; } void ECS_GetInstances(Entity_Base *entity, pk_arr_t<CompInstance *> &arr) { if (entity == nullptr) return; - for (pk_handle_bucket_index_T b = 0; b <= ecs.bc.instances.pkeHandle.bucketIndex; ++b) { - auto &bkt = ecs.bc.instances.buckets[b]; - long itemCount = ecs.bc.instances.pkeHandle.bucketIndex == b ? ecs.bc.instances.pkeHandle.itemIndex : ecs.bc.instances.limits.itemIndex; - for (pk_handle_item_index_T i = 0; i < itemCount; ++i) { - CompInstance *inst = &bkt[i]; - if (inst->entHandle == entity->handle) { - pk_arr_append(&arr, &inst); - } + + // 2025-05-29 JCB PERF + // There's gotta be a better way to do this than looping ALL GrBinds... + // Let's leave it until it shows up in performance tests. + + using InstIterFn = pk_tmpln_1<void, CompInstance *, void *>; + InstIterFn inst_iter_cb{}; + + inst_iter_cb.func = [&entity, &arr](CompInstance *arr_obj_data) { + if (arr_obj_data->entHandle == entity->handle) { + pk_arr_append(&arr, &arr_obj_data); } - } + }; + pk_bkt_arr_iterate(&ecs.bc.instances, &InstIterFn::invoke, &inst_iter_cb); } void ECS_UpdateInstance(CompInstance *instance, const InstPos &instPos, bool overridePhysics) { @@ -549,17 +549,8 @@ void ECS_UpdateInstance(CompInstance *instance, const InstPos &instPos, bool ove } } -uint64_t ECS_GetInstances_BucketCount() { - return ecs.bc.instances.pkeHandle.bucketIndex + 1; -} - -CompInstance *ECS_GetInstances(pk_handle_bucket_index_T bucketIndex, pk_handle_item_index_T &itemCount) { - if (bucketIndex == ecs.bc.instances.pkeHandle.bucketIndex) { - itemCount = ecs.bc.instances.pkeHandle.itemIndex; - } else { - itemCount = ecs.bc.instances.limits.itemIndex; - } - return ecs.bc.instances.buckets[bucketIndex]; +pk_bkt_arr *ECS_GetInstances() { + return &ecs.bc.instances; } void ECS_Teardown() { @@ -567,8 +558,8 @@ void ECS_Teardown() { pk_arr_reset(&entitiesYetToBeRemoved); pk_arr_reset(&EntitiesToBeRemoved); pk_arr_reset(&entitiesMarkedForRemoval); - Buckets_Destroy(ecs.bc.instances); - Buckets_Destroy(ecs.bc.grBinds); - Buckets_Destroy(ecs.bc.entityPtrs); - Buckets_Destroy(ecs.bc.generics); + ecs.bc.instances.~pk_bkt_arr_t<CompInstance>(); + ecs.bc.grBinds.~pk_bkt_arr_t<CompGrBinds>(); + ecs.bc.entityPtrs.~pk_bkt_arr_t<Entity_Base*>(); + ecs.bc.generics.~pk_bkt_arr_t<Entity_Base>(); } |
