From 5891af6843661a9d30c12c3ef0f9efeb534aee88 Mon Sep 17 00:00:00 2001 From: Jonathan Bradley Date: Tue, 31 Oct 2023 16:28:12 -0400 Subject: rebuild instance buffers as they become oversized --- src/entities.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) (limited to 'src/entities.cpp') 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 DynArray 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) { -- cgit v1.2.3