-
-
Notifications
You must be signed in to change notification settings - Fork 11.4k
Description
Version/Branch of Dear ImGui:
Version 2.XX
Back-ends:
any
Compiler, OS:
any
Full config/build information:
No response
Details:
Hi ocornut.
I am using your imGUI as a backup tool in a complex game engine, mostly for debuging and editors like a editor for a hybrid (immidate/retained) mode complex UI system (to avoid chicken-egg problem).
And was hit a performance\appearence issues in some cases. Not a huge problem, because this is an internal tools, but... if you decide to clean up you code and improve its architecture at some point... I want to share some experience, hope this could help.
My first UI system (written 15 years ago) was working like imGUI. Approx everything to triangles, batch and render the result each frame. That works. With problems related to performance and AA. So, I have started to investigate different options to solve this problems. If we restrict a solution space to the 'Immediate frontend' idiom, there are still ALOT of possible improvements. I can understand your design choices that are influencing the current state, but things are changing in time.
First of all, layouts and high-level draw call emitting should not be strongly coupled with fonts, textures and atlases. Fonts and images should be opaque abstract objects for the main front end logic. Because resource management is strictly defined by the backend (sizes, formats, capabilities, streaming) and could be incredibly complex in real cases. It's not possible, for ex, to use imGUI with something like win32 GDI, while it's still possible to implement even much more complex and rich dynamic immediate UI with it. Weakness just because of a data representation and low-level internals exposure to the frontend logic. This could be solved just by decomposition and refactoring, without changing anything internally. Yes, it's possible to reimplement DrawLists (and I have actually done this), but this is a huge pain in the current state.
Well, proper decoupling gives a chance to implement more low-level rendering paths. It's actually possible to draw everything in a single draw call (or two for proper blending). Just pack images and font glyphs in 2D array atlases, sort out opaque\transparent tris, pack clipping parameters along with transforms, and you do not need to switch any state. It's also possible to implement SDF rendering techniques to solve AA issues and reduce primitive count/generation cost. Just 8 triangles for a perfect AA circle instead of thousands (for a big circle) sin\cos in your case. Just a few triangles for spline paths closely approximated with arc fits instead of thousands of line segments for the same quality. One glyph for any font size. No need to bake anything and waste texture memory. This could be easily implemented and supported by almost any HW working these days.
Future improvements are possible in a command level. If we restrict a draw list operations to a high-level batches (sequences of parametric primitives that relate closely), we can cache primitive generator results by command parameters. Incremental hashes for the command stream comparsion, linear\tree allocators, ring buffers, and hash maps could make this pretty fast. While the immediate mode assumes highly dynamic content, temporal coherency is still HUGE, we could skip ALOT of work related to primitive generation, batching and uploading to GPU for nothing. We do not even need to batch everything each frame, just changed parts and then use MultiDrawElements.
It might look challenging for you to implement such a thing in the imGUI itself, but FMPOV it's a good idea to give an isolated interface for others. Because they could already have highly optimized and suited for its needs Font, Image, Atlas and PrimitiveDrawList classes...
Screenshots/Video:
No response