ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
61.11k stars 10.3k forks source link

Exploring Strategies for Optimizing ImGui Usage in an OS Context: Retained Mode, Direct Lua Calls, or a Custom DSL? #6697

Open MrManiacc opened 1 year ago

MrManiacc commented 1 year ago

Version/Branch of Dear ImGui:

Version: Latest, built from source 8/6/2023 Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_opengl3.cpp + imgui_impl_glfw.cpp Compiler: gcc (unrelated to issue) Operating System: Windows (unrelated to issue)

My Issue/Question:

My project, Vos, is an ambitious endeavor to create an embeddable operating system with a strong focus on modularity and extensibility. Drawing inspiration from tools like Visual Studio Code, Vos aims to deliver a powerful yet minimal core platform where most functionalities are provided by scripts.

This scripting system is designed around 'modules', each of which could serve as libraries or executables. These modules are intended to be portable and reusable, enabling developers to mix and match them to suit their needs. To facilitate sharing and collaboration, I'm planning to build an NPM-like centralized plugin repository where users can upload, download, and share their modules.

The project is still in its early stages, but it's important to note that this isn't my first foray into this space. I have previously developed a similar project in Java using ImGui Java bindings, available at this repository. Although the project was successful, I realized the need for a more direct control over memory and better library availability, leading me to migrate to C++ for Vos. Said project can be located

One of the key challenges I'm facing is how to efficiently leverage ImGui to render the UI in this OS-like context. ImGui's immediate mode design is well-suited for many scenarios, but for an application like Vos that requires a traditional, retained-mode UI model, there are some hurdles to overcome. Specifically, I've been considering three different strategies:

  1. Retained Mode Shell - The essence of this approach is creating a retained-mode wrapper around ImGui. This strategy would involve holding the GUI state in memory and calling ImGui only when a user event is triggered in the OS. This would allow the CPU to stay idle when no user input is happening, theoretically improving performance. However, I am concerned about the overhead this could introduce due to frequent switching between immediate and retained modes, and its potential impact on performance.
  2. Direct Lua Calls - This method involves making ImGui calls directly from Lua on a per-frame basis, leveraging ImGui's native immediate mode design. This option is simpler and more straightforward but fails to fully cater to the requirements of a retained-mode UI model in a complex, OS-like application.
  3. React-like Syntax - This experimental idea involves creating a domain-specific language (DSL) for ImGui that fuses elements from HTML and Lua. Using ANTLR, I've considered designing a JSX-like syntax that ultimately compiles down to raw ImGui calls. This approach would provide the benefits of a declarative syntax to describe the UI. However, this solution could potentially introduce complexity and maintenance challenges due to the need for a custom compiler. Furthermore, the performance implications of such an abstraction layer are uncertain. Although this is more of an implementation detail and potentially beyond the scope of this issue, it forms a part of the overall puzzle of optimizing ImGui's usage.

Screenshots/Video

Previous implementation done within java editor_new (project can be found here)

Current implementation in c++ with MVP lua implementation image

This issue is more so theory than an actual problem so please do let me know if there is a better location to pose this question.

okvik commented 1 year ago

Probably not entirely relevant to your design idea, but, for a mobile application where excessive battery usage from constant (and entirely needless) redrawing is a concern, I partially solved the problem by implementing a frame limiter that runs at 0.5 FPS in an idle state but releases the draw loop up to 30 FPS on any input and lets it run free for another N cycles so cross-frame state updates can be completed in time. For (non-UI) events that necessitate immediate UI update I simply pump a dummy event into the (in my case SDL2) queue.

It works reasonably well.