# How to Integrate Dear ImGui with Vulkan Using imgui_impl_vulkan

> Integrate Dear ImGui with Vulkan using imgui_impl_vulkan. Learn to populate ImGui_ImplVulkan_InitInfo and call ImGui_ImplVulkan_Init with your Vulkan details for seamless UI integration.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-18

---

**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](https://github.com/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 to `ImGui_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 > 0` to let ImGui create it automatically.
- **Render Pass Configuration**: Either a `VkRenderPass` or dynamic rendering setup via `VK_KHR_dynamic_rendering`, configured in `PipelineInfoMain`.

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`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.h) is the primary configuration interface. Fill all mandatory fields before initialization:

```cpp
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`](https://github.com/ocornut/imgui/blob/main/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.

```cpp
// 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`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp), [`examples/example_sdl2_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_sdl2_vulkan/main.cpp), and [`examples/example_win32_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/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:

```cpp
// 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`](https://github.com/ocornut/imgui/blob/main/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:

```cpp
// 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`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.cpp).

## Cleanup and Shutdown

Proper shutdown order ensures Vulkan object destruction occurs while the device is idle:

```cpp
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_InitInfo` with device handles and `PipelineInfoMain` render pass details.
- **Initialize in order**: Platform backend first, then `ImGui_ImplVulkan_Init()`.
- **Frame loop**: Call `ImGui_ImplVulkan_NewFrame()`, build UI, then `ImGui_ImplVulkan_RenderDrawData()` with your command buffer.
- **Texture management**: Use `ImGui_ImplVulkan_AddTexture()` to bind `VkImageView` objects 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.