From 270eda6f558c972ec86ad0580f1d3d18afc83a94 Mon Sep 17 00:00:00 2001 From: hachem Date: Mon, 21 Sep 2026 20:55:02 +0200 Subject: feat: update ui --- src/platform/opengl/shader.cpp | 1 + src/platform/vulkan/vulkan_common.h | 1 + src/platform/vulkan/vulkan_device.cpp | 29 ++++++++++++++++++++++++----- 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'src/platform') diff --git a/src/platform/opengl/shader.cpp b/src/platform/opengl/shader.cpp index a56a1b7..ca63c14 100644 --- a/src/platform/opengl/shader.cpp +++ b/src/platform/opengl/shader.cpp @@ -5,6 +5,7 @@ #include #include +#include namespace Donut { diff --git a/src/platform/vulkan/vulkan_common.h b/src/platform/vulkan/vulkan_common.h index cb86d69..22d389c 100644 --- a/src/platform/vulkan/vulkan_common.h +++ b/src/platform/vulkan/vulkan_common.h @@ -343,6 +343,7 @@ namespace Donut::RHI std::vector m_frame_pools; // one per frame in flight VkDescriptorPool m_imgui_pool = VK_NULL_HANDLE; + VkDescriptorPool m_offscreen_pool = VK_NULL_HANDLE; // run_offscreen's own; never a frame's bool m_imgui = false; VkCommandListR m_cmds; diff --git a/src/platform/vulkan/vulkan_device.cpp b/src/platform/vulkan/vulkan_device.cpp index a4f9ac7..f780f6f 100644 --- a/src/platform/vulkan/vulkan_device.cpp +++ b/src/platform/vulkan/vulkan_device.cpp @@ -119,8 +119,24 @@ namespace Donut::RHI auto VulkanDevice::run_offscreen(const std::function& record) -> void { + // this gets called mid-frame (the Export button fires from inside ui->draw + // while the frame's command buffer is still being recorded), so it has to be + // fully self-contained: its own command list AND its own descriptor pool. the + // old version reused m_cmds and then freed its buffer, so the in-flight frame + // carried on recording into a dangling handle. segfault. vkDeviceWaitIdle(m_device); - vkResetDescriptorPool(m_device, m_frame_pools[0], 0); // per-draw sets for this pass + + if (m_offscreen_pool == VK_NULL_HANDLE) + { + VkDescriptorPoolSize sizes[2] = { + { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 32 }, + { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 32 }, + }; + VkDescriptorPoolCreateInfo dpci{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; + dpci.maxSets = 16; dpci.poolSizeCount = 2; dpci.pPoolSizes = sizes; + vkCreateDescriptorPool(m_device, &dpci, nullptr, &m_offscreen_pool); + } + vkResetDescriptorPool(m_device, m_offscreen_pool, 0); // per-draw sets for this pass VkCommandBufferAllocateInfo cbai{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO }; cbai.commandPool = m_command_pool; cbai.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; cbai.commandBufferCount = 1; @@ -128,10 +144,12 @@ namespace Donut::RHI VkCommandBufferBeginInfo bi{ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO }; bi.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; vkBeginCommandBuffer(cmd, &bi); - m_cmds.m_device = m_device; m_cmds.m_cmd = cmd; - m_cmds.m_swapchain_rp = m_swapchain_rp; m_cmds.m_swapchain_fb = VK_NULL_HANDLE; m_cmds.m_extent = m_extent; - m_cmds.m_frame_pool = m_frame_pools[0]; m_cmds.m_pipe = nullptr; - record(m_cmds); // records its own off-screen render pass(es) + // a local command list, so the frame's m_cmds is never touched. + VkCommandListR ocmds; + ocmds.m_device = m_device; ocmds.m_cmd = cmd; + ocmds.m_swapchain_rp = m_swapchain_rp; ocmds.m_swapchain_fb = VK_NULL_HANDLE; ocmds.m_extent = m_extent; + ocmds.m_frame_pool = m_offscreen_pool; ocmds.m_pipe = nullptr; + record(ocmds); // records its own off-screen render pass(es) vkEndCommandBuffer(cmd); VkSubmitInfo si{ VK_STRUCTURE_TYPE_SUBMIT_INFO }; si.commandBufferCount = 1; si.pCommandBuffers = &cmd; @@ -264,6 +282,7 @@ namespace Donut::RHI if (m_imgui_pool) vkDestroyDescriptorPool(m_device, m_imgui_pool, nullptr); for (auto p : m_frame_pools) vkDestroyDescriptorPool(m_device, p, nullptr); m_frame_pools.clear(); + if (m_offscreen_pool) { vkDestroyDescriptorPool(m_device, m_offscreen_pool, nullptr); m_offscreen_pool = VK_NULL_HANDLE; } for (auto s : m_render_finished) vkDestroySemaphore(m_device, s, nullptr); for (auto s : m_image_available) vkDestroySemaphore(m_device, s, nullptr); for (auto f : m_in_flight) vkDestroyFence(m_device, f, nullptr); -- cgit v1.3