# Dear ImGui Backend Architecture: How the Core and Backend Layers Interact

> Explore Dear ImGui's backend architecture. Learn how its core UI logic interacts with platform-specific code through backend modules utilizing ImGuiIO and ImDrawData for seamless integration.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: architecture
- Published: 2026-07-25

---

**Dear ImGui separates its immediate-mode UI core from platform-specific code through a strict two-layer architecture where the core library handles widget logic while backend modules bridge to OS windows, input devices, and graphics APIs via `ImGuiIO` and `ImDrawData` structures.**

The architecture of Dear ImGui's backend system keeps the UI toolkit completely portable and rendering-agnostic. In the `ocornut/imgui` repository, the implementation splits into a platform-independent core located in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) and interchangeable backend modules housed in the `backends/` folder. This design allows developers to swap between Win32, GLFW, SDL2, OpenGL, DirectX, or Vulkan without touching the immediate-mode UI logic.

## The Two-Layer Architecture

### Core Library Responsibilities

The **core library** implements the immediate-mode UI paradigm, widget logic, memory management, and the public API. It maintains complete ignorance of windows, input hardware, or graphics APIs. According to the source code in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), the primary structures include:

- **`ImGuiContext`** – The main context containing all UI state
- **`ImGuiIO`** – Input/output interface between core and backends
- **`ImGuiPlatformIO`** – Platform abstraction for multi-viewport support
- **`ImDrawData`** – Render command lists generated by the core

### Backend Modules Structure

**Backend modules** live in the `backends/` folder and serve as the bridge between the core and the host environment. Each backend splits into two logical parts:

- **Platform Backend** – Handles mouse/keyboard/gamepad input, cursor shapes, timing, and multi-viewport window management
- **Renderer Backend** – Manages texture creation and translates `ImDrawData` into graphics API draw calls

Backend implementations follow a consistent naming convention: `ImGui_ImplXXX_Init`, `ImGui_ImplXXX_Shutdown`, `ImGui_ImplXXX_NewFrame`, and `ImGui_ImplXXX_RenderDrawData`.

## Core to Backend Communication

### Input and Display via ImGuiIO

The core polls the **`ImGuiIO`** structure each frame to read input state and display parameters. Platform backends populate this structure using helper calls such as `io.AddMousePosEvent()`, `io.AddKeyEvent()`, and `io.DeltaTime`. Backends advertise their capabilities by setting flags in `io.BackendFlags`, such as `ImGuiBackendFlags_HasMouseCursors` or `ImGuiBackendFlags_PlatformHasViewports`.

### Multi-Viewport via ImGuiPlatformIO

When multi-viewport support is enabled, the core uses **`ImGuiPlatformIO`** to request platform-specific actions like creating new OS windows or warping the mouse cursor. The backend signals support for these operations by setting `ImGuiBackendFlags_PlatformHasViewports` in the `ImGuiIO` flags field.

### Rendering via ImDrawData

After `ImGui::Render()` completes, the core produces **`ImDrawData`** containing vertex buffers, index buffers, and draw commands. The renderer backend receives this data via a call to `ImGui_ImplXXX_RenderDrawData(draw_data)` and translates it into API-specific commands such as DirectX draw calls or OpenGL vertex array rendering.

## Platform Backend Responsibilities

Platform backends handle all operating system interaction:

- **Input Conversion** – Transforming native events (Win32 messages, GLFW callbacks, SDL events) into `ImGuiIO` calls
- **Cursor Management** – Mapping `ImGuiMouseCursor` values to native OS cursor shapes
- **Timing** – Providing `io.DeltaTime` for frame timing calculations
- **Multi-Viewport** – Creating additional OS windows and forwarding focus events to the correct viewport when `ImGuiBackendFlags_PlatformHasViewports` is set

Typical implementation files include [`imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_win32.cpp), [`imgui_impl_glfw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_glfw.cpp), and [`imgui_impl_sdl2.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_sdl2.cpp). During initialization, the platform backend stores a pointer in `io.BackendPlatformUserData` and sets `io.BackendPlatformName` to identify itself.

## Renderer Backend Responsibilities

Renderer backends manage all graphics API interaction:

- **Texture Atlas** – Uploading font and GUI textures to GPU memory via functions like `ImGui_ImplXXX_CreateFontsTexture()`
- **Command Execution** – Iterating over `ImDrawData` to issue vertex/index buffer bindings and clipping rectangle commands
- **Custom Textures** – Optionally supporting `ImGuiBackendFlags_RendererHasTextures` for user-supplied images

Common implementations reside in [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp), [`imgui_impl_dx11.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_dx11.cpp), and [`imgui_impl_vulkan.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_vulkan.cpp). These backends set `io.BackendFlags` to indicate renderer-specific capabilities.

## Per-Frame Execution Flow

The architecture enforces a strict execution order each frame. The platform backend must update `ImGuiIO` before the core begins processing, while the renderer consumes output after the core finishes:

```cpp
// Platform: fill ImGuiIO before NewFrame
ImGui_ImplWin32_NewFrame();
ImGui_ImplOpenGL3_NewFrame();

// Core: prepare and process UI
ImGui::NewFrame();
ImGui::Begin("Demo Window");
ImGui::Text("Hello, backend!");
ImGui::End();

// Core: generate draw commands
ImGui::Render();

// Renderer: consume ImDrawData
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

```

*The platform backend runs **before** `ImGui::NewFrame()` to guarantee `io` data is current. The renderer backend runs **after** `ImGui::Render()` to consume the generated draw list.*

## Extending the Backend System

**Custom Backends** – You can implement only a platform layer, only a renderer, or both. The core does not care which backends you provide; it only checks the `io.BackendFlags` to determine available capabilities.

**Third-Party Bindings** – Language bindings for Python, Rust, or Unity use the same backend architecture. They expose the core API and forward native events to the standard `ImGuiIO` interface without modifying [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp).

## Summary

- Dear ImGui uses a strict two-layer architecture separating the portable core from platform-specific backends
- **`ImGuiIO`** serves as the primary communication channel for input and configuration
- **`ImDrawData`** carries render commands from the core to the graphics API
- Platform backends handle OS windows, input events, and timing; renderer backends handle GPU textures and draw calls
- Backends register capabilities via **`io.BackendFlags`** rather than through inheritance or virtual functions
- The execution flow requires platform setup before `NewFrame()` and rendering after `Render()`

## Frequently Asked Questions

### What is the difference between a platform backend and a renderer backend in Dear ImGui?

A **platform backend** manages operating system interaction—window creation, input polling, cursor shapes, and timing—while a **renderer backend** handles graphics API calls such as texture upload and drawing `ImDrawData` command lists. They are independent; you can pair a Win32 platform backend with an OpenGL renderer, or an SDL2 platform backend with a Vulkan renderer.

### How does Dear ImGui communicate input events from the OS to the UI core?

Platform backends translate native OS events (Win32 messages, GLFW callbacks, SDL events) into standardized calls on the **`ImGuiIO`** structure, such as `io.AddMousePosEvent()` and `io.AddKeyEvent()`. The core polls this structure during `ImGui::NewFrame()` to determine button states, keyboard focus, and mouse positions.

### Can I use a custom rendering API with Dear ImGui?

Yes. You only need to implement five functions: `Init`, `Shutdown`, `NewFrame`, `RenderDrawData`, and optionally `CreateFontsTexture`. Your implementation receives **`ImDrawData`** containing vertex buffers and draw commands, which you translate into your custom API's draw calls. Set the appropriate **`ImGuiBackendFlags`** in `io.BackendFlags` to advertise your capabilities to the core.

### Where can I find example implementations of Dear ImGui backends?

Official examples reside in the `backends/` folder ([`imgui_impl_win32.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_win32.cpp), [`imgui_impl_opengl3.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_impl_opengl3.cpp), etc.) and the `examples/` directory, such as [`examples/example_win32_opengl3/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_win32_opengl3/main.cpp). These demonstrate the proper initialization sequence and the per-frame call order required to wire platform and renderer backends together.