@@ -88,7 +88,27 @@ pub struct Device<A: HalApi> {
88
88
label : String ,
89
89
90
90
pub ( crate ) command_allocator : command:: CommandAllocator < A > ,
91
+
92
+ /// The index of the last command submission that was attempted.
93
+ ///
94
+ /// Note that `fence` may never be signalled with this value, if the command
95
+ /// submission failed. If you need to wait for everything running on a
96
+ /// `Queue` to complete, wait for [`last_successful_submission_index`].
97
+ ///
98
+ /// [`last_successful_submission_index`]: Device::last_successful_submission_index
91
99
pub ( crate ) active_submission_index : hal:: AtomicFenceValue ,
100
+
101
+ /// The index of the last successful submission to this device's
102
+ /// [`hal::Queue`].
103
+ ///
104
+ /// Unlike [`active_submission_index`], which is incremented each time
105
+ /// submission is attempted, this is updated only when submission succeeds,
106
+ /// so waiting for this value won't hang waiting for work that was never
107
+ /// submitted.
108
+ ///
109
+ /// [`active_submission_index`]: Device::active_submission_index
110
+ pub ( crate ) last_successful_submission_index : hal:: AtomicFenceValue ,
111
+
92
112
// NOTE: if both are needed, the `snatchable_lock` must be consistently acquired before the
93
113
// `fence` lock to avoid deadlocks.
94
114
pub ( crate ) fence : RwLock < Option < A :: Fence > > ,
@@ -257,6 +277,7 @@ impl<A: HalApi> Device<A> {
257
277
label : desc. label . to_string ( ) ,
258
278
command_allocator,
259
279
active_submission_index : AtomicU64 :: new ( 0 ) ,
280
+ last_successful_submission_index : AtomicU64 :: new ( 0 ) ,
260
281
fence : RwLock :: new ( rank:: DEVICE_FENCE , Some ( fence) ) ,
261
282
snatchable_lock : unsafe { SnatchLock :: new ( rank:: DEVICE_SNATCHABLE_LOCK ) } ,
262
283
valid : AtomicBool :: new ( true ) ,
@@ -387,37 +408,41 @@ impl<A: HalApi> Device<A> {
387
408
profiling:: scope!( "Device::maintain" ) ;
388
409
389
410
let fence = fence_guard. as_ref ( ) . unwrap ( ) ;
390
- let last_done_index = if maintain. is_wait ( ) {
391
- let index_to_wait_for = match maintain {
392
- wgt:: Maintain :: WaitForSubmissionIndex ( submission_index) => {
393
- // We don't need to check to see if the queue id matches
394
- // as we already checked this from inside the poll call.
395
- submission_index. index
396
- }
397
- _ => self . active_submission_index . load ( Ordering :: Relaxed ) ,
398
- } ;
399
- unsafe {
411
+
412
+ // Determine which submission index `maintain` represents.
413
+ let submission_index = match maintain {
414
+ wgt:: Maintain :: WaitForSubmissionIndex ( submission_index) => {
415
+ // We don't need to check to see if the queue id matches
416
+ // as we already checked this from inside the poll call.
417
+ submission_index. index
418
+ }
419
+ wgt:: Maintain :: Wait => self
420
+ . last_successful_submission_index
421
+ . load ( Ordering :: Acquire ) ,
422
+ wgt:: Maintain :: Poll => unsafe {
400
423
self . raw
401
424
. as_ref ( )
402
425
. unwrap ( )
403
- . wait ( fence, index_to_wait_for , CLEANUP_WAIT_MS )
426
+ . get_fence_value ( fence)
404
427
. map_err ( DeviceError :: from) ?
405
- } ;
406
- index_to_wait_for
407
- } else {
428
+ } ,
429
+ } ;
430
+
431
+ // If necessary, wait for that submission to complete.
432
+ if maintain. is_wait ( ) {
408
433
unsafe {
409
434
self . raw
410
435
. as_ref ( )
411
436
. unwrap ( )
412
- . get_fence_value ( fence)
437
+ . wait ( fence, submission_index , CLEANUP_WAIT_MS )
413
438
. map_err ( DeviceError :: from) ?
414
- }
415
- } ;
416
- log:: info!( "Device::maintain: last done index {last_done_index }" ) ;
439
+ } ;
440
+ }
441
+ log:: info!( "Device::maintain: waiting for submission index {submission_index }" ) ;
417
442
418
443
let mut life_tracker = self . lock_life ( ) ;
419
444
let submission_closures =
420
- life_tracker. triage_submissions ( last_done_index , & self . command_allocator ) ;
445
+ life_tracker. triage_submissions ( submission_index , & self . command_allocator ) ;
421
446
422
447
life_tracker. triage_mapped ( ) ;
423
448
@@ -3586,7 +3611,9 @@ impl<A: HalApi> Device<A> {
3586
3611
/// Wait for idle and remove resources that we can, before we die.
3587
3612
pub ( crate ) fn prepare_to_die ( & self ) {
3588
3613
self . pending_writes . lock ( ) . as_mut ( ) . unwrap ( ) . deactivate ( ) ;
3589
- let current_index = self . active_submission_index . load ( Ordering :: Relaxed ) ;
3614
+ let current_index = self
3615
+ . last_successful_submission_index
3616
+ . load ( Ordering :: Acquire ) ;
3590
3617
if let Err ( error) = unsafe {
3591
3618
let fence = self . fence . read ( ) ;
3592
3619
let fence = fence. as_ref ( ) . unwrap ( ) ;
0 commit comments