@@ -8,7 +8,9 @@ use crate::materials::MaterialSystem;
88use crate :: profiling:: { AssetIntegrationProfileSample , plot_asset_integration} ;
99
1010use super :: super :: AssetTransferQueue ;
11- use super :: super :: particle_task:: drain_ready_particle_builds;
11+ use super :: super :: particle_task:: {
12+ drain_ready_particle_builds, enqueue_startable_particle_uploads,
13+ } ;
1214use super :: gpu_context:: { AssetUploadGpuContext , GpuHandles , collect_gpu_handles} ;
1315use super :: queue:: AssetTaskLane ;
1416use super :: step:: { StepResult , step_asset_task} ;
@@ -34,6 +36,10 @@ const DEADLINE_POLL_STRIDE: u32 = 4;
3436struct LaneDrainOutcome {
3537 /// Whether the lane still had queued work when the drain ended.
3638 pending : bool ,
39+ /// Whether the lane ended with queued work that cannot make progress until background state changes.
40+ blocked_on_background : bool ,
41+ /// Whether at least one task step completed useful work.
42+ made_progress : bool ,
3743 /// Queue steps processed by this drain.
3844 processed : u32 ,
3945}
@@ -384,6 +390,16 @@ fn finalize_drain(
384390 render : outcomes. integration . render . processed ,
385391 particle : outcomes. particle . processed ,
386392 } ;
393+ let made_progress = outcomes. integration . main . made_progress
394+ || outcomes. integration . high_priority . made_progress
395+ || outcomes. integration . normal_priority . made_progress
396+ || outcomes. integration . render . made_progress
397+ || outcomes. particle . made_progress ;
398+ let blocked_on_background = outcomes. integration . main . blocked_on_background
399+ || outcomes. integration . high_priority . blocked_on_background
400+ || outcomes. integration . normal_priority . blocked_on_background
401+ || outcomes. integration . render . blocked_on_background
402+ || outcomes. particle . blocked_on_background ;
387403 summary. finish (
388404 asset,
389405 DrainFinishState {
@@ -395,6 +411,8 @@ fn finalize_drain(
395411 particle : outcomes. particle . pending ,
396412 } ,
397413 processed,
414+ made_progress,
415+ blocked_on_background,
398416 particle_elapsed : outcomes. particle_elapsed ,
399417 elapsed : outcomes. integration_elapsed ,
400418 } ,
@@ -495,6 +513,7 @@ fn drain_particle_asset_tasks(
495513) -> LaneDrainOutcome {
496514 profiling:: scope!( "asset::particle_drain" ) ;
497515 let particle_gpu = super :: step:: particle_task_gpu ( gpu) ;
516+ let startable_before = enqueue_startable_particle_uploads ( asset) ;
498517 let ready_before = drain_ready_particle_builds ( asset, particle_gpu. as_ref ( ) , particle_deadline) ;
499518 let queued = drain_lane (
500519 asset,
@@ -506,15 +525,28 @@ fn drain_particle_asset_tasks(
506525 AssetTaskLane :: Particle ,
507526 ) ;
508527 let ready_after = drain_ready_particle_builds ( asset, particle_gpu. as_ref ( ) , particle_deadline) ;
528+ let startable_after = enqueue_startable_particle_uploads ( asset) ;
509529 LaneDrainOutcome {
510530 pending : ready_before. pending
511531 || queued. pending
512532 || ready_after. pending
513533 || asset. has_ready_particle_build_results ( ) ,
534+ blocked_on_background : queued. blocked_on_background
535+ || ( ready_before. pending && particle_gpu. is_none ( ) )
536+ || ( ready_after. pending && particle_gpu. is_none ( ) )
537+ || startable_before. pending
538+ || startable_after. pending ,
539+ made_progress : queued. made_progress
540+ || ready_before. processed > 0
541+ || ready_after. processed > 0
542+ || startable_before. enqueued > 0
543+ || startable_after. enqueued > 0 ,
514544 processed : ready_before
515545 . processed
546+ . saturating_add ( startable_before. enqueued )
516547 . saturating_add ( queued. processed )
517- . saturating_add ( ready_after. processed ) ,
548+ . saturating_add ( ready_after. processed )
549+ . saturating_add ( startable_after. enqueued ) ,
518550 }
519551}
520552
@@ -535,13 +567,16 @@ fn drain_lane(
535567 let mut yielded: usize = 0 ;
536568 let mut iter_count: u32 = 0 ;
537569 let mut processed: u32 = 0 ;
570+ let mut made_progress = false ;
538571 loop {
539572 // Coarse deadline check: every `DEADLINE_POLL_STRIDE` iterations rather than every
540573 // iteration, so cheap task steps (e.g. texture mip progression) do not pay the
541574 // `Instant::now` syscall on every pop.
542575 if iter_count. is_multiple_of ( DEADLINE_POLL_STRIDE ) && Instant :: now ( ) >= deadline {
543576 return LaneDrainOutcome {
544577 pending : !asset. integrator . lane_is_empty ( lane) ,
578+ blocked_on_background : false ,
579+ made_progress,
545580 processed,
546581 } ;
547582 }
@@ -550,6 +585,8 @@ fn drain_lane(
550585 let Some ( mut task) = task_opt else {
551586 return LaneDrainOutcome {
552587 pending : false ,
588+ blocked_on_background : false ,
589+ made_progress,
553590 processed,
554591 } ;
555592 } ;
@@ -559,6 +596,7 @@ fn drain_lane(
559596 StepResult :: Continue => {
560597 asset. integrator . push_front_lane ( task, lane) ;
561598 yielded = 0 ;
599+ made_progress = true ;
562600 }
563601 StepResult :: YieldBackground => {
564602 asset. integrator . push_back_lane ( task, lane) ;
@@ -567,12 +605,15 @@ fn drain_lane(
567605 if yielded >= lane_len {
568606 return LaneDrainOutcome {
569607 pending : false ,
608+ blocked_on_background : lane_len > 0 ,
609+ made_progress,
570610 processed,
571611 } ;
572612 }
573613 }
574614 StepResult :: Done => {
575615 yielded = 0 ;
616+ made_progress = true ;
576617 }
577618 }
578619 }
0 commit comments