#include "vk_renderpass_imgui.h" #include "imgui.h" #include "imgui_impl_sdl2.h" #include "imgui_impl_vulkan.h" #include "vk_device.h" #include "vk_swapchain.h" #include "core/vk_initializers.h" #include "core/engine_context.h" #include "render/rg_graph.h" void ImGuiPass::init(EngineContext *context) { _context = context; VkDescriptorPoolSize pool_sizes[] = { {VK_DESCRIPTOR_TYPE_SAMPLER, 1000}, {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000}, {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000}, {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000}, {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000} }; VkDescriptorPoolCreateInfo pool_info = {}; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; pool_info.maxSets = 1000; pool_info.poolSizeCount = (uint32_t) std::size(pool_sizes); pool_info.pPoolSizes = pool_sizes; VkDescriptorPool imguiPool; VK_CHECK(vkCreateDescriptorPool(_context->device->device(), &pool_info, nullptr, &imguiPool)); ImGui::CreateContext(); ImGui_ImplSDL2_InitForVulkan(_context->window); ImGui_ImplVulkan_InitInfo init_info = {}; init_info.Instance = _context->getDevice()->instance(); init_info.PhysicalDevice = _context->getDevice()->physicalDevice(); init_info.Device = _context->getDevice()->device(); init_info.Queue = _context->getDevice()->graphicsQueue(); init_info.DescriptorPool = imguiPool; init_info.MinImageCount = 3; init_info.ImageCount = 3; init_info.UseDynamicRendering = true; init_info.PipelineRenderingCreateInfo = {.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO}; init_info.PipelineRenderingCreateInfo.colorAttachmentCount = 1; auto _swapchainImageFormat = _context->getSwapchain()->swapchainImageFormat(); init_info.PipelineRenderingCreateInfo.pColorAttachmentFormats = &_swapchainImageFormat; init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; ImGui_ImplVulkan_Init(&init_info); ImGui_ImplVulkan_CreateFontsTexture(); // add the destroy the imgui created structures _deletionQueue.push_function([=]() { ImGui_ImplVulkan_Shutdown(); vkDestroyDescriptorPool(_context->getDevice()->device(), imguiPool, nullptr); }); } void ImGuiPass::cleanup() { fmt::print("ImGuiPass::cleanup()\n"); _deletionQueue.flush(); } void ImGuiPass::execute(VkCommandBuffer) { // ImGui is executed via the render graph now. } void ImGuiPass::register_graph(RenderGraph *graph, RGImageHandle swapchainHandle) { if (!graph || !swapchainHandle.valid()) return; graph->add_pass( "ImGui", RGPassType::Graphics, [swapchainHandle](RGPassBuilder &builder, EngineContext *) { builder.write_color(swapchainHandle, false, {}); }, [this, swapchainHandle](VkCommandBuffer cmd, const RGPassResources &res, EngineContext *ctx) { draw_imgui(cmd, ctx, res, swapchainHandle); }); } void ImGuiPass::draw_imgui(VkCommandBuffer cmd, EngineContext *context, const RGPassResources &resources, RGImageHandle targetHandle) const { EngineContext *ctxLocal = context ? context : _context; if (!ctxLocal) return; VkImageView targetImageView = resources.image_view(targetHandle); if (targetImageView == VK_NULL_HANDLE) return; // Dynamic rendering is handled by the RenderGraph; just render draw data. ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd); }