-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Arc-d assets #15813
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
base: main
Are you sure you want to change the base?
Arc-d assets #15813
Conversation
Can you fix the inconsistency between "[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the concept of storing assets in an Arc
. I find that I very rarely mutate existing assets, only add/remove/swap, so Arc
s for assets make perfect sense to me. I am somewhat worried about a lot of usages of get_cloned_mut
that this causes in the rest of the codebase though.
Done! |
fa180c8
to
7828700
Compare
46f0334
to
d51a0b2
Compare
cfb37d8
to
8e37d87
Compare
Removing these functions makes it simpler to redesign them for when assets are Arc'd.
@ElliottjPierce First, technically a file is not strictly necessary, however it is motivating. That is, if it wasn't a file, a reader might be confused - why are we making this an asset if we could have just passed this around as an Second, I am skeptical that assets as entities will really change much in terms of async. If anything, I expect it to make it harder to access assets in async, since now you need to synchronize with the whole world (or the whole asset world or something). I'm not saying we shouldn't do assets-as-entities (I very much want it), but I believe it is gonna end up being mostly orthogonal. Next, this is absolutely a risk. However, I think the splitting of And yes, we are losing the "dense" nature of assets. But unlike components, I would expect most assets are fairly big anyway, and so won't benefit much from cache locality. Plus, assets are accessed in a more "random-access" way anyway. I think it's pretty rare to iterate over all assets. Users can still mimic the RwLock setup by just making their asset a I don't think this is the final solution - I agree, assets-as-entities may change things. But we should still support assets in async. This is necessary for asset saving (which I want to work on next). Thanks for your review!! |
Makes sense. Definitely worth keeping then, good call.
Me too. I just mean if/when we have assets as entities in their own world, and that world is referenced by both the main and render world, etc, the cloning and sharing of assets between contexts won't be much of a motivation anymore. The async stuff is still a very strong motivation, but only for a subset of asset types that need to be referenced in a task or something. And it might be easier to do that with incremental systems or tasks in the asset world anyway. I know that context is hypothetical; just thinking ahead.
Good points here too. You've convinced me.
I know we aren't loosing anything here. Just feels odd that we are standardizing the Arc pattern instead of leaving it up to the user whether to do
Still, that's in the future, and as long as we're ok re-evaluating this in like a year, I do agree that this is the best solution until then.
I'm ok with the additional foot guns here. We just need a really good introduction of the concept. If you have label permissions, it might be worth adding needs-release-note, but IDK how Bevy does that process.
You've reviewed two of mine, so I still owe you one lol. And I'm excited for that saving work. Arcs certainly are the right choice for that, and I suppose it's a reasonable assumption that all assets should be "savable". It's always confused me why game engines have great systems for scriptable objects (unity), resources (godot), etc, but never make them savable at runtime. So I'm excited to see this come to Bevy, IIUC. Thanks! |
did you check the impact of this on rendering an asset heavy scene? |
Cargo.toml
Outdated
[[example]] | ||
name = "arc_asset" | ||
path = "examples/asset/arc_asset.rs" | ||
doc-scrape-examples = true | ||
|
||
[package.metadata.example.arc_asset] | ||
name = "Arc'd Assets" | ||
description = "Demonstrates how to acquire Arc'd assets and use them in an async context" | ||
category = "Assets" | ||
wasm = false | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the focus of the example should not be "arc_asset", it should be "async_access_to_asset" or something. arc is the technical detail, not the interesting feature
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! Done.
really dislike the public api change, but not sure there's a better way to do it |
I don't understand how I haven't read the entire PR so I might have missed something. |
@kristoff3r |
Ah that makes total sense, thanks for explaining. |
@mockersf Sorry I realized I didn't respond to your other question: I have not tested this on an asset heavy scene. Does Bevy have an example or stress test of this? It is possible that the extra dereferences hurt performance, but that might not be too big a deal. We already put render assets in a hashmap so cache locality might already be hurting? Unsure. |
I'm not sure I would suggest investigating a custom smart pointer (or Thoughts? |
Fyi MeshletMesh is an example of a read-only asset that I use Arc to share with the render world cheaply. In general, I wish we could share assets between the main/render world without any copies, in the same way that bevy schedules systems across multiple threads to avoid conflicts. |
Me on Discord |
I made a discussion post #18949 that is an alternative to this. I don't have a crazy strong opinion, but I think my proposal is worth investigating before merging this. Just in case. |
Just a head's up that @andriyDev and I have come up with a followup to this PR. See here. I think we need to start with merging this pr, but I think in the end, we'll have a less breaking api change and a much more flexible system. |
Objective
Fixes #15723. This is an alternative to #15346 (and the associated PR #15359) obsolete. Note if we decide asset locking is preferable, there are learnings from this PR we can apply to #15359.
Solution
Assets are now stored as
Arc<A>
instead of justA
.get
remains the same, but I've added an alternative calledget_arc
which returns a clone of the Arc that stores an asset.Replaced the
get_mut
with one ofget_cloned_mut
,get_inplace_mut
, andget_reflect_cloned_mut
(this last one is just because it's necessary for reflection, but not necessarily needed for users).Added
add_arc
andinsert_arc
to allow addingArc
types directly.add
currently takesInto<A>
. Trying to change this toInto<Arc<A>>
breaks a lot of callsites likemeshes.add(Rectangle::new(1.0, 2.0))
(since this requires twoInto
calls, which Rust can't figure out).add_arc
takeInto<Arc<A>>
is a fine middle ground to allow bothArc
-ed assets and owned assets.insert_arc
.RenderAsset
now takes anArc<Self::SourceAsset>
. This means in most cases, cloning the asset can be skipped when passing data to the render world. Data only needs to be cloned if you mutate an asset.Testing
Showcase
Assets can now be used in asynchronous contexts! By using
Assets<A>::get_arc
, you can get a clone of the underlyingArc
of an asset, and pass it to an async closure.Migration Guide
Assets::get_mut
has been removed. Useget_cloned_mut
forClone
assets, orget_in_place_mut
for non-Clone
assets (and handle the case where the asset is aliased).Assets::iter_mut
now returns an iterator of&mut Arc<A>
. Consider usingArc::make_mut
forClone
assets, orArc::get_mut
for non-Clone
assets (and handle the case where the asset is aliased).RenderAsset
s now take anArc<Self::SourceAsset>
. Consider usingArc::try_unwrap()
and falling back to a clone if the asset is aliased (try_unwrap
returns an error). Otherwise, prefer borrowing the source asset's data instead of moving it.