summaryrefslogtreecommitdiff
path: root/src/ecs.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-10-02 19:51:10 -0400
committerJonathan Bradley <jcb@pikum.xyz>2023-10-02 19:51:10 -0400
commit4899815c69894bba3eb1a6faa8ccbbc676751728 (patch)
treee3d5895b35d060d193ec59ccdeaf65dfbad6e145 /src/ecs.cpp
parent2bdee2ce549b1306cafb1d657624eeed4cf7225a (diff)
instancing now works as intended
Diffstat (limited to 'src/ecs.cpp')
-rw-r--r--src/ecs.cpp215
1 files changed, 143 insertions, 72 deletions
diff --git a/src/ecs.cpp b/src/ecs.cpp
index b0f9250..9458506 100644
--- a/src/ecs.cpp
+++ b/src/ecs.cpp
@@ -1,7 +1,8 @@
#include "ecs.hpp"
-#include <new>
+#include "vendor/glm_include.hpp"
+#include "window.hpp"
TypeSafeInt_B(EntityHandle);
const uint64_t maxBucketItemCount = 256;
@@ -115,7 +116,6 @@ void ECS_Tick_Early(double delta) {
instBucketIndex = b;
}
if (inst != nullptr) {
- grBinds->instances.Remove(inst->index);
for (long bi = instBucketIndex; bi <= Comp_Instance_BucketContainer.bucketCounter; ++bi) {
uint64_t instCounter = 0;
if (bi == Comp_Instance_BucketContainer.bucketCounter) {
@@ -132,74 +132,139 @@ void ECS_Tick_Early(double delta) {
continue;
}
bucket.instances[ii].index -= 1;
+ bucket.instances[ii].isNeedingUpdated = true;
}
}
+ grBinds->instanceCounter -=1;
inst->entHandle = EntityHandle_MAX;
inst->grBindsHandle = GrBindsHandle_MAX;
inst->index = ECS_UNSET_VAL;
inst->instanceHandle = InstanceHandle_MAX;
- inst->ptr = CAFE_BABE(InstPos);
+ inst->isNeedingUpdated = false;
} else if (grBinds != nullptr) {
/*
* 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.
*/
- DynArrayDestroy(&grBinds->instances);
}
}
entitiesMarkedForRemoval.Resize(0);
}
+struct InstanceBufferCopyChunk {
+ uint64_t startingIndex;
+ uint64_t endingIndex;
+ DynArray<glm::mat4> mats{0};
+ VkBufferCopy dstBufferCopy;
+};
+struct InstanceBufferCopy {
+ CompGrBinds *grBinds = nullptr;
+ VkDeviceSize runningSize = 0;
+ DynArray<InstanceBufferCopyChunk> chunks{4};
+};
void ECS_Tick_Late(double delta) {
- for (long b = 0; b <= Comp_GrBinds_BucketContainer.bucketCounter; ++b) {
- auto &bkt = Comp_GrBinds_BucketContainer.buckets[b];
- long count = Comp_GrBinds_BucketContainer.bucketCounter == b ? Comp_GrBinds_BucketContainer.itemCounter >> 32 : maxBucketItemCount;
- for (long i = 0; i < count; ++i) {
- auto &grBinds = bkt.compGrBinds[i];
- if (grBinds.isInstanceBufferNeedingUpdated) {
- VkDeviceSize byteCount = sizeof(InstPos) * grBinds.instances.Count();
- VkBuffer transferBuffer;
- VkDeviceMemory transferMemory;
- void *deviceData;
- BeginTransferBuffer(byteCount, transferBuffer, transferMemory, deviceData);
- memcpy(deviceData, grBinds.instances.GetPtr(), byteCount);
- {
- VkCommandBufferBeginInfo cbbi;
- cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- cbbi.pNext = nullptr;
- cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- cbbi.pInheritanceInfo = nullptr;
-
- vkBeginCommandBuffer(transferCommandBuffer, &cbbi);
-
- VkBufferCopy vkBufferCopy;
- vkBufferCopy.srcOffset = 0;
- vkBufferCopy.dstOffset = 0;
- vkBufferCopy.size = byteCount;
-
- vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, grBinds.instanceBuffer, 1, &vkBufferCopy);
-
- vkEndCommandBuffer(transferCommandBuffer);
-
- VkSubmitInfo vkSubmitInfo{};
- vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- vkSubmitInfo.pNext = nullptr;
- vkSubmitInfo.waitSemaphoreCount = 0;
- vkSubmitInfo.pWaitSemaphores = nullptr;
- vkSubmitInfo.pWaitDstStageMask = nullptr;
- vkSubmitInfo.commandBufferCount = 1;
- vkSubmitInfo.pCommandBuffers = &transferCommandBuffer;
- vkSubmitInfo.signalSemaphoreCount = 0;
- vkSubmitInfo.pSignalSemaphores = nullptr;
- vkQueueSubmit(transferQueue, 1, &vkSubmitInfo, nullptr);
- vkQueueWaitIdle(transferQueue);
- vkResetCommandBuffer(transferCommandBuffer, 0);
+ DynArray<InstanceBufferCopy> bufferUpdates{0};
+ for (long b = 0; b <= Comp_Instance_BucketContainer.bucketCounter; ++b) {
+ auto &bkt = Comp_Instance_BucketContainer.buckets[b];
+ long count = Comp_Instance_BucketContainer.bucketCounter == b ? Comp_Instance_BucketContainer.itemCounter >> 32 : maxBucketItemCount;
+ for (uint32_t i = 0; i < count; ++i) {
+ auto &inst = bkt.instances[i];
+ if (inst.isNeedingUpdated == false)
+ continue;
+
+ GrBindsHandle_T grBindsHandle_t{static_cast<GrBindsHandle_T>(inst.grBindsHandle)};
+ auto b_inner = Buckets_GetBucketIndex(grBindsHandle_t);
+ auto bi_inner = Buckets_GetItemIndex(grBindsHandle_t);
+ auto &grBinds = Comp_GrBinds_BucketContainer.buckets[b_inner].compGrBinds[bi_inner];
+
+ InstanceBufferCopy *bfrUpdate = nullptr;
+ for (long u = 0; u < bufferUpdates.Count(); ++u) {
+ if (bufferUpdates[u].grBinds->grBindsHandle == inst.grBindsHandle) {
+ bfrUpdate = &bufferUpdates[u];
+ }
+ }
+ if (bfrUpdate == nullptr) {
+ bufferUpdates.Push({
+ .grBinds = &grBinds,
+ });
+ bfrUpdate = &bufferUpdates[bufferUpdates.Count() - 1];
+ }
+
+ InstanceBufferCopyChunk *chunk = nullptr;
+ for (long ii = 0; ii < bfrUpdate->chunks.Count(); ++ii) {
+ if (bfrUpdate->chunks[ii].endingIndex == inst.index - 1) {
+ chunk = &bfrUpdate->chunks[ii];
+ chunk->endingIndex += 1;
+ break;
}
- EndTransferBuffer(transferBuffer, transferMemory);
- grBinds.isInstanceBufferNeedingUpdated = false;
}
+ if (chunk == nullptr) {
+ bfrUpdate->chunks.Push({
+ .startingIndex = inst.index,
+ .endingIndex = inst.index,
+ });
+ chunk = &bfrUpdate->chunks[bfrUpdate->chunks.Count() - 1];
+ chunk->dstBufferCopy.dstOffset = sizeof(glm::mat4) * inst.index;
+ }
+
+ chunk->mats.Push(
+ glm::translate(glm::mat4(1), inst.instPos.pos)
+ * glm::mat4_cast(inst.instPos.rot)
+ * glm::scale(glm::mat4(1), inst.instPos.scale));
+ bfrUpdate->runningSize += sizeof(glm::mat4);
+ inst.isNeedingUpdated = false;
+ }
+ }
+ while (bufferUpdates.Count() > 0) {
+ InstanceBufferCopy ibc = bufferUpdates.Pop();
+
+ VkDeviceSize instanceBytes = sizeof(glm::mat4);
+ VkDeviceSize byteCount = ibc.runningSize;
+ VkBuffer transferBuffer;
+ VkDeviceMemory transferMemory;
+ void *deviceData;
+ BeginTransferBuffer(byteCount, transferBuffer, transferMemory, deviceData);
+ VkDeviceSize runningOffset = 0;
+ for (long i = 0; i < ibc.chunks.Count(); ++i) {
+ auto *chunk = &ibc.chunks[i];
+ memcpy(static_cast<char *>(deviceData) + runningOffset, chunk->mats.GetPtr(), byteCount);
+ chunk->dstBufferCopy.srcOffset = runningOffset;
+ chunk->dstBufferCopy.size = instanceBytes * (chunk->endingIndex - chunk->startingIndex + 1);
+ runningOffset += chunk->dstBufferCopy.size;
+ }
+ assert(runningOffset == ibc.runningSize);
+
+ {
+ VkCommandBufferBeginInfo cbbi;
+ cbbi.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ cbbi.pNext = nullptr;
+ cbbi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+ cbbi.pInheritanceInfo = nullptr;
+
+ vkBeginCommandBuffer(transferCommandBuffer, &cbbi);
+
+ for (long i = 0; i < ibc.chunks.Count(); ++i) {
+ vkCmdCopyBuffer(transferCommandBuffer, transferBuffer, ibc.grBinds->instanceBuffer, 1, &ibc.chunks[i].dstBufferCopy);
+ }
+
+ vkEndCommandBuffer(transferCommandBuffer);
+
+ VkSubmitInfo vkSubmitInfo{};
+ vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ vkSubmitInfo.pNext = nullptr;
+ vkSubmitInfo.waitSemaphoreCount = 0;
+ vkSubmitInfo.pWaitSemaphores = nullptr;
+ vkSubmitInfo.pWaitDstStageMask = nullptr;
+ vkSubmitInfo.commandBufferCount = 1;
+ vkSubmitInfo.pCommandBuffers = &transferCommandBuffer;
+ vkSubmitInfo.signalSemaphoreCount = 0;
+ vkSubmitInfo.pSignalSemaphores = nullptr;
+ vkQueueSubmit(transferQueue, 1, &vkSubmitInfo, nullptr);
+ vkQueueWaitIdle(transferQueue);
+ vkResetCommandBuffer(transferCommandBuffer, 0);
}
+ EndTransferBuffer(transferBuffer, transferMemory);
}
}
@@ -261,25 +326,24 @@ CompInstance &ECS_CreateInstance(EntityHandle entHandle, EntityHandle entityType
ent->instanceHandle = InstanceHandle{newHandle};
GrBindsHandle_T grBindsHandle_t{static_cast<GrBindsHandle_T>(entTypeEnt->grBindsHandle)};
- auto b2 = Buckets_GetBucketIndex(grBindsHandle_t);
- auto i2 = Buckets_GetItemIndex(grBindsHandle_t);
- auto *grBinds = &Comp_GrBinds_BucketContainer.buckets[b2].compGrBinds[i2];
- grBinds->isInstanceBufferNeedingUpdated = true;
- grBinds->instanceBindingCount = 1;
auto b = Buckets_GetBucketIndex(newHandle);
auto i = Buckets_GetItemIndex(newHandle);
- auto *comp = &Comp_Instance_BucketContainer.buckets[b].instances[i];
+ auto *instBkt = &Comp_Instance_BucketContainer.buckets[b];
+ auto *comp = &instBkt->instances[i];
comp = new (comp) CompInstance{};
comp->entHandle = entHandle;
+
+ auto b2 = Buckets_GetBucketIndex(grBindsHandle_t);
+ auto i2 = Buckets_GetItemIndex(grBindsHandle_t);
+ auto *grBinds = &Comp_GrBinds_BucketContainer.buckets[b2].compGrBinds[i2];
+
comp->grBindsHandle = grBinds->grBindsHandle;
comp->instanceHandle = ent->instanceHandle;
- comp->index = grBinds->instances.Count();
- grBinds->instances.Push({
- .pos = glm::vec3(0),
- .rot = glm::vec3(1),
- .scale = glm::vec3(1),
- });
- comp->ptr = &grBinds->instances[comp->index];
+ comp->index = grBinds->instanceCounter++;
+ comp->instPos.pos = glm::vec3(0, 0, 0);
+ comp->instPos.rot = glm::quat(1, 0, 0, 0);
+ comp->instPos.scale = glm::vec3(1, 1, 1);
+ comp->isNeedingUpdated = true;
return *comp;
}
@@ -295,16 +359,23 @@ CompInstance *ECS_GetInstance(EntityHandle entHandle) {
auto i = Buckets_GetItemIndex(instanceHandle_t);
auto *inst = &Comp_Instance_BucketContainer.buckets[b].instances[i];
- if (inst->index == ECS_UNSET_VAL)
- return nullptr;
- if (inst->grBindsHandle == GrBindsHandle_MAX)
- return nullptr;
+ return inst;
+}
- GrBindsHandle_T grBindsHandle_t{static_cast<GrBindsHandle_T>(inst->grBindsHandle)};
- auto b2 = Buckets_GetBucketIndex(grBindsHandle_t);
- auto i2 = Buckets_GetItemIndex(grBindsHandle_t);
- auto grBinds = &Comp_GrBinds_BucketContainer.buckets[b2].compGrBinds[i2];
+void ECS_UpdateInstance(EntityHandle entHandle, const InstPos &instPos) {
+ Entity *ent = nullptr;
+ ECS_GetEntity_Inner(entHandle, ent);
- inst->ptr = &grBinds->instances[inst->index];
- return inst;
+ if (ent->instanceHandle == InstanceHandle_MAX)
+ return;
+
+ InstanceHandle_T instanceHandle_t{static_cast<InstanceHandle_T>(ent->instanceHandle)};
+ auto b = Buckets_GetBucketIndex(instanceHandle_t);
+ auto i = Buckets_GetItemIndex(instanceHandle_t);
+ auto *inst = &Comp_Instance_BucketContainer.buckets[b].instances[i];
+
+ inst->instPos.pos = instPos.pos;
+ inst->instPos.rot = instPos.rot;
+ inst->instPos.scale = instPos.scale;
+ inst->isNeedingUpdated = true;
}