Skip to content

Commit

Permalink
Release GPU resources from device.trackers, not from lifetime_tracker.
Browse files Browse the repository at this point in the history
  • Loading branch information
bradwerth committed Jan 17, 2024
1 parent 2e38187 commit 05f04f5
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 46 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ By @wumpf in [#5044](https://github.com/gfx-rs/wgpu/pull/5044)
- GPU buffer memory is released during "lose the device". By @bradwerth in [#4851](https://github.com/gfx-rs/wgpu/pull/4851)
- wgpu and wgpu-core features are now documented on docs.rs. By @wumpf in [#4886](https://github.com/gfx-rs/wgpu/pull/4886)
- DeviceLostClosure is guaranteed to be invoked exactly once. By @bradwerth in [#4862](https://github.com/gfx-rs/wgpu/pull/4862)
- Eager release of GPU resources comes from device.trackers. By @bradwerth in [#5075](https://github.com/gfx-rs/wgpu/pull/5075)

#### OpenGL
- `@builtin(instance_index)` now properly reflects the range provided in the draw call instead of always counting from 0. By @cwfitzgerald in [#4722](https://github.com/gfx-rs/wgpu/pull/4722).
Expand Down
43 changes: 0 additions & 43 deletions wgpu-core/src/device/life.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,47 +837,4 @@ impl<A: HalApi> LifetimeTracker<A> {
}
pending_callbacks
}

pub(crate) fn release_gpu_resources(&mut self) {
// This is called when the device is lost, which makes every associated
// resource invalid and unusable. This is an opportunity to release all of
// the underlying gpu resources, even though the objects remain visible to
// the user agent. We purge this memory naturally when resources have been
// moved into the appropriate buckets, so this function just needs to
// initiate movement into those buckets, and it can do that by calling
// "destroy" on all the resources we know about which aren't already marked
// for cleanup.

// During these iterations, we discard all errors. We don't care!

// Destroy all the mapped buffers.
for buffer in &self.mapped {
let _ = buffer.destroy();
}

// Destroy all the unmapped buffers.
for buffer in &self.ready_to_map {
let _ = buffer.destroy();
}

// Destroy all the future_suspected_buffers.
for buffer in &self.future_suspected_buffers {
let _ = buffer.destroy();
}

// Destroy the buffers in all active submissions.
for submission in &self.active {
for buffer in &submission.mapped {
let _ = buffer.destroy();
}
}

// Destroy all the future_suspected_textures.
// TODO: texture.destroy is not implemented
/*
for texture in &self.future_suspected_textures {
let _ = texture.destroy();
}
*/
}
}
24 changes: 21 additions & 3 deletions wgpu-core/src/device/resource.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ impl<A: HalApi> Device<A> {
let mut device_lost_invocations = SmallVec::new();
if !self.is_valid() && life_tracker.queue_empty() {
// We can release gpu resources associated with this device.
life_tracker.release_gpu_resources();
self.release_gpu_resources();

// If we have a DeviceLostClosure, build an invocation with the
// reason DeviceLostReason::Destroyed and no message.
Expand Down Expand Up @@ -3331,7 +3331,6 @@ impl<A: HalApi> Device<A> {
// It's important to not hold the lock while calling the closure.
drop(life_lock);
device_lost_closure.call(DeviceLostReason::Unknown, message.to_string());
life_lock = self.lock_life();
}

// 2) Complete any outstanding mapAsync() steps.
Expand All @@ -3343,7 +3342,26 @@ impl<A: HalApi> Device<A> {
// until they are cleared, and then drop the device.

// Eagerly release GPU resources.
life_lock.release_gpu_resources();
self.release_gpu_resources();
}

pub(crate) fn release_gpu_resources(&self) {
// This is called when the device is lost, which makes every associated
// resource invalid and unusable. This is an opportunity to release all of
// the underlying gpu resources, even though the objects remain visible to
// the user agent. We purge this memory naturally when resources have been
// moved into the appropriate buckets, so this function just needs to
// initiate movement into those buckets, and it can do that by calling
// "destroy" on all the resources we know about.

// During these iterations, we discard all errors. We don't care!
let trackers = self.trackers.lock();
for buffer in trackers.buffers.used_resources() {
let _ = buffer.destroy();
}
for texture in trackers.textures.used_resources() {
let _ = texture.destroy();
}
}
}

Expand Down

0 comments on commit 05f04f5

Please sign in to comment.