Skip to content
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

send Unused event when asset is actually unused #12459

Merged
merged 8 commits into from
Mar 17, 2024

Conversation

robtfm
Copy link
Contributor

@robtfm robtfm commented Mar 13, 2024

Objective

fix #12344

Solution

use existing machinery in track_assets to determine if the asset is unused before firing Asset::Unused event

most extract functions use AssetEvent::Removed to schedule deletion of render world resources. RenderAssetPlugin was using AssetEvent::Unused instead.
Unused fires when the last strong handle is dropped, even if a new one is created. Removed only fires when a new one is not created.
as far as i can see, Unused is the same as Removed except for this "feature", and that it also fires early if all handles for a loading asset are dropped (Removed fires after the loading completes). note that in that case, processing based on Loaded won't have been done anyway.
i think we should get rid of Unused completely, it is not currently used anywhere (except here, previously) and i think using it is probably always a mistake.
i also am not sure why we keep loading assets that have been dropped while loading, we should probably drop the loader task as well and remove immediately.

@robtfm robtfm added C-Bug An unexpected or incorrect behavior A-Assets Load files from disk to use for things like images, models, and sounds labels Mar 13, 2024
@robtfm robtfm added this to the 0.13.1 milestone Mar 13, 2024
@mockersf
Copy link
Member

this was added in #10520 to allow removing assets from the cpu side and keeping them on the gpu side

@alice-i-cecile
Copy link
Member

i think we should get rid of Unused completely, it is not currently used anywhere (except here, previously) and i think using it is probably always a mistake.

Agreed. Different PR of course, so then we can ship this in 0.13.1.

i also am not sure why we keep loading assets that have been dropped while loading, we should probably drop the loader task as well and remove immediately.

This makes sense to me too.

@robtfm
Copy link
Contributor Author

robtfm commented Mar 13, 2024

@JMS55 on discord:

That doesn't seem right. The whole point was I added unused in 0.13 specifically so we would know when to drop a render asset without using removed, as we'll remove it even though it's still in use by the GPU ...

i missed that Removed is also fired on extract when RenderAssetUsages is !MAIN_WORLD.

so instead we can use the existing logic for processing the automatic removal (in track_assets) to determine whether to send the Unused event, as well as whether to attempt to unload the asset.

Copy link
Contributor

@bushrat011899 bushrat011899 left a comment

Choose a reason for hiding this comment

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

Mostly just some minor style suggestions. Otherwise, makes sense!

crates/bevy_asset/src/assets.rs Outdated Show resolved Hide resolved
crates/bevy_asset/src/assets.rs Outdated Show resolved Hide resolved
@robtfm robtfm changed the title unload renderasset on Removed send Unused event when asset is actually unused Mar 14, 2024
@robtfm
Copy link
Contributor Author

robtfm commented Mar 14, 2024

i think the resending of not_ready events might break this. i reworked it to use a local instead of resending, but that requires DropEvent to be pub or track_assets to be pub(crate) - is it a breaking change to make a type public?

@alice-i-cecile
Copy link
Member

is it a breaking change to make a type public

No :)

@robtfm
Copy link
Contributor Author

robtfm commented Mar 15, 2024

i think the resending of not_ready events might break this. i reworked it to use a local instead of resending, but that requires DropEvent to be pub or track_assets to be pub(crate) - is it a breaking change to make a type public?

nope, the code is fine, sorry. i think this is good as is

@JMS55
Copy link
Contributor

JMS55 commented Mar 16, 2024

Tbh I'm having a hard time reviewing this, as the code is a bit confusing. I'm not quite sure I understand the implications of moving it around like this.

@robtfm
Copy link
Contributor Author

robtfm commented Mar 16, 2024

Tbh I'm having a hard time reviewing this, as the code is a bit confusing. I'm not quite sure I understand the implications of moving it around like this.

Have a look at the related issue. the important thing is that the process_handle_drop call checks whether new handles have been created since the drop event was fired, before removing the asset. We now perform that check before sending the unused event as well.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Mar 17, 2024
assets.remove_dropped(id);

if !infos.process_handle_drop(untyped_id) {
// a new handle has been created, or the asset doesn't exist
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we expand this comment a bit with the context you put in your last comment to me? That this is a check to see if a new handle has been created in the same frame after the last one was dropped, meaning it's not actually unused.

Also, what does "or the asset doesn't exist" mean here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's what the comment in the process_handle_drop function says. i don't know a scenario where it would happen.

Copy link
Contributor

@JMS55 JMS55 left a comment

Choose a reason for hiding this comment

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

Thanks that clears it up for me. Approved, but I'd like some more verbose doc comments.

@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 17, 2024
Merged via the queue into bevyengine:main with commit 36cfb21 Mar 17, 2024
26 checks passed
mockersf pushed a commit that referenced this pull request Mar 18, 2024
fix #12344

use existing machinery in track_assets to determine if the asset is
unused before firing Asset::Unused event

~~most extract functions use `AssetEvent::Removed` to schedule deletion
of render world resources. `RenderAssetPlugin` was using
`AssetEvent::Unused` instead.
`Unused` fires when the last strong handle is dropped, even if a new one
is created. `Removed` only fires when a new one is not created.
as far as i can see, `Unused` is the same as `Removed` except for this
"feature", and that it also fires early if all handles for a loading
asset are dropped (`Removed` fires after the loading completes). note
that in that case, processing based on `Loaded` won't have been done
anyway.
i think we should get rid of `Unused` completely, it is not currently
used anywhere (except here, previously) and i think using it is probably
always a mistake.
i also am not sure why we keep loading assets that have been dropped
while loading, we should probably drop the loader task as well and
remove immediately.~~
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 C-Bug An unexpected or incorrect behavior S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Asset will wrongly unload while strong handle is alive under certain circumstances
6 participants