Skip to content

Text change detection split #19438

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

ickshonpe
Copy link
Contributor

@ickshonpe ickshonpe commented May 30, 2025

Objective

The detect_text_needs_rerender system runs twice, once querying for all Text root UI node entities and once querying for all Text2d 2d root entities. But both times it queries for all TextSpans. This causes two problems:

  • All TextSpans are checked twice for changes.

  • If there is an error with a TextSpan, detect_text_needs_rerender::<Root> reports the current Root type parameter:

             once!(warn!("found entity {} with a TextSpan that has a TextLayout, which should only be on root \
                 text entities (that have {}); this warning only prints once",
                 entity, core::any::type_name::<Root>()));

    But since the system checks all TextSpans for both root types, the reported root type is determined by the system order. Not the type of the specific TextSpan's root.

Fixes #19437

Solution

Split detect_text_needs_rerender into two systems detect_text_root_needs_rerender and detect_text_span_needs_rerender.
detect_text_root_needs_rerender runs twice, once for Text and once for Text2d, while detect_text_span_needs_rerender only runs once.

The root type has been removed from all the warnings. I considered adding Has<Text> and Has<Text2d> parameters but this already quite convoluted and I don't think identifying the type of root is very useful here. Also it wouldn't be compatible with a custom text implementation using alternative root components.

Testing

With line 114 of many_buttons changed to:

        app.add_systems(Update, |mut text_query: Query<&mut TextSpan>| {

run

cargo run --example many_buttons --release --features bevy/trace_tracy -- --recompute-text --image-freq 0 --buttons 25

many_buttons has no Text2d entities but you can see detect_text_root_needs_rerender::<Text2d> on main doing work:
text-2d-comp

The result looks exciting but this is with an unrealistically large number of text sections. For normal apps though the improvements won't be measurable and they might even be exceeded by the overhead of the new detect_text_span_needs_rerender system. The fix for the deceptive warnings is the more important part of this PR.

ickshonpe added 3 commits May 30, 2025 15:01
…_needs_rerender` and `detect_text_spawn_needs_rerender`.

This avoids checking `TextSpan` nodes for changes twice.
@ickshonpe ickshonpe added C-Bug An unexpected or incorrect behavior A-UI Graphical user interfaces, styles, layouts, and widgets A-Text Rendering and layout for characters S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed A-UI Graphical user interfaces, styles, layouts, and widgets labels May 30, 2025
@alice-i-cecile alice-i-cecile added C-Performance A change motivated by improving speed, memory usage or compile times D-Straightforward Simple bug fixes and API improvements, docs, test and examples X-Uncontroversial This work is generally agreed upon labels Jun 7, 2025
@ickshonpe ickshonpe requested a review from UkoeHB June 7, 2025 11:50
// Potential conflict: `Assets<Image>`
// Since both systems will only ever insert new [`Image`] assets,
// they will never observe each other's effects.
.ambiguous_with(bevy_text::update_text2d_layout)
// We assume Text is on disjoint UI entities to ImageNode and UiTextureAtlasImage
// FIXME: Add an archetype invariant for this https://github.com/bevyengine/bevy/issues/1481.
.ambiguous_with(widget::update_image_content_size_system),
.ambiguous_with(widget::update_image_content_size_system)
.after(detect_text_span_needs_rerender),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means text span rerender detection is not locked into the UiSystems system sets. Which means systems in PostUpdate that deal with text stuff .before(UiSystems::Prepare) could be ordered wrong relative to text span rerender detection.

Can you move detect_text_span_needs_rerender to a system set then in this plugin do .configure_sets(PostUpdate, TextSpanDetectSet.in_set(UiSystems::Content)?

Copy link
Contributor

@UkoeHB UkoeHB Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although that may screw up text2d ordering. Which is might be why I originally allowed duplicate text span change detection.

Copy link
Contributor Author

@ickshonpe ickshonpe Jun 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although that may screw up text2d ordering. Which is might be why I originally allowed duplicate text span change detection.

I guess we could work around this a different way, maybe by adding a Has<Root> to the computed query? Walking all the text spans twice feels really unpleasant though, even if it's cheap in practice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Has<Root> in computed would change anything. Afaict we have these options:

  • This PR with ordering constraints. Will couple text2d and UI system ordering, possibly losing parallelism.
  • Invert the loop and traverse down from roots, manually checking for changed spans. This may be less performant than simply iterating spans twice, since hierarchy traversal is an order of magnitude more expensive per entity IIRC (hashmap lookup vs vec indexing, approximately).
  • Change nothing. Continue to iterate all spans twice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Text Rendering and layout for characters C-Bug An unexpected or incorrect behavior C-Performance A change motivated by improving speed, memory usage or compile times D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Uncontroversial This work is generally agreed upon
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Text change detection discriminator bug
3 participants