From 00b9d26131a39568a944ddc477a66cf39d1ca0c4 Mon Sep 17 00:00:00 2001 From: Matthew Date: Wed, 19 Mar 2025 22:24:38 +1100 Subject: [PATCH] fixed vulkan buffer cleanup --- src/game.c | 10 ++----- src/render_vulkan.c | 64 ++++++++++++++++++++++++++++++++++++++++++--- src/render_vulkan.h | 5 ++++ src/util.c | 16 ++++++++---- src/util.h | 10 +++---- 5 files changed, 83 insertions(+), 22 deletions(-) diff --git a/src/game.c b/src/game.c index 828056e..073131a 100644 --- a/src/game.c +++ b/src/game.c @@ -52,16 +52,10 @@ static void RunCycle(Arena *arena, GameInput *inputs, u32 i_count) FinishFrame(); - //if (renderer.frame_state.prev_buffer_count > 0) - //FreeBuffers(renderer.frame_state.prev_buffers, renderer.frame_state.prev_buffer_count); + FreeBuffers(&vertex_buffer, 1); + FreeBuffers(&index_buffer, 1); ArenaFree(arena); - - u32 buffer_count = 2; - renderer.frame_state.prev_buffers = ArenaAlloc(arena, sizeof(RenderBuffer) * buffer_count); - renderer.frame_state.prev_buffers[0] = vertex_buffer; - renderer.frame_state.prev_buffers[1] = index_buffer; - renderer.frame_state.prev_buffer_count = buffer_count; } static void DrawRect(GUIContext *ctx, Vec2 p0, Vec2 p1, Vec4 col) diff --git a/src/render_vulkan.c b/src/render_vulkan.c index 1a0b32d..361ee5b 100644 --- a/src/render_vulkan.c +++ b/src/render_vulkan.c @@ -17,7 +17,7 @@ void DestroyRenderer() static u32 GetFrameIndex() { - return renderer.frame_state.frame_cnt % renderer.vk.sc.img_count; + return renderer.frame_state.frame_cnt % FRAME_OVERLAP; } static VkCommandBuffer GetFrameCmdBuf() @@ -40,6 +40,16 @@ static VkSemaphore GetFrameSwapSem() return renderer.vk.frame.swapchain_sems[GetFrameIndex()]; } +static u32 *GetFrameBufferCount() +{ + return &renderer.vk.frame.buffer_counts[GetFrameIndex()]; +} + +static RenderBuffer *GetFrameRenderBuffers() +{ + return renderer.vk.frame.buffer_destroy_queues[GetFrameIndex()]; +} + static void BeginRendering() { VkCommandBuffer cmd = GetFrameCmdBuf(); @@ -111,6 +121,15 @@ b32 BeginFrame() if (success) { + u32 *buf_count = GetFrameBufferCount(); + if (*buf_count > 0) + { + RenderBuffer *buffers = GetFrameRenderBuffers(); + for (u32 i = 0; i < *buf_count; i++) + vmaDestroyBuffer(renderer.vk.alloc, buffers[i].buffer, buffers[i].alloc); + *buf_count = 0; + } + result = vkResetFences(device, 1, fence); if (result != VK_SUCCESS) { @@ -324,6 +343,7 @@ b32 FinishFrame() } } + renderer.frame_state.prev_frame = renderer.frame_state.frame_cnt; renderer.frame_state.frame_cnt++; return success; @@ -344,11 +364,16 @@ static void FreeBuffers(RenderBuffer *buffers, u32 buffer_count) { VkDevice device = renderer.vk.device; VmaAllocator alloc = renderer.vk.alloc; + u32 frame_index = renderer.frame_state.begin_rendering ? renderer.frame_state.frame_cnt : renderer.frame_state.prev_frame; + frame_index = frame_index % FRAME_OVERLAP; + + u32 *buf_count = &renderer.vk.frame.buffer_counts[frame_index]; // TODO: make this better at some point for (u32 i = 0; i < buffer_count; i++) { - vmaDestroyBuffer(alloc, buffers[i].buffer, buffers[i].alloc); + renderer.vk.frame.buffer_destroy_queues[frame_index][*buf_count] = buffers[i]; + *buf_count += 1; } } @@ -1187,8 +1212,10 @@ static b32 CreateFrameStructures() renderer.vk.frame.swapchain_sems = ArenaAlloc(renderer.perm_arena, sizeof(VkSemaphore) * img_count); renderer.vk.frame.render_sems = ArenaAlloc(renderer.perm_arena, sizeof(VkSemaphore) * img_count); renderer.vk.frame.render_fences = ArenaAlloc(renderer.perm_arena, sizeof(VkFence) * img_count); + renderer.vk.frame.buffer_destroy_queues = ArenaAlloc(renderer.perm_arena, sizeof(RenderBuffer *) * FRAME_OVERLAP); + renderer.vk.frame.buffer_counts = ArenaAlloc(renderer.perm_arena, sizeof(u32) * FRAME_OVERLAP); - for (u32 i = 0; i < renderer.vk.sc.img_count; i++) + for (u32 i = 0; i < FRAME_OVERLAP; i++) { VkResult result; VkDevice device = renderer.vk.device; @@ -1214,6 +1241,8 @@ static b32 CreateFrameStructures() result = vkCreateSemaphore(device, &semaphore_create_info, NULL, &data->swapchain_sems[i]); if (result != VK_SUCCESS) success = false; + + renderer.vk.frame.buffer_destroy_queues[i] = ArenaAlloc(renderer.perm_arena, sizeof(RenderBuffer) * 64); } return success; @@ -1418,8 +1447,12 @@ static VkFormat GetImageFormat() static b32 CreateDescriptors() { b32 success = true; + + renderer.vk.pipe.bindings = ArenaAlloc(renderer.perm_arena, sizeof(DescBindings) * DESC_TYPE_MAX); + VkDevice device = renderer.vk.device; VkResult result; + DescBindings *bindings = renderer.vk.pipe.bindings; result = vkCreateDescriptorPool(device, &desc_pool_info, NULL, &renderer.vk.pipe.pool); if (result != VK_SUCCESS) @@ -1451,6 +1484,20 @@ static b32 CreateDescriptors() if (result != VK_SUCCESS) success = false; + for (u32 i = 0; i < DESC_TYPE_MAX; i++) + { + bindings[i].free = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS); + bindings[i].used = ArenaAlloc(renderer.perm_arena, sizeof(u16) * DESC_MAX_BINDINGS); + + u16 free_count = 0; + for (i32 j = DESC_MAX_BINDINGS-1; j >= 0; j--) + { + bindings[i].free[j] = free_count++; + } + + bindings[i].free_count = free_count; + } + return success; } @@ -1613,13 +1660,19 @@ static void DestroyVulkan() vkFreeCommandBuffers(device, imm.pool, 1, &imm.cmd); vkDestroyCommandPool(device, imm.pool, NULL); - for (u32 i = 0; i < sc.img_count; i++) + for (u32 i = 0; i < FRAME_OVERLAP; i++) { vkDestroySemaphore(device, data.render_sems[i], NULL); vkDestroySemaphore(device, data.swapchain_sems[i], NULL); vkDestroyFence(device, data.render_fences[i], NULL); vkFreeCommandBuffers(device, data.pools[i], 1, &data.buffers[i]); vkDestroyCommandPool(device, data.pools[i], NULL); + + if (data.buffer_counts[i] > 0) + { + for (u32 j = 0; j < data.buffer_counts[i]; j++) + vmaDestroyBuffer(renderer.vk.alloc, data.buffer_destroy_queues[i][j].buffer, data.buffer_destroy_queues[i][j].alloc); + } } vmaDestroyAllocator(renderer.vk.alloc); @@ -1633,6 +1686,9 @@ static void DestroyVulkan() #endif vkDestroyInstance(renderer.vk.inst, NULL); + + ArenaFree(renderer.arena); + ArenaFree(renderer.perm_arena); } void VkInfo(const char *str) diff --git a/src/render_vulkan.h b/src/render_vulkan.h index f9d3ba1..5012b2c 100644 --- a/src/render_vulkan.h +++ b/src/render_vulkan.h @@ -187,7 +187,9 @@ typedef struct typedef struct { u16 *free; + u16 free_count; u16 *used; + u16 used_count; } DescBindings; typedef struct @@ -213,6 +215,8 @@ typedef struct VkSemaphore *swapchain_sems; VkSemaphore *render_sems; VkFence *render_fences; + RenderBuffer **buffer_destroy_queues; + u32 *buffer_counts; } FrameStructures; typedef struct @@ -249,6 +253,7 @@ typedef struct { typedef struct { u32 img_ix; u64 frame_cnt; + u64 prev_frame; b8 begin_rendering; PipelineHandle last_pipeline; RenderBuffer *prev_buffers; diff --git a/src/util.c b/src/util.c index c8274b6..ade6fdf 100644 --- a/src/util.c +++ b/src/util.c @@ -159,25 +159,25 @@ void static inline WriteBit(BitWriter *bw, u32 v) FlushBits(bw); } -void static inline HMScan1(HMNode *nodes, u32 symbol) +void static inline HMScan1(HMNode *nodes, u8 symbol) { nodes[symbol].freq += 1; } -void static inline HMScan2(HMNode *nodes, u32 symbol1, u32 symbol2) +void static inline HMScan2(HMNode *nodes, u8 symbol1, u8 symbol2) { nodes[symbol1].freq += 1; nodes[symbol2].freq += 1; } -void static inline HMScan3(HMNode *nodes, u32 symbol1, u32 symbol2, u32 symbol3) +void static inline HMScan3(HMNode *nodes, u8 symbol1, u8 symbol2, u8 symbol3) { nodes[symbol1].freq += 1; nodes[symbol2].freq += 1; nodes[symbol3].freq += 1; } -void static inline HMScan4(HMNode *nodes, u32 symbol1, u32 symbol2, u32 symbol3, u32 symbol4) +void static inline HMScan4(HMNode *nodes, u8 symbol1, u8 symbol2, u8 symbol3, u8 symbol4) { nodes[symbol1].freq += 1; nodes[symbol2].freq += 1; @@ -228,10 +228,12 @@ void static inline HMBuildTable(HMNode *nodes) } } + // TODO: also finish this trash + HMQuicksort(nodes, 0, num_symbols); } -b32 CompressData(u8* data, u32 len) +b32 HMCompressData(u8 *data, u32 len, u8 *out) { b32 success = true; @@ -242,5 +244,9 @@ b32 CompressData(u8* data, u32 len) .pos = 24, }; + // TODO: finish this trash + + u32 iterations; + return success; } diff --git a/src/util.h b/src/util.h index 6d0a80d..5461f2c 100644 --- a/src/util.h +++ b/src/util.h @@ -61,14 +61,14 @@ i32 i32Clamp(i32 v, i32 min, i32 max); u32 u32Clamp(u32 v, u32 min, u32 max); // Compression -b32 CompressData(u8* data, u32 len); +b32 HMCompressData(u8 *data, u32 len, u8 *out); u32 static inline ReadBit(BitWriter *bw); void static inline RefillBits(BitWriter *bw); void static inline FlushBits(BitWriter *bw); void static inline WriteBit(BitWriter *bw, u32 v); -void static inline HMScan1(HMNode *nodes, u32 symbol); -void static inline HMScan2(HMNode *nodes, u32 symbol1, u32 symbol2); -void static inline HMScan3(HMNode *nodes, u32 symbol1, u32 symbol2, u32 symbol3); -void static inline HMScan4(HMNode *nodes, u32 symbol1, u32 symbol2, u32 symbol3, u32 symbol4); +void static inline HMScan1(HMNode *nodes, u8 symbol); +void static inline HMScan2(HMNode *nodes, u8 symbol1, u8 symbol2); +void static inline HMScan3(HMNode *nodes, u8 symbol1, u8 symbol2, u8 symbol3); +void static inline HMScan4(HMNode *nodes, u8 symbol1, u8 symbol2, u8 symbol3, u8 symbol4); void static inline HMBuildTable(HMNode *nodes); void static inline HMQuicksort(HMNode *nodes, u32 low, u32 high);