How to Use Dear ImGui for Debugging in Games: Built-in Tools and Techniques
Dear ImGui provides built-in debugging utilities accessible through ImGuiIO configuration flags, debug windows, and debugger visualizers that allow runtime inspection of UI state without external dependencies.
Dear ImGui is an immediate-mode graphical user interface library widely used for creating debug interfaces in game development. When integrating Dear ImGui debugging into your game engine, you gain access to a comprehensive suite of runtime inspection tools that visualize draw calls, track widget hierarchies, and trigger breakpoints directly from the UI. These features require no additional libraries and are implemented entirely within the ImGui source tree, making them ideal for rapid iteration during development.
Enabling Debug Mode Features in ImGuiIO
Before accessing debug windows, you must configure the ImGuiIO structure during initialization. The library exposes several boolean flags that activate specific debugging capabilities.
Set these flags immediately after calling ImGui::CreateContext():
ImGuiIO& io = ImGui::GetIO();
io.ConfigDebugIsDebuggerPresent = true; // Indicates a debugger is attached
io.ConfigDebugShowMetrics = true; // Enables the Metrics/Debugger window
io.ConfigDebugShowDebugLog = true; // Enables the Debug Log window
io.ConfigDebugShowIdStackTool = true; // Enables the ID Stack Tool window
These configuration options are declared in imgui.h around lines 2510-2535. The ConfigDebugIsDebuggerPresent flag is particularly important because it enables the Item Picker functionality to safely trigger breakpoints when a debugger is attached.
Accessing Built-in Debug Windows
The fastest way to access debugging tools is through ImGui::ShowDemoWindow(), which contains a dedicated Debug menu. The implementation in imgui_demo.cpp (lines 714-730) provides toggle buttons for all major debug interfaces.
static bool show_demo = true;
ImGui::ShowDemoWindow(&show_demo);
Alternatively, you can invoke specific debug windows directly using the following functions:
ImGui::ShowMetricsWindow()– Displays draw-list statistics and window hierarchyImGui::ShowDebugLogWindow()– Shows internal ImGui logging outputImGui::ShowIDStackToolWindow()– Visualizes the ID stack for the current widgetImGui::ShowStackToolWindow()– (Legacy alias) Same as above
Metrics and Debugger Window
The Metrics/Debugger window visualizes per-frame statistics including draw-call count, vertex count, texture bindings, and window hierarchy. This tool updates through the ImGui::UpdateDebugTools() function in imgui.cpp, providing real-time feedback on UI performance. Use this window to identify bottlenecks such as excessive ImDrawList allocations or unnecessary texture switches that impact your game's frame rate.
Debug Log Window
The Debug Log captures internal ImGui warnings and errors, including layout violations and ID conflicts. Entries are added via the IMGUI_DEBUG_LOG macro defined in imgui_internal.h. You can filter messages by category and severity, making it invaluable for tracking down subtle layout bugs that only appear at specific resolutions or scaling factors.
ID Stack Tool
Every ImGui widget generates a unique identifier based on its position in the window hierarchy. The ID Stack Tool displays the current stack of IDs, helping you diagnose why IsItemHovered() or IsItemClicked() returns unexpected values. This is essential when debugging complex nested menus or dynamically generated UI elements where label collisions might occur.
Item Picker and Debugger Breakpoints
The Item Picker adds a small button (🪤) next to widgets in the demo window that triggers IM_DEBUG_BREAK() when clicked. This macro expands to platform-specific breakpoints: __debugbreak() on MSVC, __builtin_debugtrap() on GCC/Clang, or a user-defined handler. The implementation resides in imgui_demo.cpp around lines 560-585.
When ConfigDebugIsDebuggerPresent is true, clicking the picker immediately pauses execution, allowing you to inspect the ImGui context (GImGui) and call stack. This provides one-click debugging without manually setting breakpoints in your IDE.
Debugger Integration and Visualizers
To improve debugging experience in popular IDEs, Dear ImGui ships with custom visualizer files in the misc/debuggers/ directory:
misc/debuggers/imgui.natvis– Visual Studio native visualizer forImVector,ImGuiWindow, and other containersmisc/debuggers/imgui.gdb– GDB pretty-printer definitions for ImGui typesmisc/debuggers/imgui_lldb.py– LLDB synthetic children and summaries for ImGui structures
Load the appropriate file into your debugger configuration to view ImGui containers as readable arrays rather than raw memory pointers. This makes inspecting the draw list or window stack significantly easier during breakpoint sessions.
Runtime Assertions and Custom Debugging
ImGui defines assertion macros in imgui_internal.h (lines 315-330) that you can leverage in your own code:
IM_ASSERT(condition)– Triggers a breakpoint if the condition failsIM_DEBUG_BREAK()– Unconditionally breaks into the debuggerIMGUI_DEBUG_LOG(format, ...)– Writes formatted messages to the debug log
Sprinkle IM_ASSERT throughout your rendering code to catch illegal states early, such as calling ImGui functions before NewFrame() or modifying draw lists after Render(). When an assertion triggers, you can inspect the global context GImGui to examine the current window, draw list, and frame state.
Complete Implementation Example
The following example demonstrates initializing ImGui with full debugging support and rendering the debug windows alongside your game UI:
// Initialization
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigDebugIsDebuggerPresent = true;
io.ConfigDebugShowMetrics = true;
io.ConfigDebugShowDebugLog = true;
// Main game loop
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Your game UI
ImGui::Begin("Game HUD");
ImGui::Text("FPS: %.1f", ImGui::GetIO().Framerate);
if (ImGui::Button("Trigger Event"))
{
// Game logic
}
ImGui::End();
// Debug windows
static bool show_demo = true;
static bool show_metrics = true;
static bool show_debug_log = true;
ImGui::ShowDemoWindow(&show_demo);
ImGui::ShowMetricsWindow(&show_metrics);
ImGui::ShowDebugLogWindow(&show_debug_log);
ImGui::Render();
// Rendering code...
}
Summary
- Enable debug flags in
ImGuiIOduring initialization to activateConfigDebugShowMetrics,ConfigDebugShowDebugLog, andConfigDebugIsDebuggerPresent - Use
ShowDemoWindow()to access the Debug menu, or call specific debug window functions directly - Leverage the Item Picker to break into your debugger with a single click when
ConfigDebugIsDebuggerPresentis enabled - Install debugger visualizers from
misc/debuggers/to inspect ImGui containers in Visual Studio, GDB, or LLDB - Utilize
IM_ASSERTandIM_DEBUG_BREAK()for runtime validation and immediate breakpoint triggers
Frequently Asked Questions
How do I view the ID stack for a specific widget in Dear ImGui?
Open the ID Stack Tool window via ImGui::ShowIDStackToolWindow() or through the Debug menu in the demo window. Hover over any widget to see its complete ID hierarchy in the tool window, which helps resolve ID collisions and understand why input queries fail.
Can I use Dear ImGui debugging tools in a release build?
While possible, it is not recommended. Debug features like ConfigDebugIsDebuggerPresent and the Item Picker are designed for development. The IM_ASSERT macros typically compile to nothing in release builds (unless you override IM_ASSERT), and debug windows add CPU overhead by tracking detailed statistics.
Where are the debugger visualizer files located in the ImGui repository?
Platform-specific debugger files reside in misc/debuggers/. Use imgui.natvis for Visual Studio, imgui.gdb for GDB, and imgui_lldb.py for LLDB. These files provide custom visualizations for ImVector, ImDrawList, and other internal structures.
What is the difference between IM_ASSERT and IM_DEBUG_BREAK?
IM_ASSERT(condition) checks a condition and breaks only if it fails, similar to standard assert macros. IM_DEBUG_BREAK() unconditionally triggers a debugger breakpoint regardless of state. Both are defined in imgui_internal.h and map to platform-specific breakpoint instructions.
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 →