Skip to content

Retain asset metadata in RetainedAssets and check if extracted when accessing Assets#23871

Closed
beicause wants to merge 23 commits intobevyengine:mainfrom
beicause:retained-asset
Closed

Retain asset metadata in RetainedAssets and check if extracted when accessing Assets#23871
beicause wants to merge 23 commits intobevyengine:mainfrom
beicause:retained-asset

Conversation

@beicause
Copy link
Copy Markdown
Member

@beicause beicause commented Apr 18, 2026

Objective

Follow up to #21732

Currently we retain render-world-only assets in Assets, and during extraction asset's gpu data is taken, which causes a lack of integrity guarantees when accessing assets and Mesh interface to provide many try_* methods to avoid panics.

Also take_gpu_data only runs for render-world-only assets, which means for the other asset usages, Mesh::final_aabb isn't precomputed.

Solution

The main design changes are in bevy_assets/assets.rs, bevy_assets/render_asset.rs, bevy_render/{erased_}render_asset.rs

  1. Add ErasedRetainedAssets resource and RenderAssets::retain_main_world_asset. When extracting, we create the metadata version of asset and add it to ErasedRetainedAssets. This always runs for any asset usage. To opt out this, use EmptyRetainedAsset. Use RetainedAssets<A> system parameter to access ErasedRetainedAssets.

  2. Allow storing Extractable<A> instead of A internally in Assets so that we can extract data within it (though only the heap data within A can be deallocated). For Mesh, Image, ShaderBuffer, Assets::get will return a Extractable<A> to check if it is extracted.

  3. All try_* methods of Mesh are removed since it's impossible to panic if you can get a Mesh. And systems that need Mesh final_aabb or skinned_mesh_bounds now use RetainedMesh.

  4. Whether Image is extracted is checked everywhere as well.

Testing

I tested test_skinned_mesh_bounds, alter_sprite, mesh_picking

@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen A-Assets Load files from disk to use for things like images, models, and sounds D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Apr 18, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Rendering Apr 18, 2026
@github-project-automation github-project-automation Bot moved this to Needs SME Triage in Assets Apr 18, 2026
@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior C-Code-Quality A section of code that is hard to understand or change X-Contentious There are nontrivial implications that should be thought through labels Apr 18, 2026
Copy link
Copy Markdown
Contributor

@andriyDev andriyDev left a comment

Choose a reason for hiding this comment

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

I haven't done a full review (yet), but just from a quick skim, this is leaking a lot of rendering details into the asset system, which I think is just wrong. Now calling Assets::::get returns a "maybe extracted", which may not be relevant at all to music stuff. The fact that rendering uses a render world and needs to extract data should not leak into literally every other asset type.

Personally I also don't like this "all or nothing" approach. For example, do we really need to remove all the data about an Image? For example, we could keep the size of the image on the Assets, which could be useful information even without having the actual image data (e.g. picking or something?), and it's tiny anyway. So making that data completely inaccessible just because the image data is extracted feels... not ideal.

@beicause
Copy link
Copy Markdown
Member Author

Now calling Assets::::get returns a "maybe extracted", which may not be relevant at all to music stuff.

Assets::get returns None for extracted assets. There is Assets::get_maybe_extracted.

Personally I also don't like this "all or nothing" approach. For example, do we really need to remove all the data about an Image? For example, we could keep the size of the image on the Assets, which could be useful information even without having the actual image data (e.g. picking or something?), and it's tiny anyway. So making that data completely inaccessible just because the image data is extracted feels... not ideal.

There is RetainedAssets<RetainedImage>.

@andriyDev
Copy link
Copy Markdown
Contributor

Assets::get returns None for extracted assets.

Oh then I strongly disagree with this PR. This just brings us back to the previous state of "users just see their Mesh asset as suddenly missing when using RENDER_WORLD". This is exactly why we stopped just removing from the Assets resource - it yields unintuitive behavior and bad error messages.

@beicause
Copy link
Copy Markdown
Member Author

Update: I added an associated type and #[asset(extractable)] to Asset to set the internal storage in Assets. It's Extractable<A> only for Image, Mesh, and ShaderBuffer.

@greeble-dev
Copy link
Copy Markdown
Contributor

I don't think I'm qualified to review this PR - it involves too many big design decisions on how the asset system and renderer work together. I think it needs SME review, and there probably should be a formal goal - something that can organise consensus on the long-term path to optimizing GPU upload and supporting streaming.

Gonna throw out some quick thoughts anyway: I agree with this PR's objective of avoiding so many try_* methods on Mesh. But I disagree with the path taken - I think the building and CPU reading parts of Mesh should be moved to a separate struct or structs, and Mesh should be a fairly opaque wrapper around whatever's the optimal representation for GPU upload.

There's also a few variations on this. Maybe the mesh could be split into two assets, one of which is the GPU data to be extracted. Or maybe the full-fat assets-as-entities-with-multiple-components happens, and the GPU data can be a separate component on the mesh asset entity. Either way, there's a big design space, so it's best discussed in a working group.

@beicause
Copy link
Copy Markdown
Member Author

I think this is less about whether the mesh representation is GPU-optimal but more about how to deal with render world only usage and their metadata needed in the main world.

@beicause
Copy link
Copy Markdown
Member Author

Closing. I agree that this could be resolved if we have non-monolithic assets as entities, where it could be easier to split off and unload gpu data.

@beicause beicause closed this Apr 23, 2026
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in Assets Apr 23, 2026
@github-project-automation github-project-automation Bot moved this from Needs SME Triage to Done in Rendering Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-Assets Load files from disk to use for things like images, models, and sounds A-Rendering Drawing game state to the screen C-Bug An unexpected or incorrect behavior C-Code-Quality A section of code that is hard to understand or change D-Complex Quite challenging from either a design or technical perspective. Ask for help! S-Needs-Review Needs reviewer attention (from anyone!) to move forward X-Contentious There are nontrivial implications that should be thought through

Projects

Status: Done
Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants