Cache textures for performance boost #4
Labels
No Label
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No Milestone
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: go/ui#4
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
To improve UI toolkit performance, widgets shouldn't need to re-draw themselves from scratch every single frame. This is fine enough on desktop builds, but WASM builds quickly get bogged down with all the extra draw calls.
Consider the simple Button widget which incurs at least five draw ops per button per frame:
This ticket contains ideas and notes on how texture caching will work.
Prerequisite
The underlying go/render engine has a Texturer interface for holding cached textures (SDL2 or HTML Canvas), but the interface is currently optimized for holding onto generated PNG images.
The Texturer interface should be extended to support creating a "blank" texture and drawing to it manually in much the same way as the render.Engine interface itself: with functions like DrawLine(), DrawRect(), DrawText() and so on.
The UI toolkit can then direct its draw calls to a Texturer instead of directly to the Engine.
Implementation A.
Have a centralized module responsible for holding the cached textures. The advantage over Implementation B (widgets owning their own textures) is that it's easier to free unused textures when they're centralized whereas a garbage-collected widget may be trickier to free properly.
The UI library would get a source file like
texture_cache.go
holding centralized variables and methods, like:The key(s) for the texture cache would usually be the ui.Widget struct directly, with all of its configuration (width, height, text variable, fonts, etc.) and in case a widget has multiple states (e.g. a Button having hover and mouse down states) they could append additional keys such as a string or int value for the state they want:
Basically: if the cacher doesn't have your texture it returns nil/false and you generate it yourself and then store it in the cacher, so on your next check you can get back the texture you stored.
The cache key algorithm would be basically:
Hopefully, widgets having a TextVariable or IntVariable (pointer to data) in their struct will have those values correctly conveyed in the key, so multiple Labels having similar properties but capturing different text contents will be appropriately keyed distinctly in the cache.
Implementation B.
High level overview is:
For example with the Label widget:
So for the best case scenario where a texture is already cached, each call to Present() just blits the texture to the screen in a single draw call.
The
dirty
flag would be set for cases such as:Since caching is up to the widgets, some widgets can maintain multiple cached states, for example Button might keep caches for their normal, hover, and pressed states whereas Label only needs one texture.