Live data from Hacker News

Leveraging Rust and the GPU to render user interfaces at 120 FPS

zed.dev

131–140 of 212 posts

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#131

"Inspired by the gaming world, we realized that the only way to achieve the performance we needed was to build our own UI framework" I'm surprised you did not look at "Dear ImGui", "Noesis", and "JUCE". All three of them are heavily used in gaming, are rather clean C++, use full GPU acceleration, and have visual editors available. Especially JUCE is used for A LOT of hard-realtime professional audio applications. "Wh…

Google has done a ton of work on GPU accelerated vector graphics too for Android and other platforms. Their skia library is pretty nice: https://skia.org/

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#132
post #17

The bottleneck of UI is not the rendering. A measly 60 fps is plenty fast for UI that feels immediate. We had this in the 90's with software rendering, you don't need a GPU for that today. What causes user interfaces to hick up is that it's too easy to do stuff in the main UI thread. First it doesn't matter but stuff does accumulate, and eventually the UI begins to freeze briefly for example, after you press a button…

Proper development of multithreaded desktop apps and not blocking the UI thread appears to be a lost art. I remember I was drawing all the threads on a person wide piece of paper on the wall when I was working on my first commercial winforms application. It's not exactly hard, but requires basic understanding for UX, threading and the platforms you are working with.

Nowadays I still regularly see applications with (temporarily) frozen windows and I just don't understand how that's possible. When I was developing my winforms apps, anything that would do more than perfectly predictable UI manipulations was run on a background thread (in a task), would be forbidden from starting twice at the same time and only updated the UI when done.

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#133

Earlier quoted context omitted.

But when you do software rendering you don't need to redraw the entire frame buffer, just the parts that changed, which can be very small even at 8k - e.g. the box of a checkbox being switched

Scrolling requires redrawing most if not the whole framebuffer.

With scrolling couldn't you just shift the existing framebuffer up/down and only draw the newly scrolled-to parts?

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#136
post #17

The bottleneck of UI is not the rendering. A measly 60 fps is plenty fast for UI that feels immediate. We had this in the 90's with software rendering, you don't need a GPU for that today. What causes user interfaces to hick up is that it's too easy to do stuff in the main UI thread. First it doesn't matter but stuff does accumulate, and eventually the UI begins to freeze briefly for example, after you press a button…

Unfortunately this isn't true anymore when you get to very high resolutions like 8k. Just clearing the framebuffer of an 8k display at 60hz requires ~6GB/s; about 1/10th of the theoretical memory bandwidth of modern desktop processors. Add in compositing for multiple windows, text rendering and none of that likely being multi-threaded it's pretty clear a CPU has no chance of keeping up.

You aren't talking about the same thing they are and you aren't talking about a scenario that exists. 8k is still exotic and no one is driving any desktop off of a video buffer going from main memory through a CPU.

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#137
post #17

The bottleneck of UI is not the rendering. A measly 60 fps is plenty fast for UI that feels immediate. We had this in the 90's with software rendering, you don't need a GPU for that today. What causes user interfaces to hick up is that it's too easy to do stuff in the main UI thread. First it doesn't matter but stuff does accumulate, and eventually the UI begins to freeze briefly for example, after you press a button…

Proper development of multithreaded desktop apps and not blocking the UI thread appears to be a lost art. I remember I was drawing all the threads on a person wide piece of paper on the wall when I was working on my first commercial winforms application. It's not exactly hard, but requires basic understanding for UX, threading and the platforms you are working with. Nowadays I still regularly see applications with (t…

In .NET Core/.NET 5+ I think it even defaults to having awaited Tasks run on a different thread. So long as you're using async/await properly it's almost impossible to screw up (no need to worry about SynchronizationContext etc.), yet I still see tons of examples of people who simply don't understand threading, async/await, etc. and screw it all up

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#138

Earlier quoted context omitted.

Proper development of multithreaded desktop apps and not blocking the UI thread appears to be a lost art. I remember I was drawing all the threads on a person wide piece of paper on the wall when I was working on my first commercial winforms application. It's not exactly hard, but requires basic understanding for UX, threading and the platforms you are working with. Nowadays I still regularly see applications with (t…

In .NET Core/.NET 5+ I think it even defaults to having awaited Tasks run on a different thread. So long as you're using async/await properly it's almost impossible to screw up (no need to worry about SynchronizationContext etc.), yet I still see tons of examples of people who simply don't understand threading, async/await, etc. and screw it all up

As I don't like async/await (read: I probably don't properly understand it) I just added two extension methods to Control that took a lambda for updating UI stuff (one for Invoke, one for BeginInvoke).

Probably kind of like this: https://stackoverflow.com/a/36107907/2306536

I haven't developed C# for almost a decade, so I probably didn't even have access to async/await back then.

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#139

Earlier quoted context omitted.

Unfortunately this isn't true anymore when you get to very high resolutions like 8k. Just clearing the framebuffer of an 8k display at 60hz requires ~6GB/s; about 1/10th of the theoretical memory bandwidth of modern desktop processors. Add in compositing for multiple windows, text rendering and none of that likely being multi-threaded it's pretty clear a CPU has no chance of keeping up.

But when you do software rendering you don't need to redraw the entire frame buffer, just the parts that changed, which can be very small even at 8k - e.g. the box of a checkbox being switched

You don't need to redraw the entire framebuffer with GPU rendering, either. It's perfectly possible to do small, partial updates.

See for example https://registry.khronos.org/EGL/extensions/EXT/EGL_EXT_buff...

And https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_part...

Re: Leveraging Rust and the GPU to render user interfaces at 120 FPS

#140

Earlier quoted context omitted.

In .NET Core/.NET 5+ I think it even defaults to having awaited Tasks run on a different thread. So long as you're using async/await properly it's almost impossible to screw up (no need to worry about SynchronizationContext etc.), yet I still see tons of examples of people who simply don't understand threading, async/await, etc. and screw it all up

As I don't like async/await (read: I probably don't properly understand it) I just added two extension methods to Control that took a lambda for updating UI stuff (one for Invoke, one for BeginInvoke). Probably kind of like this: https://stackoverflow.com/a/36107907/2306536 I haven't developed C# for almost a decade, so I probably didn't even have access to async/await back then.

Even if you don't really understand async/await in C#, you can do it mostly right by following just a few rules:

1) Make anything that accesses a resource over the network, in a database, or in the filesystem async. So basically any time you make an HTTP request, execute a SQL query, or open a file etc. Otherwise you should generally stick to synchronous since async code is actually slightly slower than synchronous code. An exception to this might be if you're doing some heavy computation that's going to take a while and don't want it blocking the UI thread

2) Async is viral. If you have a method that calls an async method, you need to make the calling method async too. You need to then make its own calling method async as well all the way back to Main()

3) Never use async void as a return type, with the sole notable exception to this rule being event handlers. Use async Task instead as the return type (or async Task if it returns a value)

4) Always call async code with the "await SomeAsyncFunction()" syntax. Calling it other ways like "SomeAsyncFunction().Result" will eliminate most of the benefits of using async in the first place since it is blocking, can cause deadlocks in some cases, etc.

Follow those 4 rules and you don't really even need to understand how async works under the hood, though personally I'd recommend learning it as it will help you a lot when you run into issues with edge cases.

Post reply on HN