Skip to content

Insert ResolvedScenes as dynamic bundles#23808

Merged
alice-i-cecile merged 11 commits intobevyengine:mainfrom
cart:resolved_scene_bundle
Apr 16, 2026
Merged

Insert ResolvedScenes as dynamic bundles#23808
alice-i-cecile merged 11 commits intobevyengine:mainfrom
cart:resolved_scene_bundle

Conversation

@cart
Copy link
Copy Markdown
Member

@cart cart commented Apr 15, 2026

Objective

Currently BSN inserts each component one-by-one. This is incredibly expensive, as it forces an archetype move after every insert.

Solution

Scene templates now write their outputs to reusable bundle scratch space (which uses a bump allocator). The final bundle is written after all components (including inherited components) are written to the bundle.

  • Introduce a BundleWriter, which enables defining a dynamic bundle using scratch space in a bump allocator. Currently this only supports writing individual components to the BundleWriter, because supporting arbitrary bundles is much harder (ex: dynamic bundle effects). This sadly means that we are temporarily constraining both bsn! { Node } and bsn! { @SomeTemplate } "template patches" to require a component output. Custom scene impls can still push arbitrary bundles, which are inserted before the final dynamic bundle write. In practice I believe this will cover the relevant use cases in the short term.
  • We now skip duplicate insertions of components when spawning inherited scenes.
  • We now write empty RelationshipTarget collections, pre-allocated to the correct size to the dynamic bundle, which both avoids another archetype move and ensures we only allocate the inner relationship target collection once.
  • We now write the Relationship component to the dynamic bundle, avoiding an archetype move
  • I added a new "loaded scene inheritance" test variant, just to make sure that case still works
  • ErasedTemplate has been moved to bevy_scene, as it is now "opinionated", more specific to bevy_scene, and less safe to use in a general context
image

These are benchmarks that produce the same UI scene hierarchy through different means (the benchmarks have been updated to have a few "matrix wrapper" components to show the cost of archetype moves):

  • immediate_function_scene: a test of going through the whole "scene building" process, then spawning. this is the cost of ad-hoc scenes that don't reuse work from inherited scenes
  • immediate_loaded_scene: a test where we instantiate a bunch of inherited scene instances, where the inherited scene has already been computed / cached.
  • raw_bundle_no_scene: just spawning the raw bundle directly

@cart cart added this to the 0.19 milestone Apr 15, 2026
@cart cart added C-Performance A change motivated by improving speed, memory usage or compile times A-Scenes Composing and serializing ECS objects labels Apr 15, 2026
Copy link
Copy Markdown
Contributor

@urben1680 urben1680 left a comment

Choose a reason for hiding this comment

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

One thing, did not review the other things because they are a bit of deep water for me yet.

Comment thread crates/bevy_ecs/src/bundle/writer.rs Outdated
@alice-i-cecile alice-i-cecile added S-Needs-Review Needs reviewer attention (from anyone!) to move forward D-Complex Quite challenging from either a design or technical perspective. Ask for help! A-ECS Entities, components, systems, and events labels Apr 15, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in ECS Apr 15, 2026
Comment thread crates/bevy_ecs/src/bundle/writer.rs
Comment thread crates/bevy_ecs/src/bundle/writer.rs
Comment thread crates/bevy_scene/src/resolved_scene.rs
Comment thread crates/bevy_ecs/src/bundle/writer.rs Outdated
Copy link
Copy Markdown
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

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

I've left a number of comments on the details here, and I think there are a number of modest improvements we could make.

The main questions center around overall architecture though: this is quite a bit of tricky, very niche unsafe code.

Can we copy from the entity cloning machinery (which you called out when talking to @Shatur about related work in BEI)?

The core problem feels very similar to that, and I think that with some changes to how we manage ownership of scratch data we should be able to get something that compiles without the need for this level of sketchiness.

@Shatur
Copy link
Copy Markdown
Contributor

Shatur commented Apr 15, 2026

If you have safety concerns, maybe just move it to bevy_scene and make the writer private?

But the API seems reasonable to me.

Copy link
Copy Markdown
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

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

Good: the by_id change was my primary concern, and the changes to merge OwnedBundleScratch into BundleWriter make this a bit more robust.

The drop thing would be nice to fix, but eh, probably not worth the overhead. I'm content with this.

Comment thread crates/bevy_ecs/src/bundle/writer.rs
@alice-i-cecile alice-i-cecile requested a review from NiseVoid April 16, 2026 00:24
Comment thread crates/bevy_ecs/src/bundle/writer.rs Outdated
Comment thread crates/bevy_scene/src/resolved_scene.rs Outdated
Comment thread crates/bevy_ecs/src/bundle/writer.rs Outdated
/// written as a dynamic bundle. The contents are cleared after each write and the allocated scratch
/// space is reused across writes.
#[derive(Default)]
pub struct BundleWriter {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If I'm reading this correctly, the only difference between BundleWriter and BundleScratch is that BundleScratch stores the Bump externally so it can rely on lifetimes a bit more for safety. Is that right? Will we want to do follow-up work to replace the uses of BundleScratch in the cloning code with BundleWriter?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Doing so would give some perf wins, which in the context of cloning makes sense. So my vote is yes.

Comment thread crates/bevy_ecs/src/bundle/writer.rs Outdated
}

/// A filter to skip the template for a given `TypeId`
trait SkipTemplate {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is this a trait, as opposed to leaving the methods non-generic and just passing an empty HashSet or using Option<HashSet>?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was in "skip all unnecessary work" mode. This saves us a branch on each entity spawn (if false {} is trivially optimized out). Given that there are only two versions, I don't think its a steep price to pay.

Comment thread crates/bevy_scene/src/resolved_scene.rs Outdated
Comment thread crates/bevy_scene/src/resolved_scene.rs Outdated
Comment thread crates/bevy_scene/src/resolved_scene.rs
@alice-i-cecile alice-i-cecile added S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Apr 16, 2026
Comment on lines +52 to +53
/// # Safety
/// `components` must be from the same world as the components that were pushed to this writer.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should mention to call this method at most once.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There is no harm in calling this multiple times.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah right my bad 👍

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Apr 16, 2026
Merged via the queue into bevyengine:main with commit dc70b2e Apr 16, 2026
44 checks passed
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in ECS Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-ECS Entities, components, systems, and events A-Scenes Composing and serializing ECS objects C-Performance A change motivated by improving speed, memory usage or compile times D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants