Skip UI updates when UI state unchanged#8610
Skip UI updates when UI state unchanged#8610ickshonpe wants to merge 8 commits intobevyengine:mainfrom
Conversation
|
Example |
|
Example failed with Can you reproduce locally? |
No, works fine locally. Not tested it yet but I think I can see what's wrong. |
… that when a new primary window is created, it can create a root taffy node corresponding to the window. * Added an `EventReader<WindowCreated>` parameter to `ui_layout_system`. * `ui_layout_system` performs a full update on recieving a `WindowCreated` event for the primary window entity.
|
Should be good now. |
crates/bevy_ui/src/layout/mod.rs
Outdated
| } | ||
|
|
||
| impl UiSurface { | ||
| pub fn needs_update(&self) -> bool { |
There was a problem hiding this comment.
Doc strings: this is pub (and will help future readers).
| /// Removes children from the entity's taffy node if it exists. Does nothing otherwise. | ||
| pub fn try_remove_children(&mut self, entity: Entity) { | ||
| /// Removes children from the entity's taffy node if it exists. | ||
| /// Returns false if no corresponding taffy node. |
There was a problem hiding this comment.
| /// Returns false if no corresponding taffy node. | |
| /// | |
| /// Returns false if no corresponding taffy node exists. |
alice-i-cecile
left a comment
There was a problem hiding this comment.
Works locally for me as well. Skipping this work is absolutely worth it: in 99.9% of frames we won't need this.
I would probably use a run condition rather than an in-system check to see if it needs to be skipped, as that will prevent spawning a thread. Minor, but probably a bit nicer.
If you feel that the in-system check is better (it certainly involves a smaller change), just clean up the docs and I'll approve :)
Yep I'm trying to keep to small and isolated changes with these PRs, I have quite a lot of them to put in. I'm not quite sure what you mean about run conditions? I'm using run conditions for the |
I was thinking that you could split out ui_layout system into more parts: one to check if updates should be made, and another to actually do the layout. Might not be faster though, as you'd need to walk the trees twice 🤔 Don't worry about it for this PR. |
Ah right. Yes |
| .collect::<Vec<taffy::node::Node>>(); | ||
| self.taffy.set_children(*taffy_node, &child_nodes).unwrap(); | ||
| if self.taffy.children(*taffy_node).unwrap() != child_nodes { | ||
| self.taffy.set_children(*taffy_node, &child_nodes).unwrap(); |
There was a problem hiding this comment.
Why not bake that check into Taffy's set_children() directly and have Taffy itself tell us if any change occurred? That sounds better conceptually, and allows Taffy internally to optimize any Vec comparison if possible (can maybe run the Vec once looking for changes and applying them in one pass?).
There was a problem hiding this comment.
Why not bake that check into Taffy's
set_children()directly and have Taffy itself tell us if any change occurred? That sounds better conceptually, and allows Taffy internally to optimize anyVeccomparison if possible (can maybe run theVeconce looking for changes and applying them in one pass?).
Probably what we'll do in the future is have our own implementation of Taffy's LayoutTree rather than using the Taffy built-in. With a custom LayoutTree impl the Taffy layout algorithm can access Bevy's parent-child tree directly and there would be no need to maintain a second internal tree with all the fragile synchronization logic that entails.
There was a problem hiding this comment.
Ok thanks for the details!
Objective
Updates to the node geometries, the UI stack, and clipping rects can be skipped entirely if the UI node entities, the window resolution, and the scale factor are all unchanged.
Solution
Add a flag to
UiSurfaceneeds_updatethat is set byui_layout_systemif it makes any changes to the UI layout tree. If the flag is not set, don't update the node geometry, UI stack, or clipping rects.Changelog
UiSurfaceneeds_updatethat is set byui_layout_systemif it makes any changes to the UI layout tree.run_ifconditions toui_stack_systemandupdate_clipping_systemso they only run ifneeds_updateis set.ui_layout_systemonly doescompute_window_layoutsand theNodeandTransformupdates ifneeds_updateis set.Migration Guide