@@ -2,8 +2,9 @@ use alloc::{boxed::Box, collections::BTreeSet, vec::Vec};
2
2
3
3
use bevy_platform:: collections:: HashMap ;
4
4
5
- use crate :: system :: IntoSystem ;
5
+ use crate :: schedule :: SystemSetKey ;
6
6
use crate :: world:: World ;
7
+ use crate :: { schedule:: SystemKey , system:: IntoSystem } ;
7
8
8
9
use super :: {
9
10
is_apply_deferred, ApplyDeferred , DiGraph , Direction , NodeId , ReportCycles , ScheduleBuildError ,
@@ -37,28 +38,26 @@ impl AutoInsertApplyDeferredPass {
37
38
. get ( & distance)
38
39
. copied ( )
39
40
. or_else ( || {
40
- let node_id = self . add_auto_sync ( graph) ;
41
+ let node_id = NodeId :: System ( self . add_auto_sync ( graph) ) ;
41
42
self . auto_sync_node_ids . insert ( distance, node_id) ;
42
43
Some ( node_id)
43
44
} )
44
45
. unwrap ( )
45
46
}
46
47
/// add an [`ApplyDeferred`] system with no config
47
- fn add_auto_sync ( & mut self , graph : & mut ScheduleGraph ) -> NodeId {
48
- let id = NodeId :: System ( graph. systems . len ( ) ) ;
49
-
50
- graph
48
+ fn add_auto_sync ( & mut self , graph : & mut ScheduleGraph ) -> SystemKey {
49
+ let key = graph
51
50
. systems
52
- . push ( SystemNode :: new ( Box :: new ( IntoSystem :: into_system (
51
+ . insert ( SystemNode :: new ( Box :: new ( IntoSystem :: into_system (
53
52
ApplyDeferred ,
54
53
) ) ) ) ;
55
- graph. system_conditions . push ( Vec :: new ( ) ) ;
54
+ graph. system_conditions . insert ( key , Vec :: new ( ) ) ;
56
55
57
56
// ignore ambiguities with auto sync points
58
57
// They aren't under user control, so no one should know or care.
59
- graph. ambiguous_with_all . insert ( id ) ;
58
+ graph. ambiguous_with_all . insert ( NodeId :: System ( key ) ) ;
60
59
61
- id
60
+ key
62
61
}
63
62
}
64
63
@@ -80,76 +79,90 @@ impl ScheduleBuildPass for AutoInsertApplyDeferredPass {
80
79
let mut sync_point_graph = dependency_flattened. clone ( ) ;
81
80
let topo = graph. topsort_graph ( dependency_flattened, ReportCycles :: Dependency ) ?;
82
81
83
- fn set_has_conditions ( graph : & ScheduleGraph , node : NodeId ) -> bool {
84
- !graph. set_conditions_at ( node ) . is_empty ( )
82
+ fn set_has_conditions ( graph : & ScheduleGraph , set : SystemSetKey ) -> bool {
83
+ !graph. set_conditions_at ( set ) . is_empty ( )
85
84
|| graph
86
85
. hierarchy ( )
87
86
. graph ( )
88
- . edges_directed ( node, Direction :: Incoming )
89
- . any ( |( parent, _) | set_has_conditions ( graph, parent) )
87
+ . edges_directed ( NodeId :: Set ( set) , Direction :: Incoming )
88
+ . any ( |( parent, _) | {
89
+ parent
90
+ . as_set ( )
91
+ . is_some_and ( |p| set_has_conditions ( graph, p) )
92
+ } )
90
93
}
91
94
92
- fn system_has_conditions ( graph : & ScheduleGraph , node : NodeId ) -> bool {
93
- assert ! ( node. is_system( ) ) ;
94
- !graph. system_conditions [ node. index ( ) ] . is_empty ( )
95
+ fn system_has_conditions ( graph : & ScheduleGraph , key : SystemKey ) -> bool {
96
+ !graph. system_conditions [ key] . is_empty ( )
95
97
|| graph
96
98
. hierarchy ( )
97
99
. graph ( )
98
- . edges_directed ( node, Direction :: Incoming )
99
- . any ( |( parent, _) | set_has_conditions ( graph, parent) )
100
+ . edges_directed ( NodeId :: System ( key) , Direction :: Incoming )
101
+ . any ( |( parent, _) | {
102
+ parent
103
+ . as_set ( )
104
+ . is_some_and ( |p| set_has_conditions ( graph, p) )
105
+ } )
100
106
}
101
107
102
- let mut system_has_conditions_cache = HashMap :: < usize , bool > :: default ( ) ;
103
- let mut is_valid_explicit_sync_point = |system : NodeId | {
104
- let index = system. index ( ) ;
105
- is_apply_deferred ( graph. systems [ index] . get ( ) . unwrap ( ) )
108
+ let mut system_has_conditions_cache = HashMap :: < SystemKey , bool > :: default ( ) ;
109
+ let mut is_valid_explicit_sync_point = |key : SystemKey | {
110
+ is_apply_deferred ( graph. systems [ key] . get ( ) . unwrap ( ) )
106
111
&& !* system_has_conditions_cache
107
- . entry ( index )
108
- . or_insert_with ( || system_has_conditions ( graph, system ) )
112
+ . entry ( key )
113
+ . or_insert_with ( || system_has_conditions ( graph, key ) )
109
114
} ;
110
115
111
116
// Calculate the distance for each node.
112
117
// The "distance" is the number of sync points between a node and the beginning of the graph.
113
118
// Also store if a preceding edge would have added a sync point but was ignored to add it at
114
119
// a later edge that is not ignored.
115
- let mut distances_and_pending_sync: HashMap < usize , ( u32 , bool ) > =
120
+ let mut distances_and_pending_sync: HashMap < SystemKey , ( u32 , bool ) > =
116
121
HashMap :: with_capacity_and_hasher ( topo. len ( ) , Default :: default ( ) ) ;
117
122
118
123
// Keep track of any explicit sync nodes for a specific distance.
119
124
let mut distance_to_explicit_sync_node: HashMap < u32 , NodeId > = HashMap :: default ( ) ;
120
125
121
126
// Determine the distance for every node and collect the explicit sync points.
122
127
for node in & topo {
128
+ let & NodeId :: System ( key) = node else {
129
+ continue ;
130
+ } ;
131
+
123
132
let ( node_distance, mut node_needs_sync) = distances_and_pending_sync
124
- . get ( & node . index ( ) )
133
+ . get ( & key )
125
134
. copied ( )
126
135
. unwrap_or_default ( ) ;
127
136
128
- if is_valid_explicit_sync_point ( * node ) {
137
+ if is_valid_explicit_sync_point ( key ) {
129
138
// The distance of this sync point does not change anymore as the iteration order
130
139
// makes sure that this node is no unvisited target of another node.
131
140
// Because of this, the sync point can be stored for this distance to be reused as
132
141
// automatically added sync points later.
133
- distance_to_explicit_sync_node. insert ( node_distance, * node ) ;
142
+ distance_to_explicit_sync_node. insert ( node_distance, NodeId :: System ( key ) ) ;
134
143
135
144
// This node just did a sync, so the only reason to do another sync is if one was
136
145
// explicitly scheduled afterwards.
137
146
node_needs_sync = false ;
138
147
} else if !node_needs_sync {
139
148
// No previous node has postponed sync points to add so check if the system itself
140
149
// has deferred params that require a sync point to apply them.
141
- node_needs_sync = graph. systems [ node . index ( ) ] . get ( ) . unwrap ( ) . has_deferred ( ) ;
150
+ node_needs_sync = graph. systems [ key ] . get ( ) . unwrap ( ) . has_deferred ( ) ;
142
151
}
143
152
144
153
for target in dependency_flattened. neighbors_directed ( * node, Direction :: Outgoing ) {
145
- let ( target_distance, target_pending_sync) = distances_and_pending_sync
146
- . entry ( target. index ( ) )
147
- . or_default ( ) ;
154
+ let NodeId :: System ( target) = target else {
155
+ continue ;
156
+ } ;
157
+ let ( target_distance, target_pending_sync) =
158
+ distances_and_pending_sync. entry ( target) . or_default ( ) ;
148
159
149
160
let mut edge_needs_sync = node_needs_sync;
150
161
if node_needs_sync
151
- && !graph. systems [ target. index ( ) ] . get ( ) . unwrap ( ) . is_exclusive ( )
152
- && self . no_sync_edges . contains ( & ( * node, target) )
162
+ && !graph. systems [ target] . get ( ) . unwrap ( ) . is_exclusive ( )
163
+ && self
164
+ . no_sync_edges
165
+ . contains ( & ( * node, NodeId :: System ( target) ) )
153
166
{
154
167
// The node has deferred params to apply, but this edge is ignoring sync points.
155
168
// Mark the target as 'delaying' those commands to a future edge and the current
@@ -174,14 +187,20 @@ impl ScheduleBuildPass for AutoInsertApplyDeferredPass {
174
187
// Find any edges which have a different number of sync points between them and make sure
175
188
// there is a sync point between them.
176
189
for node in & topo {
190
+ let & NodeId :: System ( key) = node else {
191
+ continue ;
192
+ } ;
177
193
let ( node_distance, _) = distances_and_pending_sync
178
- . get ( & node . index ( ) )
194
+ . get ( & key )
179
195
. copied ( )
180
196
. unwrap_or_default ( ) ;
181
197
182
198
for target in dependency_flattened. neighbors_directed ( * node, Direction :: Outgoing ) {
199
+ let NodeId :: System ( target) = target else {
200
+ continue ;
201
+ } ;
183
202
let ( target_distance, _) = distances_and_pending_sync
184
- . get ( & target. index ( ) )
203
+ . get ( & target)
185
204
. copied ( )
186
205
. unwrap_or_default ( ) ;
187
206
@@ -190,7 +209,7 @@ impl ScheduleBuildPass for AutoInsertApplyDeferredPass {
190
209
continue ;
191
210
}
192
211
193
- if is_apply_deferred ( graph. systems [ target. index ( ) ] . get ( ) . unwrap ( ) ) {
212
+ if is_apply_deferred ( graph. systems [ target] . get ( ) . unwrap ( ) ) {
194
213
// We don't need to insert a sync point since ApplyDeferred is a sync point
195
214
// already!
196
215
continue ;
@@ -202,10 +221,10 @@ impl ScheduleBuildPass for AutoInsertApplyDeferredPass {
202
221
. unwrap_or_else ( || self . get_sync_point ( graph, target_distance) ) ;
203
222
204
223
sync_point_graph. add_edge ( * node, sync_point) ;
205
- sync_point_graph. add_edge ( sync_point, target) ;
224
+ sync_point_graph. add_edge ( sync_point, NodeId :: System ( target) ) ;
206
225
207
226
// The edge without the sync point is now redundant.
208
- sync_point_graph. remove_edge ( * node, target) ;
227
+ sync_point_graph. remove_edge ( * node, NodeId :: System ( target) ) ;
209
228
}
210
229
}
211
230
@@ -215,34 +234,39 @@ impl ScheduleBuildPass for AutoInsertApplyDeferredPass {
215
234
216
235
fn collapse_set (
217
236
& mut self ,
218
- set : NodeId ,
219
- systems : & [ NodeId ] ,
237
+ set : SystemSetKey ,
238
+ systems : & [ SystemKey ] ,
220
239
dependency_flattened : & DiGraph ,
221
240
) -> impl Iterator < Item = ( NodeId , NodeId ) > {
222
241
if systems. is_empty ( ) {
223
242
// collapse dependencies for empty sets
224
- for a in dependency_flattened. neighbors_directed ( set, Direction :: Incoming ) {
225
- for b in dependency_flattened. neighbors_directed ( set, Direction :: Outgoing ) {
226
- if self . no_sync_edges . contains ( & ( a, set) )
227
- && self . no_sync_edges . contains ( & ( set, b) )
243
+ for a in dependency_flattened. neighbors_directed ( NodeId :: Set ( set) , Direction :: Incoming )
244
+ {
245
+ for b in
246
+ dependency_flattened. neighbors_directed ( NodeId :: Set ( set) , Direction :: Outgoing )
247
+ {
248
+ if self . no_sync_edges . contains ( & ( a, NodeId :: Set ( set) ) )
249
+ && self . no_sync_edges . contains ( & ( NodeId :: Set ( set) , b) )
228
250
{
229
251
self . no_sync_edges . insert ( ( a, b) ) ;
230
252
}
231
253
}
232
254
}
233
255
} else {
234
- for a in dependency_flattened. neighbors_directed ( set, Direction :: Incoming ) {
256
+ for a in dependency_flattened. neighbors_directed ( NodeId :: Set ( set) , Direction :: Incoming )
257
+ {
235
258
for & sys in systems {
236
- if self . no_sync_edges . contains ( & ( a, set) ) {
237
- self . no_sync_edges . insert ( ( a, sys) ) ;
259
+ if self . no_sync_edges . contains ( & ( a, NodeId :: Set ( set) ) ) {
260
+ self . no_sync_edges . insert ( ( a, NodeId :: System ( sys) ) ) ;
238
261
}
239
262
}
240
263
}
241
264
242
- for b in dependency_flattened. neighbors_directed ( set, Direction :: Outgoing ) {
265
+ for b in dependency_flattened. neighbors_directed ( NodeId :: Set ( set) , Direction :: Outgoing )
266
+ {
243
267
for & sys in systems {
244
- if self . no_sync_edges . contains ( & ( set, b) ) {
245
- self . no_sync_edges . insert ( ( sys, b) ) ;
268
+ if self . no_sync_edges . contains ( & ( NodeId :: Set ( set) , b) ) {
269
+ self . no_sync_edges . insert ( ( NodeId :: System ( sys) , b) ) ;
246
270
}
247
271
}
248
272
}
0 commit comments