Immediate Mode GUI vs Retained Mode GUI: Architectural Differences Explained
Immediate mode GUI (IMGUI) rebuilds the entire interface every frame directly from application code with minimal state retention, while retained mode GUI maintains a persistent widget tree that requires explicit updates and state synchronization.
Dear ImGui (ocornut/imgui) is a mature C++ implementation of the immediate mode GUI paradigm designed for game development tools and real-time debugging interfaces. Unlike traditional widget toolkits that rely on persistent scene graphs, Dear ImGui minimizes superfluous state duplication by reconstructing the UI each frame as described in docs/README.md (lines 99-102). Understanding these architectural differences helps developers choose between straightforward procedural UI code and complex event-driven widget hierarchies.
Core Philosophy of Immediate Mode GUI
According to the Dear ImGui documentation in docs/README.md (lines 99-102), the immediate mode GUI paradigm minimizes superfluous state duplication, state synchronization, and state retention from the user's point of view. In this model, the application code describes the interface procedurally on every update rather than modifying persistent objects.
The docs/FAQ.md file (lines 1000-1012) provides a direct comparison: while Dear ImGui "issues UI on every update," retained mode systems "issue UI once then later modify." This fundamental distinction eliminates the need for complex observer patterns and data binding layers.
Architectural Differences: Immediate Mode GUI vs Retained Mode GUI
UI Lifecycle and State Ownership
In immediate mode, widgets exist only for the duration of the frame. The programmer calls functions like ImGui::Button() and ImGui::SliderFloat() inside the main loop, passing application state directly.
Retained mode creates persistent objects during initialization. The toolkit stores widget properties internally, requiring the application to synchronize state through getters, setters, or signal/slot mechanisms.
Memory Footprint and Performance Model
Dear ImGui maintains a minimal footprint, keeping only transient command buffers and small internal caches in imgui.cpp. This architecture optimizes for the "worst case" scenario where UI changes frequently.
Retained mode systems carry the overhead of an entire widget tree, style data, and layout caches. They optimize for the "steady case" where UI remains static, but incur costs when rebuilding hierarchies or updating properties.
Code Locality and Debugging
Immediate mode colocates UI logic, layout, and data binding in procedural code within the render loop. This makes the code path easy to follow and modify, as seen in imgui_demo.cpp where ImGui::ShowDemoWindow() constructs the entire interface procedurally.
Retained mode often splits UI definition across multiple files or markup languages (QML, XAML), requiring developers to understand widget hierarchies and signal/slot mechanisms. Custom extensions typically require subclassing and complex event wiring.
Code Comparison: Immediate vs Retained Implementation
The following Dear ImGui example from examples/example_glfw_opengl3/main.cpp demonstrates the immediate mode approach, where UI construction and logic occur together in the frame loop:
// Executed every frame
ImGui::Begin("Demo Window");
if (ImGui::Button("Save")) {
SaveCurrentState();
}
ImGui::SliderFloat("Speed", &g_speed, 0.0f, 10.0f);
ImGui::End();
In contrast, retained mode toolkits like Qt instantiate objects once and manage their lifecycle separately:
// Initialization code runs once
QWidget *window = new QWidget;
QPushButton *saveButton = new QPushButton("Save", window);
QObject::connect(saveButton, &QPushButton::clicked, [](){ SaveCurrentState(); });
QSlider *speedSlider = new QSlider(Qt::Horizontal, window);
speedSlider->setRange(0, 100);
QObject::connect(speedSlider, &QSlider::valueChanged, [](int v){
g_speed = v / 10.0f;
});
Notice how the ImGui example places UI creation and logic together in the rendering loop, while the Qt example separates widget creation from event handling via signals and slots.
Dear ImGui Implementation Files
The repository structure reflects the immediate mode architecture through specific files:
imgui.handimgui.cpp: Core implementation defining stateless widget calls likeImGui::Begin()and transient window management.backends/imgui_impl_glfw.cpp: Translates platform input/events into ImGui commands without retaining widget state between frames.backends/imgui_impl_opengl3.cpp: Renders draw lists generated fresh each frame by the core library.imgui_demo.cpp: ContainsImGui::ShowDemoWindow(), demonstrating complex procedural UI construction without persistent scene graphs.examples/example_glfw_opengl3/main.cpp: Provides a minimal example tying the GLFW backend and the ImGui core together in a per-frame reconstruction pattern.
Summary
- Immediate mode GUI reconstructs the interface every frame, storing no persistent widget tree in
imgui.cppand minimizing state synchronization. - Retained mode GUI creates objects once, maintaining hierarchical state in a scene graph that requires explicit updates and event handling.
- Dear ImGui implements immediate mode through transient command buffers and stateless API calls like
ImGui::Button(). - Immediate mode excels for tools, debug panels, and dynamic layouts where code locality and flexibility matter, while retained mode suits complex desktop applications requiring stable hierarchies and rich styling.
Frequently Asked Questions
Can immediate mode GUI handle complex user interfaces?
Yes. Dear ImGui powers full-featured level editors and debugging tools in major game engines. While the paradigm differs from desktop application frameworks, imgui_demo.cpp demonstrates sophisticated layouts including docking, tab bars, and property editors. The absence of a persistent scene graph actually simplifies handling highly dynamic interfaces that change based on runtime data.
How does immediate mode GUI manage widget state without retention?
State lives entirely in the application variables passed by reference. When calling ImGui::SliderFloat("Speed", &g_speed, 0.0f, 10.0f), Dear ImGui reads and writes directly to g_speed. The library maintains only temporary draw commands and input handling state in internal caches, not widget properties, as implemented in imgui.cpp.
What are the main drawbacks of retained mode GUI?
Retained mode requires careful state synchronization between the application and the widget tree. Developers must handle widget lifecycle management, explicit layout updates, and signal/slot wiring. As noted in the docs/FAQ.md comparison (lines 1000-1012), this introduces superfluous state duplication and synchronization overhead that immediate mode eliminates.
Is Dear ImGui suitable for general-purpose applications?
Dear ImGui targets tools and real-time debugging interfaces rather than end-user applications requiring OS-native styling. While it compiles for consoles, mobile, and web with no external dependencies, its immediate mode nature means users must implement their own persistence for complex form workflows. Traditional retained mode frameworks handle such persistence automatically through their widget hierarchies.
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 →