Use component_access_set to determine the set of conflicting accesses between two systems. (#19495)

# Objective

- Fixes #4381

## Solution

- Replace `component_access` with `component_access_set` when
determining conflicting systems during schedule building.
- All `component_access()` impls just forward to
`&component_access_set().combined_access`, so we are essentially trading
`Access::is_compatible` for `FilteredAccessSet::is_compatible`.
- `FilteredAccessSet::get_conflicts` internally calls
`combined_access.is_compatible` as the first step, so we can remove that
redundant check.

## Testing

- Un-ignored a previously failing test now that it passes!
- Ran the `build_schedule` benchmark and got basically no change in the
results. Perhaps are benchmarks are just not targetted towards this
situation.
```
$ critcmp main fix-ambiguity -f 'build_schedule'
group                                          fix-ambiguity                          main
-----                                          -------------                          ----
build_schedule/1000_schedule                   1.00       2.9±0.02s        ? ?/sec    1.01       2.9±0.05s        ? ?/sec
build_schedule/1000_schedule_no_constraints    1.02     48.3±1.48ms        ? ?/sec    1.00     47.4±1.78ms        ? ?/sec
build_schedule/100_schedule                    1.00      9.9±0.17ms        ? ?/sec    1.06     10.5±0.32ms        ? ?/sec
build_schedule/100_schedule_no_constraints     1.00   804.7±21.85µs        ? ?/sec    1.03   828.7±19.36µs        ? ?/sec
build_schedule/500_schedule                    1.00    451.7±7.25ms        ? ?/sec    1.04   468.9±11.70ms        ? ?/sec
build_schedule/500_schedule_no_constraints     1.02     12.7±0.46ms        ? ?/sec    1.00     12.5±0.44ms        ? ?/sec
```
This commit is contained in:
andriyDev 2025-06-09 12:40:52 -07:00 committed by GitHub
parent 064e5e48b4
commit f163649b48
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 16 additions and 19 deletions

View File

@ -874,7 +874,6 @@ mod tests {
}
#[test]
#[ignore = "Known failing but fix is non-trivial: https://github.com/bevyengine/bevy/issues/4381"]
fn filtered_components() {
let mut world = World::new();
world.spawn(A);

View File

@ -1418,26 +1418,24 @@ impl ScheduleGraph {
if system_a.is_exclusive() || system_b.is_exclusive() {
conflicting_systems.push((a, b, Vec::new()));
} else {
let access_a = system_a.component_access();
let access_b = system_b.component_access();
if !access_a.is_compatible(access_b) {
match access_a.get_conflicts(access_b) {
AccessConflicts::Individual(conflicts) => {
let conflicts: Vec<_> = conflicts
.ones()
.map(ComponentId::get_sparse_set_index)
.filter(|id| !ignored_ambiguities.contains(id))
.collect();
if !conflicts.is_empty() {
conflicting_systems.push((a, b, conflicts));
}
}
AccessConflicts::All => {
// there is no specific component conflicting, but the systems are overall incompatible
// for example 2 systems with `Query<EntityMut>`
conflicting_systems.push((a, b, Vec::new()));
let access_a = system_a.component_access_set();
let access_b = system_b.component_access_set();
match access_a.get_conflicts(access_b) {
AccessConflicts::Individual(conflicts) => {
let conflicts: Vec<_> = conflicts
.ones()
.map(ComponentId::get_sparse_set_index)
.filter(|id| !ignored_ambiguities.contains(id))
.collect();
if !conflicts.is_empty() {
conflicting_systems.push((a, b, conflicts));
}
}
AccessConflicts::All => {
// there is no specific component conflicting, but the systems are overall incompatible
// for example 2 systems with `Query<EntityMut>`
conflicting_systems.push((a, b, Vec::new()));
}
}
}
}