-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Add AssetChanged
query filter
#16810
base: main
Are you sure you want to change the base?
Conversation
Why does this revert the |
Because I didn't know that. Will change it back! |
Separately, how should the resource access in |
@@ -141,13 +141,15 @@ | |||
// FIXME(3492): remove once docs are ready | |||
// FIXME(15321): solve CI failures, then replace with `#![expect()]`. | |||
#![allow(missing_docs, reason = "Not all docs are written yet, see #3492.")] | |||
#![allow(unsafe_code)] |
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.
Should we just #![allow(unsafe_code)]
wherever we need it instead of throughout the crate?
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.
That's what the other crates seem to do, I'm not unsure about our policy here.
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.
Much prefer local allows here.
|
||
/// Filter that selects entities with a `A` for an asset that changed | ||
/// after the system last ran, where `A` is a component that implements | ||
/// [`AsAssetId`]. |
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.
What about components that store handles to multiple assets of the same type? We don't need to do that right now, but we might have to revisit it later. In my app I have components with handles to dozens of AnimationClip
s for example. I think you could maybe just have AsAssetId
's method return -> impl Iterator<Item = AssetId>
.
This isn't blocking, just a suggestion.
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 bigger issue is how to handle the associated type. We might have to use some kind of indirection via UntypedAssetId instead to be able to handle multiple kinds of assets.
How would the user forge an id if they do not have access to the underlying type? |
Co-authored-by: Patrick Walton <[email protected]>
Overall this looks fine to me, but as I mentioned we should have an ECS expert look over the |
#[inline] | ||
fn update_component_access(state: &Self::State, access: &mut FilteredAccess<ComponentId>) { | ||
<&A>::update_component_access(&state.asset_id, access); | ||
access.add_resource_read(state.resource_id); |
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 don't think this line is quite enough. We need Query
to report the access in Access<ArchetypeComponentId>
for it to be used by the scheduler, and it currently does that in QueryState::update_archetype_component_access()
, which only looks at component_reads_and_writes()
and component_writes()
.
I think you need modify QueryState::new_with_access()
to look at resource_reads_and_writes()
and resource_writes()
and convert them to ArchetypeComponentId
s.
I think you also need to modify FilteredAccess::is_compatible()
to consider resources to conflict even when the filters don't overlap. (That may need to get reworked in the future for resources-as-components, but the semantics seem reasonable.)
It would be good to add a unit test that verifies that the access is set up correctly. Maybe check that fn system(r: ResMut<AssetChanges<A>>, q: Query<Entity, AssetChanged<A>>)
panics when passed to assert_system_does_not_conflict
, and again with the parameters reversed.
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.
Alright thanks for the close review. Will add a test to validate.
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.
So just added a test and without making any other changes am getting the following error:
error[B0001]: Query<MyComponent, AssetChanged<MyComponent>> in system bevy_asset::asset_changed::tests::resource_conflict::system accesses component(s)AssetChanges<MyAsset> in a way that conflicts with a previous system parameter. Consider using `Without<T>` to create disjoint Queries or merging conflicting Queries into a `ParamSet`. See: https://bevyengine.org/learn/errors/b0001
Thoughts?
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.
Oh, right, ResMut
does unfiltered access, so FilteredAccess::is_compatible()
will see that the filters overlap and catch it. Great! So that won't be a problem unless someone tries to do mutable resource access from a query.
I think it's just the Access<ArchetypeComponentId>
that would be an issue, then. I'm not coming up with a simple way to write a test for that, though.
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.
So, I think it's just adding the following to QueryState::update_archetype_component_access
? d0130a3
@@ -583,6 +583,16 @@ impl<D: QueryData, F: QueryFilter> QueryState<D, F> { | |||
{ | |||
access.add_component_write(archetype_component_id); | |||
} | |||
if self.component_access.access.has_resource_read(component_id) { |
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.
Oh right, this is an existing soundness bug. Re-adding the tag.
Co-authored-by: Alice Cecile <[email protected]>
Objective
Implement a new
AssetChanged
query filter that allows users to query for entities whose related assets may have changed.cold-specialization
, a key rendering optimization for unlocking ancillary benefits of the retained render world, is blocked on being unable detect all scenarios in which an entity's mesh/material changes using events and observers. AnAssetChanged
filter will drastically simplify our implementation and be more robust to future changes.Originally implemented by @nicopap in #5080.
Solution
AssetChanged
query filter that initializes aAssetChanges<A>
resource that tracks changed assets and ticks inasset_events
.Reverts constrain WorldQuery::get_state to only use &Components #13343 and changes the api ofget_state
to acceptimpl Into<UnsafeWorldCell<'w>>
to allow accessing theAssetChanges<A>
resource.AsAssetId
trait used for newtype handle wrappers (e.g.Mesh3d
) that allows associating a component with the underlyingAsset
it represents.Testing
AssetChanged
.Mesh3d
andMeshMaterial3d
(etc) in the renderer. Long term wins in render performance this unblocks should swamp tracking overhead for any realistic workload.Migration Guide
asset_events
system is no longer public. Users should order their systems relative to theAssetEvents
system set.