# How to Integrate Dear ImGui with Vulkan: Complete Backend Setup Guide

> Learn to integrate Dear ImGui with Vulkan. This guide provides a complete backend setup, detailing initialization and rendering for seamless UI integration in your Vulkan applications.

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

---

**To integrate Dear ImGui with Vulkan, populate the `ImGui_ImplVulkan_InitInfo` struct with your `VkInstance`, `VkDevice`, and render pass details, then call `ImGui_ImplVulkan_Init()` to initialize the backend and `ImGui_ImplVulkan_RenderDrawData()` each frame to render the UI.**

Dear ImGui provides a production-ready Vulkan renderer backend that plugs into any existing Vulkan application with minimal boilerplate. Understanding how to integrate Dear ImGui with Vulkan requires configuring the `imgui_impl_vulkan` backend from the **ocornut/imgui** repository, which manages vertex buffer uploads, descriptor pools, and pipeline state automatically using the files [`backends/imgui_impl_vulkan.h`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.h) and [`backends/imgui_impl_vulkan.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.cpp).

## Required Vulkan Context Setup

Before initializing ImGui, your application must create a valid Vulkan context. The backend requires specific handles passed through `ImGui_ImplVulkan_InitInfo`:

- **`VkInstance`** – Created with surface extensions (e.g., `VK_KHR_surface`)
- **`VkPhysicalDevice`** – Selected GPU supporting graphics queue families
- **`VkDevice`** – Logical device with graphics queue family enabled
- **`VkQueue`** – Graphics queue for command submission
- **`VkRenderPass`** – Defined in `PipelineInfoMain.RenderPass` (or use dynamic rendering)
- **`VkDescriptorPool`** – Optional; ImGui creates one internally if `DescriptorPoolSize > 0`

As implemented in [`backends/imgui_impl_vulkan.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.cpp), these handles allow the backend to allocate GPU resources and submit draw commands without managing your swap chain.

## Initializing the imgui_impl_vulkan Backend

The initialization sequence follows the pattern established in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp). First, include the backend headers:

```cpp
#include "imgui.h"
#include "imgui_impl_vulkan.h"
#include "imgui_impl_glfw.h"  // Replace with your platform backend

```

Next, populate the `ImGui_ImplVulkan_InitInfo` structure. Since version **2025-09-26**, render pass configuration moved into the `PipelineInfoMain` sub-struct:

```cpp
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance       = g_Instance;
init_info.PhysicalDevice = g_PhysicalDevice;
init_info.Device         = g_Device;
init_info.QueueFamily    = g_QueueFamily;
init_info.Queue          = g_Queue;
init_info.PipelineCache  = g_PipelineCache;      // Optional
init_info.DescriptorPool = g_DescriptorPool;     // Optional, or set DescriptorPoolSize
init_info.MinImageCount  = 2;                    // Minimum swap chain images
init_info.ImageCount     = wd->ImageCount;       // Swap chain image count
init_info.Allocator      = g_Allocator;          // Optional custom allocator

// Render pass configuration (required)
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 */ };

```

Initialize the platform backend first, then the Vulkan renderer:

```cpp
ImGui_ImplGlfw_InitForVulkan(window, true);
ImGui_ImplVulkan_Init(&init_info);

```

The backend lazily creates the font texture during the first call to `ImGui_ImplVulkan_NewFrame()`.

## Per-Frame Rendering Workflow

Each frame follows a strict sequence to synchronize platform input and Vulkan rendering. According to the implementation in [`backends/imgui_impl_vulkan.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.cpp), the workflow is:

```cpp
// 1. Start frame
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();  // Your platform backend
ImGui::NewFrame();

// 2. Build UI
ImGui::Begin("Vulkan Example");
ImGui::Text("Hello from Vulkan!");
ImGui::End();

// 3. Render
ImGui::Render();
ImDrawData* draw_data = ImGui::GetDrawData();

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 records draw commands into your provided command buffer, binding the internal graphics pipeline and descriptor sets automatically.

## Managing Custom Textures and Samplers

To display application textures within ImGui widgets, convert `VkImageView` handles to `ImTextureID` using the backend's descriptor set management:

```cpp
VkDescriptorSet tex_ds = ImGui_ImplVulkan_AddTexture(
    myImageView, 
    VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
);
ImTextureID my_texture = (ImTextureID)tex_ds;

// Use in UI
ImGui::Image(my_texture, ImVec2(256, 256));

```

When the texture is no longer needed, explicitly release the descriptor set:

```cpp
ImGui_ImplVulkan_RemoveTexture(tex_ds);

```

The backend maintains built-in linear and nearest samplers accessible through `ImGui_ImplVulkan_DrawCallback_SetSamplerLinear` and `ImGui_ImplVulkan_DrawCallback_SetSamplerNearest`, as 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 Resource Destruction

Proper shutdown prevents Vulkan validation errors and memory leaks. The sequence mirrors initialization in reverse:

```cpp
vkDeviceWaitIdle(g_Device);
ImGui_ImplVulkan_Shutdown();   // Destroys internal buffers, pipelines, and descriptor pools
ImGui_ImplGlfw_Shutdown();     // Platform-specific cleanup
ImGui::DestroyContext();

```

Calling `vkDeviceWaitIdle` before `ImGui_ImplVulkan_Shutdown()` ensures no pending command buffers reference the backend's vertex or index buffers.

## Summary

- **Prepare Vulkan context** with valid `VkInstance`, `VkDevice`, graphics `VkQueue`, and `VkRenderPass` before initialization.
- **Configure `ImGui_ImplVulkan_InitInfo`** using the `PipelineInfoMain` sub-struct for render pass details, updated since v2025-09-26.
- **Initialize platform first**, then call `ImGui_ImplVulkan_Init()` to create the renderer backend.
- **Render each frame** by calling `ImGui_ImplVulkan_NewFrame()`, building the UI, and submitting draw data via `ImGui_ImplVulkan_RenderDrawData()`.
- **Register custom textures** with `ImGui_ImplVulkan_AddTexture()` and clean up with `ImGui_ImplVulkan_RemoveTexture()`.
- **Shutdown properly** using `ImGui_ImplVulkan_Shutdown()` after waiting for device idle.

## Frequently Asked Questions

### What Vulkan extensions are required for Dear ImGui?

Dear ImGui's Vulkan backend requires only core Vulkan 1.0 functionality plus whatever extensions your surface provider needs (typically `VK_KHR_surface` and `VK_KHR_swapchain`). The backend does not require `VK_KHR_dynamic_rendering`, though it supports it if you prefer dynamic rendering over traditional render passes.

### Can I use Dear ImGui with Vulkan without GLFW or SDL?

Yes. While [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp) and [`examples/example_sdl2_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_sdl2_vulkan/main.cpp) demonstrate common windowing libraries, you can use the Win32 platform backend or create your own. The `imgui_impl_vulkan` backend is windowing-agnostic and only requires a valid `VkSurfaceKHR` and render pass setup, as shown in [`examples/example_win32_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_win32_vulkan/main.cpp).

### How do I handle window resizing with the Vulkan backend?

Window resizing requires recreating your swap chain and render pass. After resizing, update `ImGui_ImplVulkan_InitInfo::PipelineInfoMain.RenderPass` if your render pass handle changed, and ensure `MinImageCount` and `ImageCount` reflect the new swap chain configuration. The backend automatically handles buffer resizing internally during the next frame.

### Why does ImGui_ImplVulkan_Init fail with VK_ERROR_INITIALIZATION_FAILED?

This error typically indicates missing required fields in `ImGui_ImplVulkan_InitInfo`, particularly an invalid `QueueFamily` index or null `RenderPass` in `PipelineInfoMain`. Verify that your `VkDevice` was created with the graphics queue family specified in `QueueFamily`, and that `PipelineInfoMain.RenderPass` is a valid handle created for your swap chain's image format.