summaryrefslogtreecommitdiff
path: root/src/ecs.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2025-05-29 16:11:37 -0400
committerJonathan Bradley <jcb@pikum.xyz>2025-05-29 16:11:37 -0400
commitd9dc3559296661249f9e5f1c3d0a8320cbf8fc29 (patch)
tree2a0203b676f15e8933960e786c8181354f73b121 /src/ecs.cpp
parenta9bc23377bd9193cd3eb3ef2e91431d088d13d5d (diff)
pke: ecs: BucketContainer > pk_bkt_arr_t & cleanup
Diffstat (limited to 'src/ecs.cpp')
-rw-r--r--src/ecs.cpp459
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>();
}