summaryrefslogtreecommitdiff
path: root/src/entities.cpp
diff options
context:
space:
mode:
authorJonathan Bradley <jcb@pikum.xyz>2023-10-31 16:28:12 -0400
committerJonathan Bradley <jcb@pikum.xyz>2023-11-03 15:03:20 -0400
commit5891af6843661a9d30c12c3ef0f9efeb534aee88 (patch)
tree5e1af54c08f6ff4baaefcd187fbec4d031de76c9 /src/entities.cpp
parentcb26bbf9945b7b3badb088e1c3df06efdfc7fad1 (diff)
rebuild instance buffers as they become oversized
Diffstat (limited to 'src/entities.cpp')
-rw-r--r--src/entities.cpp113
1 files changed, 111 insertions, 2 deletions
diff --git a/src/entities.cpp b/src/entities.cpp
index f61927a..a9108a0 100644
--- a/src/entities.cpp
+++ b/src/entities.cpp
@@ -1,6 +1,7 @@
#include "entities.hpp"
+#include <vulkan/vulkan_core.h>
DynArray<EntityType> GlobalEntityTypes{16};
void EntityType_Init() {
@@ -597,8 +598,10 @@ void EntityType_Load(EntityType &et) {
}
// set up instance buffer
- bufferCI.size = sizeof(InstPos) * et.startingInstanceCount;
- bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ grBinds.instanceBufferMaxCount = et.startingInstanceCount;
+ grBinds.instanceBufferMaxCount = grBinds.instanceBufferMaxCount < 1 ? 1 : grBinds.instanceBufferMaxCount;
+ bufferCI.size = sizeof(glm::mat4) * grBinds.instanceBufferMaxCount;
+ bufferCI.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
vkCreateBuffer(vkDevice, &bufferCI, vkAllocator, &grBinds.instanceBuffer);
VkMemoryRequirements vkMemoryRequirementsInst;
vkGetBufferMemoryRequirements(vkDevice, grBinds.instanceBuffer, &vkMemoryRequirementsInst);
@@ -613,6 +616,112 @@ void EntityType_Load(EntityType &et) {
}
}
+void EntityType_Tick_Late(double delta) {
+ while (EntitiesWithExcessInstances.Count() != 0) {
+ auto entHandle = EntitiesWithExcessInstances.Pop();
+ auto index = EntityType_FindByEntityHandle(entHandle);
+ auto &et = GlobalEntityTypes[index];
+ auto &grBinds = *ECS_GetGrBinds(entHandle);
+ EntityType_RolloverInstances(et, grBinds);
+ }
+}
+
+void EntityType_RolloverInstances(EntityType &et, CompGrBinds &grBinds) {
+ int32_t oldCount = grBinds.instanceBufferMaxCount;
+ int32_t newCount = std::ceil(grBinds.instanceBufferMaxCount * 1.5);
+ newCount = newCount < 4 ? 4 : newCount;
+ grBinds.instanceBufferMaxCount = newCount;
+ uint32_t oldSize = sizeof(glm::mat4) * oldCount;
+
+ VkDeviceMemory oldMemory(et.deviceMemoryInst);
+ VkBuffer oldBuffer(grBinds.instanceBuffer);
+
+ VkBufferCreateInfo vkBufferCreateInfo{};
+ vkBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ vkBufferCreateInfo.pNext = nullptr;
+ vkBufferCreateInfo.flags = 0;
+ vkBufferCreateInfo.size = sizeof(glm::mat4) * newCount;
+ vkBufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ vkBufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ vkBufferCreateInfo.queueFamilyIndexCount = 1;
+ vkBufferCreateInfo.pQueueFamilyIndices = &graphicsFamilyIndex;
+ vkCreateBuffer(vkDevice, &vkBufferCreateInfo, vkAllocator, &grBinds.instanceBuffer);
+
+ VkMemoryRequirements vkMemoryRequirementsInst;
+ vkGetBufferMemoryRequirements(vkDevice, grBinds.instanceBuffer, &vkMemoryRequirementsInst);
+
+ VkMemoryAllocateInfo vkMemoryAllocateInfo;
+ vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ vkMemoryAllocateInfo.pNext = nullptr;
+ vkMemoryAllocateInfo.allocationSize = vkMemoryRequirementsInst.size;
+ vkMemoryAllocateInfo.memoryTypeIndex = FindMemoryTypeIndex(vkMemoryRequirementsInst.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
+ vkAllocateMemory(vkDevice, &vkMemoryAllocateInfo, vkAllocator, &et.deviceMemoryInst);
+
+ vkBindBufferMemory(vkDevice, grBinds.instanceBuffer, et.deviceMemoryInst, 0);
+
+ // copy data
+ {
+ vkResetCommandBuffer(graphicsCommandBuffer, 0);
+ VkBufferMemoryBarrier memBarriers[2];
+ for (long i = 0; i < 2; ++i) {
+ memBarriers[i].sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
+ memBarriers[i].pNext = nullptr;
+ }
+
+ memBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ memBarriers[0].dstAccessMask = {};
+ memBarriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ memBarriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ memBarriers[0].buffer = oldBuffer;
+ memBarriers[0].offset = 0;
+ memBarriers[0].size = oldSize;
+
+ memBarriers[1].srcAccessMask = {};
+ memBarriers[1].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ memBarriers[1].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ memBarriers[1].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ memBarriers[1].buffer = grBinds.instanceBuffer;
+ memBarriers[1].offset = 0;
+ memBarriers[1].size = vkMemoryRequirementsInst.size;
+
+ VkCommandBufferBeginInfo vkCommandBufferBeginInfo;
+ vkCommandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ vkCommandBufferBeginInfo.pNext = nullptr;
+ // TODO consider single-use?
+ vkCommandBufferBeginInfo.flags = 0;
+ vkCommandBufferBeginInfo.pInheritanceInfo = nullptr;
+
+ vkBeginCommandBuffer(graphicsCommandBuffer, &vkCommandBufferBeginInfo);
+ vkCmdPipelineBarrier(graphicsCommandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 2, memBarriers, 0, nullptr);
+
+ VkBufferCopy vkBufferCopy;
+ vkBufferCopy.srcOffset = 0;
+ vkBufferCopy.dstOffset = 0;
+ vkBufferCopy.size = oldSize;
+ vkCmdCopyBuffer(graphicsCommandBuffer, oldBuffer, grBinds.instanceBuffer, 1, &vkBufferCopy);
+
+ vkEndCommandBuffer(graphicsCommandBuffer);
+
+ VkSubmitInfo submitInfo;
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.pNext = nullptr;
+ submitInfo.waitSemaphoreCount = 0;
+ submitInfo.pWaitSemaphores = nullptr;
+ submitInfo.pWaitDstStageMask = nullptr;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &graphicsCommandBuffer;
+ submitInfo.signalSemaphoreCount = 0;
+ submitInfo.pSignalSemaphores = nullptr;
+ vkQueueSubmit(graphicsQueue, 1, &submitInfo, nullptr);
+ vkQueueWaitIdle(graphicsQueue);
+ vkResetCommandBuffer(graphicsCommandBuffer, 0);
+ }
+
+ // cleanup
+ vkDestroyBuffer(vkDevice, oldBuffer, vkAllocator);
+ vkFreeMemory(vkDevice, oldMemory, vkAllocator);
+}
+
void EntityType_Teardown() {
long entityTypeCount = GlobalEntityTypes.Count();
for (long i = 0; i < entityTypeCount; ++i) {