How to Integrate Dear ImGui with Vulkan Using imgui_impl_vulkan
To integrate Dear ImGui with Vulkan, populate the ImGui_ImplVulkan_InitInfo structure with your Vulkan instance, device, queue, and render pass details, then call ImGui_ImplVulkan_Init() after initializing your platform backend.
Dear ImGui provides a production-ready Vulkan renderer backend through imgui_impl_vulkan.* that handles vertex buffers, descriptor pools, and pipeline management. This implementation lives in the ocornut/imgui repository and requires only a valid Vulkan context to begin rendering immediate-mode UI in your application.
Prerequisites: Required Vulkan Context
Before calling any ImGui Vulkan functions, your application must initialize a complete Vulkan context. The backend does not create these objects for you.
- VkInstance: Created with necessary surface extensions (e.g.,
VK_KHR_surface,VK_KHR_swapchain). Passed toImGui_ImplVulkan_InitInfo::Instance. - VkPhysicalDevice: Selected GPU supporting required queue families. Stored in
PhysicalDevice. - VkDevice: Logical device with graphics queue family enabled. Stored in
Device. - VkQueue: Graphics queue for command buffer submission. Stored in
Queue. - VkDescriptorPool: Either create one manually or set
DescriptorPoolSize > 0to let ImGui create it automatically. - Render Pass Configuration: Either a
VkRenderPassor dynamic rendering setup viaVK_KHR_dynamic_rendering, configured inPipelineInfoMain.
Optional fields include VkPipelineCache for pipeline creation caching and VkAllocationCallbacks for custom memory allocation.
Configuring ImGui_ImplVulkan_InitInfo
The ImGui_ImplVulkan_InitInfo structure declared in backends/imgui_impl_vulkan.h is the primary configuration interface. Fill all mandatory fields before initialization:
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = g_Instance; // Your VkInstance
init_info.PhysicalDevice = g_PhysicalDevice; // Selected GPU
init_info.Device = g_Device; // Logical device
init_info.QueueFamily = g_QueueFamily; // Graphics queue family index
init_info.Queue = g_Queue; // Graphics queue handle
init_info.PipelineCache = g_PipelineCache; // Optional: VK_NULL_HANDLE allowed
init_info.DescriptorPool = g_DescriptorPool; // Optional: set 0 to auto-create
init_info.MinImageCount = g_MinImageCount; // Must be >= 2
init_info.ImageCount = wd->ImageCount; // Swap-chain image count
init_info.Allocator = g_Allocator; // Optional: custom allocator
// Render pass configuration (moved to PipelineInfoMain since v2025-09-26)
init_info.PipelineInfoMain.RenderPass = wd->RenderPass;
init_info.PipelineInfoMain.Subpass = 0;
init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
// Optional error callback
init_info.CheckVkResultFn = [](VkResult err){ /* handle error */ };
Note that RenderPass, Subpass, and MSAASamples moved into the PipelineInfoMain sub-structure in recent versions. Check the changelog comments in backends/imgui_impl_vulkan.h for migration details.
Initialization Sequence
Initialize your platform backend first, then the Vulkan renderer. The backend creates its font texture automatically during the first frame.
// 1. Platform backend (GLFW, SDL, Win32, etc.)
ImGui_ImplGlfw_InitForVulkan(window, true); // Replace with your platform
// 2. Vulkan renderer backend
ImGui_ImplVulkan_Init(&init_info);
Reference implementations in examples/example_glfw_vulkan/main.cpp, examples/example_sdl2_vulkan/main.cpp, and examples/example_win32_vulkan/main.cpp demonstrate complete setup sequences for different windowing systems. The helper functions prefixed with ImGui_ImplVulkanH_* used in these examples are convenience utilities for the examples and are not required for your own engine integration.
Per-Frame Rendering Workflow
Each frame requires coordinated calls between the platform and Vulkan backends:
// Start frame
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame(); // Your platform backend
ImGui::NewFrame();
// Build UI
ImGui::Begin("Vulkan Demo");
ImGui::Text("Rendering with imgui_impl_vulkan");
ImGui::End();
// Render
ImGui::Render();
ImDrawData* draw_data = ImGui::GetDrawData();
// Submit draw data (skip if minimized)
if (draw_data->DisplaySize.x > 0.0f && draw_data->DisplaySize.y > 0.0f)
{
VkCommandBuffer cmd = /* your command buffer */;
ImGui_ImplVulkan_RenderDrawData(draw_data, cmd, VK_NULL_HANDLE);
}
The ImGui_ImplVulkan_RenderDrawData() function recorded in backends/imgui_impl_vulkan.cpp handles vertex/index buffer uploads and pipeline binding. Pass VK_NULL_HANDLE for the pipeline parameter to use the backend's built-in pipeline, or provide your own compatible pipeline handle.
Managing Custom Textures
Register application textures for use in ImGui widgets via descriptor sets:
// Register texture
VkDescriptorSet tex_id = ImGui_ImplVulkan_AddTexture(
myImageView,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
);
// Use in UI
ImGui::Image((ImTextureID)tex_id, ImVec2(256, 256));
// Cleanup when done
ImGui_ImplVulkan_RemoveTexture(tex_id);
The backend maintains built-in linear and nearest samplers accessible through ImGui_ImplVulkan_DrawCallback_SetSamplerLinear and ImGui_ImplVulkan_DrawCallback_SetSamplerNearest callbacks defined around lines 340-350 in backends/imgui_impl_vulkan.cpp.
Cleanup and Shutdown
Proper shutdown order ensures Vulkan object destruction occurs while the device is idle:
vkDeviceWaitIdle(g_Device);
ImGui_ImplVulkan_Shutdown(); // Destroys internal buffers, pipelines, descriptor sets
ImGui_ImplGlfw_Shutdown(); // Platform-specific cleanup
ImGui::DestroyContext();
The ImGui_ImplVulkan_Shutdown() function destroys all internal Vulkan objects including font textures and descriptor pools created during initialization.
Summary
- Prepare Vulkan context: Ensure valid
VkInstance,VkDevice,VkQueue, and render pass exist before initialization. - Configure InitInfo: Populate
ImGui_ImplVulkan_InitInfowith device handles andPipelineInfoMainrender pass details. - Initialize in order: Platform backend first, then
ImGui_ImplVulkan_Init(). - Frame loop: Call
ImGui_ImplVulkan_NewFrame(), build UI, thenImGui_ImplVulkan_RenderDrawData()with your command buffer. - Texture management: Use
ImGui_ImplVulkan_AddTexture()to bindVkImageViewobjects for UI rendering. - Shutdown cleanly: Call
ImGui_ImplVulkan_Shutdown()after device idle wait to prevent validation errors.
Frequently Asked Questions
What Vulkan version does imgui_impl_vulkan require?
The backend targets Vulkan 1.0 as a baseline but supports optional extensions like VK_KHR_dynamic_rendering for modern rendering paths. Ensure your physical device supports the queue families and extensions you enable in your VkInstance and VkDevice creation.
Can I use dynamic rendering instead of VkRenderPass?
Yes. Since recent updates, imgui_impl_vulkan supports VK_KHR_dynamic_rendering. Leave PipelineInfoMain.RenderPass as VK_NULL_HANDLE and ensure your VkDevice was created with the dynamic rendering extension enabled. The backend detects this configuration and omits render pass compatibility checks.
How do I handle high-DPI or multi-viewport rendering?
The backend automatically handles DPI scaling through ImGui's io.DisplayFramebufferScale. For multi-viewport support (floating ImGui windows outside the main platform window), enable ImGuiConfigFlags_ViewportsEnable in ImGuiIO::ConfigFlags and ensure your Vulkan swap-chain creation code in the platform backend supports multiple window surfaces.
Why is my font texture not appearing?
The font texture uploads during the first call to ImGui_ImplVulkan_NewFrame() if ImGui_ImplVulkan_Init() succeeded. Ensure your MinImageCount is at least 2 and matches your swap-chain configuration. If using a custom VkDescriptorPool, verify it has enough sets and descriptor types (combined image samplers) allocated for the font texture plus your custom textures.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →