Struct wgpu_core::device::life::LifetimeTracker
source · pub(super) struct LifetimeTracker<A: Api> {
mapped: Vec<Stored<BufferId>>,
pub future_suspected_buffers: Vec<Stored<BufferId>>,
pub future_suspected_textures: Vec<Stored<TextureId>>,
pub suspected_resources: SuspectedResources,
active: Vec<ActiveSubmission<A>>,
free_resources: NonReferencedResources<A>,
ready_to_map: Vec<Valid<BufferId>>,
work_done_closures: SmallVec<[SubmittedWorkDoneClosure; 1]>,
}
Expand description
Resource tracking for a device.
Host mapping buffers
A buffer cannot be mapped until all active queue submissions that use it have completed. To that end:
-
Each buffer’s
LifeGuard::submission_index
records the index of the most recent queue submission that uses that buffer. -
Calling
map_async
adds the buffer toself.mapped
, and changesBuffer::map_state
to prevent it from being used in any new submissions. -
When the device is polled, the following
LifetimeTracker
methods decide what should happen next:-
triage_mapped
drainsself.mapped
, checking the submission index of each buffer against the queue submissions that have finished execution. Buffers used by submissions still in flight go inself.active[index].mapped
, and the rest go intoself.ready_to_map
. -
triage_submissions
moves entries inself.active[i]
for completed submissions toself.ready_to_map
. At this point, bothself.active
andself.ready_to_map
are up to date with the given submission index. -
handle_mapping
drainsself.ready_to_map
and actually maps the buffers, collecting a list of notification closures to call. But any buffers that were dropped by the user get moved toself.free_resources
. -
cleanup
frees everything infree_resources
.
-
Only self.mapped
holds a RefCount
for the buffer; it is dropped by
triage_mapped
.
Fields§
§mapped: Vec<Stored<BufferId>>
Resources that the user has requested be mapped, but which are used by queue submissions still in flight.
future_suspected_buffers: Vec<Stored<BufferId>>
Buffers can be used in a submission that is yet to be made, by the
means of write_buffer()
, so we have a special place for them.
future_suspected_textures: Vec<Stored<TextureId>>
Textures can be used in the upcoming submission by write_texture
.
suspected_resources: SuspectedResources
Resources whose user handle has died (i.e. drop/destroy has been called) and will likely be ready for destruction soon.
active: Vec<ActiveSubmission<A>>
Resources used by queue submissions still in flight. One entry per submission, with older submissions appearing before younger.
Entries are added by track_submission
and drained by
LifetimeTracker::triage_submissions
. Lots of methods contribute data
to particular entries.
free_resources: NonReferencedResources<A>
Raw backend resources that are neither referenced nor used.
These are freed by LifeTracker::cleanup
, which is called from periodic
maintenance functions like Global::device_poll
, and when a device is
destroyed.
ready_to_map: Vec<Valid<BufferId>>
Buffers the user has asked us to map, and which are not used by any queue submission still in flight.
work_done_closures: SmallVec<[SubmittedWorkDoneClosure; 1]>
Queue “on_submitted_work_done” closures that were initiated for while there is no currently pending submissions. These cannot be immeidately invoked as they must happen after all mapped buffer callbacks are mapped, so we defer them here until the next time the device is maintained.
Implementations§
source§impl<A: Api> LifetimeTracker<A>
impl<A: Api> LifetimeTracker<A>
pub fn new() -> Self
sourcepub fn queue_empty(&self) -> bool
pub fn queue_empty(&self) -> bool
Return true if there are no queue submissions still in flight.
sourcepub fn track_submission(
&mut self,
index: FenceValue,
temp_resources: impl Iterator<Item = TempResource<A>>,
encoders: Vec<EncoderInFlight<A>>
)
pub fn track_submission( &mut self, index: FenceValue, temp_resources: impl Iterator<Item = TempResource<A>>, encoders: Vec<EncoderInFlight<A>> )
Start tracking resources associated with a new queue submission.
pub fn post_submit(&mut self)
pub(crate) fn map(&mut self, value: Valid<BufferId>, ref_count: RefCount)
sourcepub fn triage_submissions(
&mut self,
last_done: FenceValue,
command_allocator: &Mutex<CommandAllocator<A>>
) -> SmallVec<[SubmittedWorkDoneClosure; 1]>
pub fn triage_submissions( &mut self, last_done: FenceValue, command_allocator: &Mutex<CommandAllocator<A>> ) -> SmallVec<[SubmittedWorkDoneClosure; 1]>
Sort out the consequences of completed submissions.
Assume that all submissions up through last_done
have completed.
-
Buffers used by those submissions are now ready to map, if requested. Add any buffers in the submission’s
mapped
list toself.ready_to_map
, whereLifetimeTracker::handle_mapping
will find them. -
Resources whose final use was in those submissions are now ready to free. Add any resources in the submission’s
last_resources
table toself.free_resources
, whereLifetimeTracker::cleanup
will find them.
Return a list of SubmittedWorkDoneClosure
s to run.
pub fn cleanup(&mut self, device: &A::Device)
pub fn schedule_resource_destruction( &mut self, temp_resource: TempResource<A>, last_submit_index: FenceValue )
pub fn add_work_done_closure(&mut self, closure: SubmittedWorkDoneClosure)
source§impl<A: HalApi> LifetimeTracker<A>
impl<A: HalApi> LifetimeTracker<A>
sourcepub(super) fn triage_suspected<G: GlobalIdentityHandlerFactory>(
&mut self,
hub: &Hub<A, G>,
trackers: &Mutex<Tracker<A>>,
trace: Option<&Mutex<Trace>>,
token: &mut Token<'_, Device<A>>
)
pub(super) fn triage_suspected<G: GlobalIdentityHandlerFactory>( &mut self, hub: &Hub<A, G>, trackers: &Mutex<Tracker<A>>, trace: Option<&Mutex<Trace>>, token: &mut Token<'_, Device<A>> )
Identify resources to free, according to trackers
and self.suspected_resources
.
Given trackers
, the Tracker
belonging to same Device
as
self
, and hub
, the Hub
to which that Device
belongs:
Remove from trackers
each resource mentioned in
self.suspected_resources
. If trackers
held the final reference to
that resource, add it to the appropriate free list, to be destroyed by
the hal:
-
Add resources used by queue submissions still in flight to the
last_resources
table of the last such submission’s entry inself.active
. When that submission has finished execution. thetriage_submissions
method will move them toself.free_resources
. -
Add resources that can be freed right now to
self.free_resources
directly.LifetimeTracker::cleanup
will take care of them as part of this poll.
Entrained resources
This function finds resources that are used only by other resources
ready to be freed, and adds those to the free lists as well. For
example, if there’s some texture T
used only by some texture view
TV
, then if TV
can be freed, T
gets added to the free lists too.
Since wgpu-core
resource ownership patterns are acyclic, we can visit
each type that can be owned after all types that could possibly own
it. This way, we can detect all free-able objects in a single pass,
simply by starting with types that are roots of the ownership DAG (like
render bundles) and working our way towards leaf types (like buffers).
sourcepub(super) fn triage_mapped<G: GlobalIdentityHandlerFactory>(
&mut self,
hub: &Hub<A, G>,
token: &mut Token<'_, Device<A>>
)
pub(super) fn triage_mapped<G: GlobalIdentityHandlerFactory>( &mut self, hub: &Hub<A, G>, token: &mut Token<'_, Device<A>> )
Determine which buffers are ready to map, and which must wait for the GPU.
See the documentation for LifetimeTracker
for details.
sourcepub(super) fn handle_mapping<G: GlobalIdentityHandlerFactory>(
&mut self,
hub: &Hub<A, G>,
raw: &A::Device,
trackers: &Mutex<Tracker<A>>,
token: &mut Token<'_, Device<A>>
) -> Vec<BufferMapPendingClosure>
pub(super) fn handle_mapping<G: GlobalIdentityHandlerFactory>( &mut self, hub: &Hub<A, G>, raw: &A::Device, trackers: &Mutex<Tracker<A>>, token: &mut Token<'_, Device<A>> ) -> Vec<BufferMapPendingClosure>
Map the buffers in self.ready_to_map
.
Return a list of mapping notifications to send.
See the documentation for LifetimeTracker
for details.