diff options
| author | Jonathan Bradley <jcb@pikum.xyz> | 2025-08-14 11:29:48 -0400 |
|---|---|---|
| committer | Jonathan Bradley <jcb@pikum.xyz> | 2025-08-14 11:46:02 -0400 |
| commit | ebcae77b137a759c453b89a774ece5a755078a38 (patch) | |
| tree | 4d2239e94bfbbd7bbe9b33cb33e8ca8262b99ea1 /src | |
| parent | 0b5f7059cc88d9ee18fa46eb7e6d9fb45ee65da8 (diff) | |
pke: HACK: avoid modifying in-use vulkan buffers
Replace me with a memory barrier helper fn.
Diffstat (limited to 'src')
| -rw-r--r-- | src/game.cpp | 1 | ||||
| -rw-r--r-- | src/static-ui.cpp | 4 | ||||
| -rw-r--r-- | src/window.cpp | 44 | ||||
| -rw-r--r-- | src/window.hpp | 4 |
4 files changed, 51 insertions, 2 deletions
diff --git a/src/game.cpp b/src/game.cpp index aea1039..27c42ac 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -114,6 +114,7 @@ void Game_Tick(double delta) { EntityType_Tick_Late(delta); ECS_Tick_Late(delta); + window_tick_late(delta); } void Game_Main(PKEWindowProperties windowProps, const char *executablePath) { diff --git a/src/static-ui.cpp b/src/static-ui.cpp index 1179028..7e500d9 100644 --- a/src/static-ui.cpp +++ b/src/static-ui.cpp @@ -464,10 +464,10 @@ void pke_ui_update_instance_buffer(pk_arr_t<pke_ui_box_instance_buffer_item> &ar vkResult = vkBindBufferMemory(vkDevice, newBuffer, new_memory, 0); assert(vkResult == VK_SUCCESS); if (pke_ui_master.bindings.bd_instance.buffer != VK_NULL_HANDLE) { - vkDestroyBuffer(vkDevice, pke_ui_master.bindings.bd_instance.buffer, vkAllocator); + pkvk_queue_vk_buffer_destroy(pke_ui_master.bindings.bd_instance.buffer); } if (pke_ui_master.bindings.deviceMemoryInst != VK_NULL_HANDLE) { - vkFreeMemory(vkDevice, pke_ui_master.bindings.deviceMemoryInst, vkAllocator); + pkvk_queue_vk_memory_free(pke_ui_master.bindings.deviceMemoryInst); } pke_ui_master.bindings.bd_instance.buffer = newBuffer; pke_ui_master.bindings.deviceMemoryInst = new_memory; diff --git a/src/window.cpp b/src/window.cpp index fa28e34..0c7f281 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -74,6 +74,13 @@ VkExtent2D Extent; VkSampler global_sampler; VkSampleCountFlagBits global_sample_count; +struct pkvk_queued_actions { + struct pkvk_queued_actions_delete { + pk_arr_t<VkBuffer> buffers{}; + pk_arr_t<VkDeviceMemory> memory{}; + } destroy; +} pkvk_actn_queue; + // pkvk_shared.descr_set_layout.single_sampler // the pke default, works for: // 2025-01-28 - present @@ -705,6 +712,14 @@ void pkvk_texture_upload(pkvk_texture_upload_data *data, pkvk_texture_upload_dat PKVK_EndBuffer(tmpBufferDetails); } +void pkvk_queue_vk_buffer_destroy(VkBuffer buffer) { + pk_arr_append_t(&pkvk_actn_queue.destroy.buffers, buffer); +} + +void pkvk_queue_vk_memory_free(VkDeviceMemory memory) { + pk_arr_append_t(&pkvk_actn_queue.destroy.memory, memory); +} + unsigned int FindQueueFamilyIndex(VkPhysicalDevice device, char hasPresentSupport = -1, VkQueueFlagBits includeBits = (VkQueueFlagBits)0U, VkQueueFlagBits excludeBits = (VkQueueFlagBits)0U) { if (hasPresentSupport == -1 && includeBits == 0 && excludeBits == 0) { @@ -3845,6 +3860,8 @@ void DestroyWindow() { fprintf(stderr, "VkAllocator has '%u' outstanding allocations!", vulkanAllocs.next); } pk_arr_reset(&vulkanAllocs); + pk_arr_reset(&pkvk_actn_queue.destroy.buffers); + pk_arr_reset(&pkvk_actn_queue.destroy.memory); // TODO there's un-freed vulkan stuff in the bucket // comment this out to see it in the debug printout pk_mem_bucket_destroy(MemBkt_Vulkan); @@ -3909,6 +3926,33 @@ void CalculateCombinedMemReqs(uint64_t memReqsCount, VkMemoryRequirements *memRe } } +/* 2025-08-07 - JCB DEBT + * This function was a result of buffer synchronization issues. + * Specifically, the UI module was trying to reallocate its instance buffer. + * Vulkan was emitting an error that the buffer was in use by a command buffer. + * Processing these actions after the graphics queue is idle solved that specific issue. + * This is a stop-gap measure so I can keep working and is not intended to be permanent. + * PERF + * This will block the main thread until all in-flight renders are no longer using any of the resources needed to render a scene. + * Move this to a fire-and-forget background thread that uses a memory barrier and a semaphore specifically for the target resource. + */ +void window_tick_late(double delta) { + (void)delta; + uint32_t i; + if (pkvk_actn_queue.destroy.buffers.next > 0 + || pkvk_actn_queue.destroy.memory.next > 0) { + vkQueueWaitIdle(pkvk_shared.queue.graphics); + } + for (i = 0; i < pkvk_actn_queue.destroy.buffers.next; ++i) { + vkDestroyBuffer(vkDevice, pkvk_actn_queue.destroy.buffers[i], vkAllocator); + } + for (i = 0; i < pkvk_actn_queue.destroy.memory.next; ++i) { + vkFreeMemory(vkDevice, pkvk_actn_queue.destroy.memory[i], vkAllocator); + } + pk_arr_clear(&pkvk_actn_queue.destroy.buffers); + pk_arr_clear(&pkvk_actn_queue.destroy.memory); +} + void Render() { vkWaitForFences(vkDevice, 1, &pkvk_present.fences_in_flight[CURRENT_FRAME], VK_TRUE, UINT64_MAX); diff --git a/src/window.hpp b/src/window.hpp index 1df25b7..90793ed 100644 --- a/src/window.hpp +++ b/src/window.hpp @@ -96,6 +96,7 @@ extern ImplementedPKVK pkePipelines; void CreateWindow(PKEWindowProperties wp); void DestroyWindow(); VkShaderModule UploadShader(AssetHandle handle); +void window_tick_late(double delta); void Render(); unsigned int FindMemoryTypeIndex(uint32_t typeFilter, VkMemoryPropertyFlags memPropertyFlags); @@ -150,4 +151,7 @@ struct pkvk_texture_upload_data_out { }; void pkvk_texture_upload(pkvk_texture_upload_data *data, pkvk_texture_upload_data_out *out); +void pkvk_queue_vk_buffer_destroy(VkBuffer buffer); +void pkvk_queue_vk_memory_free(VkDeviceMemory memory); + #endif /* PKE_WINDOW_HPP */ |
