# How to Integrate ImGui with Vulkan Validation Layers: Complete Setup Guide

> Integrate ImGui with Vulkan validation layers by defining APP_USE_VULKAN_DEBUG_REPORT, enabling the KHRONOS_validation layer, and registering a VkDebugReportCallbackEXT for error reporting.

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

---

**To integrate ImGui with Vulkan validation layers, define the `APP_USE_VULKAN_DEBUG_REPORT` macro before including the backend headers, enable the `VK_LAYER_KHRONOS_validation` layer in your `VkInstanceCreateInfo`, and register a `VkDebugReportCallbackEXT` to capture and print validation messages to your output stream.**

Dear ImGui's Vulkan backend (`imgui_impl_vulkan.h/cpp`) is deliberately engineered to remain agnostic of engine-specific initialization code, which means validation layer setup happens in your application layer, not inside ImGui itself. By following the reference implementation in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp), you can integrate ImGui with Vulkan validation layers to catch API misuse and synchronization errors during development.

## Understanding the Validation Layer Architecture

### The APP_USE_VULKAN_DEBUG_REPORT Control Macro

The official Vulkan example uses a conditional compilation flag to toggle validation code. When `APP_USE_VULKAN_DEBUG_REPORT` is defined, the example code in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp) (lines 19-27) injects the Khronos validation layer and debug report extension into the instance creation process.

### Key Source Files for Reference

According to the `ocornut/imgui` repository structure, these files contain the relevant implementation details:

- **[`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp)**: Contains the complete validation layer setup in the `SetupVulkan()` function (lines 119-146)
- **[`backends/imgui_impl_vulkan.h`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.h)**: Backend API declarations that accept externally created Vulkan objects
- **[`backends/imgui_impl_vulkan.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.cpp)**: Backend implementation that assumes your instance is already configured with desired layers

## Step-by-Step Integration

### 1. Define the Validation Layer Macro

Before including any ImGui headers, define the macro to enable the validation code path:

```cpp
#define APP_USE_VULKAN_DEBUG_REPORT
#include "imgui.h"
#include "imgui_impl_vulkan.h"

```

Alternatively, pass it as a compiler flag: `-DAPP_USE_VULKAN_DEBUG_REPORT`.

### 2. Configure Instance Creation with Validation Layers

In your `VkInstanceCreateInfo` structure, populate the layer and extension arrays when the macro is defined. This code mirrors the implementation in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp) (lines 119-125):

```cpp
VkInstanceCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;

#ifdef APP_USE_VULKAN_DEBUG_REPORT
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
create_info.enabledLayerCount = 1;
create_info.ppEnabledLayerNames = layers;
instance_extensions.push_back("VK_EXT_debug_report");
#endif

create_info.enabledExtensionCount = (uint32_t)instance_extensions.size();
create_info.ppEnabledExtensionNames = instance_extensions.data();

```

### 3. Register the Debug Report Callback

After creating the Vulkan instance, load the debug report function pointer dynamically and create the callback. The example in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp) (lines 136-147) demonstrates this pattern:

```cpp
#ifdef APP_USE_VULKAN_DEBUG_REPORT
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)
    vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");

VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 
                        VK_DEBUG_REPORT_WARNING_BIT_EXT | 
                        VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
debug_report_ci.pfnCallback = debug_report;  // Your callback function

vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, 
                               g_Allocator, &g_DebugReport);
#endif

```

### 4. Implement the Callback Function

The callback receives validation messages and routes them to your logging system:

```cpp
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(
    VkDebugReportFlagsEXT flags, 
    VkDebugReportObjectTypeEXT objectType, 
    uint64_t object, 
    size_t location, 
    int32_t messageCode, 
    const char* pLayerPrefix, 
    const char* pMessage, 
    void* pUserData)
{
    fprintf(stderr, "[VULKAN][%s] %s\n", 
            (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) ? "ERROR" : 
            (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT) ? "WARN" : "INFO", 
            pMessage);
    return VK_FALSE;
}

```

### 5. Clean Up Resources During Shutdown

During application shutdown, destroy the callback to prevent validation layer leaks. The `CleanupVulkan()` function in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp) (lines 49-53) shows the proper teardown:

```cpp
#ifdef APP_USE_VULKAN_DEBUG_REPORT
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)
    vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
if (vkDestroyDebugReportCallbackEXT)
    vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
#endif

```

## Complete Working Example

Here is a minimal, runnable integration that combines all steps:

```cpp
#define APP_USE_VULKAN_DEBUG_REPORT
#include "imgui.h"
#include "imgui_impl_vulkan.h"
#include <vulkan/vulkan.h>
#include <stdio.h>

static VkInstance g_Instance = VK_NULL_HANDLE;
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
static VkAllocationCallbacks* g_Allocator = nullptr;

static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(
    VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT, uint64_t,
    size_t, int32_t, const char*, const char* pMessage, void*)
{
    fprintf(stderr, "[VALIDATION] %s\n", pMessage);
    return VK_FALSE;
}

void SetupVulkanWithValidation(ImVector<const char*> extensions)
{
    VkInstanceCreateInfo ci = {};
    ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    
#ifdef APP_USE_VULKAN_DEBUG_REPORT
    const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
    ci.enabledLayerCount = 1;
    ci.ppEnabledLayerNames = layers;
    extensions.push_back("VK_EXT_debug_report");
#endif

    ci.enabledExtensionCount = (uint32_t)extensions.Size;
    ci.ppEnabledExtensionNames = extensions.Data;
    
    vkCreateInstance(&ci, g_Allocator, &g_Instance);
    
#ifdef APP_USE_VULKAN_DEBUG_REPORT
    auto f_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)
        vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
    
    VkDebugReportCallbackCreateInfoEXT drci = {};
    drci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
    drci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 
                 VK_DEBUG_REPORT_WARNING_BIT_EXT;
    drci.pfnCallback = debug_report;
    
    f_vkCreateDebugReportCallbackEXT(g_Instance, &drci, g_Allocator, &g_DebugReport);
#endif
}

```

## Summary

- **Define `APP_USE_VULKAN_DEBUG_REPORT`** before including ImGui headers to enable validation code paths in your application
- **Add `VK_LAYER_KHRONOS_validation`** to `VkInstanceCreateInfo::ppEnabledLayerNames` during instance creation to activate the validation layer
- **Load `vkCreateDebugReportCallbackEXT`** via `vkGetInstanceProcAddr` and register your callback to receive validation messages
- **Include `VK_EXT_debug_report`** in your instance extensions array to enable the debug reporting extension
- **Destroy the callback** using `vkDestroyDebugReportCallbackEXT` during application shutdown to prevent resource leaks

## Frequently Asked Questions

### Does ImGui automatically enable Vulkan validation layers?

No. According to the `ocornut/imgui` source code in [`backends/imgui_impl_vulkan.cpp`](https://github.com/ocornut/imgui/blob/main/backends/imgui_impl_vulkan.cpp), the backend assumes you have already created and configured the Vulkan instance. Validation layers must be enabled in your application code before initializing ImGui, as demonstrated in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp).

### What's the difference between VK_EXT_debug_report and VK_EXT_debug_utils?

`VK_EXT_debug_report` is the older extension used in the ImGui examples, while `VK_EXT_debug_utils` provides richer functionality in newer Vulkan SDKs. The example in [`examples/example_glfw_vulkan/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_glfw_vulkan/main.cpp) uses `debug_report` for compatibility, but you can upgrade to `debug_utils` by using `VkDebugUtilsMessengerEXT` and `vkCreateDebugUtilsMessengerEXT` instead.

### Why aren't validation errors appearing even after following these steps?

Ensure that the Vulkan SDK is installed and that your system's `VK_LAYER_PATH` environment variable points to the SDK layer binaries. Additionally, verify that `APP_USE_VULKAN_DEBUG_REPORT` is defined in all translation units that include the initialization code, or pass it as a compiler flag (e.g., `-DAPP_USE_VULKAN_DEBUG_REPORT`).

### Where should I define APP_USE_VULKAN_DEBUG_REPORT in a CMake project?

Define it in your CMakeLists.txt or as a preprocessor definition in your build system: `target_compile_definitions(your_app PRIVATE APP_USE_VULKAN_DEBUG_REPORT)`. This ensures the macro is visible throughout your codebase, matching the pattern used in the official ImGui examples.