Hacker News new | ask | show | jobs
by amelius 1957 days ago
Yes, but immediate mode causes more CPU load (or draining of batteries) since you have to redraw everything all the time.
3 comments

It's easy to skip drawing frames when no state changes, and for frames where state does change, you can use techniques like rxi's cached software rendering to avoid redrawing the entire screen: https://rxi.github.io/cached_software_rendering.html
That doesn‘t seem too different anymore to the invalidate/paint paradigm of traditional UI frameworks (e.g. win32 GDI).
How does it handle scrolling? This is typically very fast and smooth (performed by bitblt and redrawing only the newly exposed part on every frame), but in immediate mode you'd have to redraw the entire screen on every frame.
I think this whole efficiency thing is a common misconception. Only the public API appears "immediate mode", the internal implementation doesn't need to be, and usually isn't (e.g. it keeps mutating state between frames instead of building everything from scratch again).

The user-side code basically describes what the UI should look like in the current frame, those "instructions" are recorded, and this recording is reasonably cheap.

The UI backend can then figure out how to "diff" the new instruction stream against the current internal state and render this with the least changes to the screen.

However some immediate mode UI systems came to the conclusion that it might actually be cheaper to just render most things from scratch instead of spending lots of processing resources to figure out what needs to be updated.

In conclusion: "Immediate Mode UI" doesn't say anything how the UI is actually rendered or generally how the internals are implemented, it only describes how the public API works.

Perhaps I should give a different example: a listbox filled with 1 million items, with a scrollbar.

If the public API requires you to give a new paint command on every frame (everytime the scrollbar is dragged), then regardless of whether the underlying rendering engine performs each of these paint commands, you still have to run through every item of the list (and so does the diff'ing code), making this a O(N) operation on every frame.

From what I've seen (in Dear ImGui), this is solved by not giving the 1 million items to the API, instead you can query what range of the list is currently visible, and only describe those to the API (in Dear ImGui this is called a ListClipper).

But I guess different UI frameworks have different solution for this. Creating and updating a 1 million item list wouldn't be a cheap operation in a traditional UI system either.

Ok. Yes my point is not that you can't find efficient ways around the limitations, but my fear is that you end up with a system that is less ergonomic in the end.
> Creating and updating a 1 million item list wouldn't be a cheap operation in a traditional UI system either.

IDK, works pretty well with Qt's item model system

It's not difficult to implement a 'virtual' list which renders only the items which are visible. It's a little trickier if your list items are not all the same height, but not impossible.
Modern renderers typically draw scrollable content into a separate texture (or collection of smaller textures that tile the scrollable region) and use the GPU to scroll rather than bitblting on the CPU. You can use the same technique to render the scrollable part of the UI in an immediate mode system.
> immediate mode causes more CPU load

Does it? Computers are FAST. Webdev stacks are many things, but it ain’t fast or performant.

Has anyone built a moderately complex UI in a good immediate mode UI and in a good retained UI? I’d be very curious to know the actual results.

What if you have your ‘immediate mode’ produce not a direct rendering of the GUI, but a virtual object model describing what the structure of the GUI should be at that moment? Then you diff that object model against the actual object model of the GUI and apply the changes....

That’s how react works. It’s effectively an ‘immediate mode’ abstraction above a component based UI.

That avoids the component connecting and wiring problems, and creates the simple determinism that makes immediate mode systems easier to reason about.