diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2023-10-31 16:28:12 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2023-11-03 15:03:20 -0400 |
| commit | 5891af6843661a9d30c12c3ef0f9efeb534aee88 (patch) | |
| tree | 5e1af54c08f6ff4baaefcd187fbec4d031de76c9 /src/entities.cpp | |
| parent | cb26bbf9945b7b3badb088e1c3df06efdfc7fad1 (diff) | |
rebuild instance buffers as they become oversized
Diffstat (limited to 'src/entities.cpp')
| -rw-r--r-- | src/entities.cpp | 113 |
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) { |
