本页介绍了优化 Dear ImGui 应用程序以获得最佳运行时性能的技术。它概述了内置优化、配置选项和最佳实践,以在使用 Dear ImGui 时实现高效渲染并最大限度地减少 CPU/GPU 使用。
Dear ImGui 的设计将性能作为首要考虑因素。以下几个关键设计原则有助于其高效运行:
来源: imgui.cpp216-220
这些原则使 Dear ImGui 即使在具有复杂界面和大量 UI 元素的应用程序中也能保持良好的性能。
Dear ImGui 采用多种策略来最大限度地减少帧渲染期间的内存分配:
当渲染一个典型帧而没有创建新的窗口或小部件时:
来源: imgui.cpp217 imgui_internal.h357-358
Dear ImGui 中的内存主要用于:
| 组件 | 描述 | 优化 |
|---|---|---|
| 绘图缓冲区 | 用于渲染的顶点和索引缓冲区 | 采用增长策略预分配 |
| 窗口数据 | 窗口状态、内容和绘图命令 | 窗口被池化和重用 |
| 小部件状态 | 活动小部件数据和状态 | 帧之间保留最小状态 |
| 字体数据 | 字符字形和纹理图集 | 在所有上下文中共享 |
为避免性能问题,您应该:
PushID()/PopID() 而不是生成长字符串 ID来源: imgui.cpp214-220 imgui_internal.h352-358
Dear ImGui 通过批处理相似的绘图命令来优化渲染
具有相同纹理、剪裁矩形和属性的命令会自动批处理,以最大限度地减少绘制调用。
Dear ImGui 使用多种技术来避免渲染不可见内容:
ImGui 首先尝试消除不可见的整个小部件或窗口
BeginChild 只渲染可见项当内容必须部分剪裁时
对于大型列表或表格,使用 ImGuiListClipper 对性能至关重要
来源: imgui_widgets.cpp196-204 imgui_tables.cpp156-184
某些小部件比其他小部件更耗费性能
| 小部件 | 性能特征 | 优化技巧 |
|---|---|---|
| 基本小部件(按钮、文本等) | 非常高效 | 可安全大量使用 |
| 输入字段 | 激活时成本适中 | 限制屏幕上活动输入控件的数量 |
| 表格 | 多列时成本可能较高 | 使用剪裁和固定列宽 |
| 具有许多节点的树形结构 | 每个节点都有开销 | 使用剪裁和延迟加载 |
| 自定义渲染 | 取决于实现方式 | 最小化绘制调用和状态更改 |
布局计算在误用时可能开销很大
PushStyleVar()/PopStyleVar() 都需要重新计算来源: imgui_widgets.cpp266-321 imgui_tables.cpp156-184
表格可能占用大量性能,特别是当行和列很多时。使用以下策略进行优化:
对于具有许多行的表格,请始终使用 ImGuiListClipper
TableNextColumn() 的返回值以跳过处理隐藏列文本渲染可能是重要的性能因素。考虑以下优化措施:
ImGuiFreeType 以提高质量(会带来一定的性能开销)TextUnformatted()不同的渲染后端具有不同的性能特征
现代图形 API 的技巧
对于 OpenGL 后端
来源: examples/example_glfw_vulkan/main.cpp264-327
Dear ImGui 提供了多种工具来识别性能问题
指标窗口提供有价值的性能数据
ImGui::ShowMetricsWindow() 打开来源: imgui.cpp96-98
频繁创建/销毁窗口
ImGui::Begin("Window", nullptr, ImGuiWindowFlags_NoDecoration)热路径中的复杂格式化
TextUnformatted()深度嵌套的窗口/组
没有剪裁的大型表格
ImGuiListClipper使用不同 ID 重新创建相同 UI
低效的 ID 栈使用
PushID(int) 而不是字符串 ID过多的样式更改
PushStyleVar()/PopStyleVar() 调用不检查可见性
过多的绘制回调
过度使用自动调整大小
来源: imgui.cpp214-221 imgui_tables.cpp156-184 docs/TODO.txt52-108
优化 Dear ImGui 应用程序涉及:
当这些原则正确应用时,Dear ImGui 可以轻松处理包含数千个元素的复杂界面,同时保持出色的性能。