@@ -144,6 +144,11 @@ impl ExecutorStage {
144
144
for system_index in prepare_system_index_range. clone ( ) {
145
145
let mut system = systems[ system_index] . lock ( ) ;
146
146
system. update_archetype_access ( world) ;
147
+
148
+ // Clear this so that the next block of code that populates it doesn't insert
149
+ // duplicates
150
+ self . system_dependents [ system_index] . clear ( ) ;
151
+ self . system_dependencies [ system_index] . clear ( ) ;
147
152
}
148
153
149
154
// calculate dependencies between systems and build execution order
@@ -204,6 +209,27 @@ impl ExecutorStage {
204
209
}
205
210
}
206
211
212
+ // Verify that dependents are not duplicated
213
+ #[ cfg( debug_assertions) ]
214
+ for system_index in prepare_system_index_range. clone ( ) {
215
+ let mut system_dependents_set = std:: collections:: HashSet :: new ( ) ;
216
+ for dependent_system in & self . system_dependents [ system_index] {
217
+ let inserted = system_dependents_set. insert ( * dependent_system) ;
218
+
219
+ // This means duplicate values are in the system_dependents list
220
+ // This is reproducing when archetypes change. When we fix this, we can remove
221
+ // the hack below and make this a debug-only assert or remove it
222
+ debug_assert ! ( inserted) ;
223
+ }
224
+ }
225
+
226
+ // Clear the ready events lists associated with each system so we can rebuild them
227
+ for ready_events_of_dependents in
228
+ & mut self . ready_events_of_dependents [ prepare_system_index_range. clone ( ) ]
229
+ {
230
+ ready_events_of_dependents. clear ( ) ;
231
+ }
232
+
207
233
// Now that system_dependents and system_dependencies is populated, update
208
234
// system_dependency_count and ready_events
209
235
for system_index in prepare_system_index_range. clone ( ) {
@@ -285,7 +311,11 @@ impl ExecutorStage {
285
311
) ;
286
312
287
313
for dependency in self . system_dependencies [ system_index] . ones ( ) {
288
- log:: trace!( " * Depends on {}" , systems[ dependency] . lock( ) . name( ) ) ;
314
+ log:: trace!(
315
+ " * system ({}) depends on {}" ,
316
+ system_index,
317
+ systems[ dependency] . lock( ) . name( )
318
+ ) ;
289
319
}
290
320
291
321
// This event will be awaited, preventing the task from starting until all
@@ -298,7 +328,6 @@ impl ExecutorStage {
298
328
if start_system_index != 0 {
299
329
if let Some ( ready_event) = ready_event. as_ref ( ) {
300
330
for dependency in self . system_dependencies [ system_index] . ones ( ) {
301
- log:: trace!( " * Depends on {}" , dependency) ;
302
331
if dependency < start_system_index {
303
332
ready_event. decrement ( ) ;
304
333
}
@@ -309,8 +338,32 @@ impl ExecutorStage {
309
338
let world_ref = & * world;
310
339
let resources_ref = & * resources;
311
340
341
+ let dependent_systems = & self . system_dependents [ system_index] ;
312
342
let trigger_events = & self . ready_events_of_dependents [ system_index] ;
313
343
344
+ // Verify that any dependent task has a > 0 count. If a dependent task has > 0
345
+ // count, then the current system we are starting now isn't blocking it from running
346
+ // as it should be. Failure here implies the sync primitives are not matching the
347
+ // intended schedule. This likely compiles out if trace/asserts are disabled but
348
+ // make it explicitly debug-only anyways
349
+ #[ cfg( debug_assertions) ]
350
+ {
351
+ debug_assert_eq ! ( trigger_events. len( ) , dependent_systems. len( ) ) ;
352
+ for ( trigger_event, dependent_system_index) in
353
+ trigger_events. iter ( ) . zip ( dependent_systems)
354
+ {
355
+ log:: trace!(
356
+ " * system ({}) triggers events: ({}): {}" ,
357
+ system_index,
358
+ dependent_system_index,
359
+ trigger_event. get( )
360
+ ) ;
361
+ debug_assert ! (
362
+ * dependent_system_index < start_system_index || trigger_event. get( ) > 0
363
+ ) ;
364
+ }
365
+ }
366
+
314
367
// Spawn the task
315
368
scope. spawn ( async move {
316
369
// Wait until our dependencies are done
0 commit comments