Skip to content

Commit f0e245e

Browse files
committed
Cleanup unused framebuffers
1 parent f2365ea commit f0e245e

File tree

3 files changed

+82
-35
lines changed

3 files changed

+82
-35
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ clear:
4848
rm wgpu-bindings/wgpu.h
4949

5050
lib-native: Cargo.lock wgpu-native/Cargo.toml $(wildcard wgpu-native/**/*.rs)
51-
cargo build --manifest-path wgpu-native/Cargo.toml --features $(FEATURE_NATIVE)
51+
cargo build --manifest-path wgpu-native/Cargo.toml --features "local,$(FEATURE_NATIVE)"
5252

5353
lib-rust: Cargo.lock wgpu-rs/Cargo.toml $(wildcard wgpu-rs/**/*.rs)
5454
cargo build --manifest-path wgpu-rs/Cargo.toml --features $(FEATURE_RUST)

wgpu-native/src/device.rs

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ pub(crate) struct RenderPassKey {
6464
}
6565
impl Eq for RenderPassKey {}
6666

67-
#[derive(Hash, PartialEq)]
67+
#[derive(Clone, Hash, PartialEq)]
6868
pub(crate) struct FramebufferKey {
6969
pub attachments: AttachmentVec<TextureViewId>,
7070
}
@@ -77,16 +77,19 @@ enum ResourceId {
7777
TextureView(TextureViewId),
7878
}
7979

80-
enum Resource<B: hal::Backend> {
81-
Buffer(resource::Buffer<B>),
82-
Texture(resource::Texture<B>),
83-
TextureView(resource::TextureView<B>),
80+
enum NativeResource<B: hal::Backend> {
81+
Buffer(B::Buffer),
82+
Image(B::Image),
83+
ImageView(B::ImageView),
84+
Framebuffer(B::Framebuffer),
8485
}
8586

8687
struct ActiveSubmission<B: hal::Backend> {
8788
index: SubmissionIndex,
8889
fence: B::Fence,
89-
resources: Vec<Resource<B>>,
90+
// Note: we keep the associated ID here in order to be able to check
91+
// at any point what resources are used in a submission.
92+
resources: Vec<(Option<ResourceId>, NativeResource<B>)>,
9093
mapped: Vec<BufferId>,
9194
}
9295

@@ -101,7 +104,7 @@ struct DestroyedResources<B: hal::Backend> {
101104
active: Vec<ActiveSubmission<B>>,
102105
/// Resources that are neither referenced or used, just pending
103106
/// actual deletion.
104-
free: Vec<Resource<B>>,
107+
free: Vec<NativeResource<B>>,
105108
ready_to_map: Vec<BufferId>,
106109
}
107110

@@ -119,32 +122,35 @@ impl<B: hal::Backend> DestroyedResources<B> {
119122
}
120123

121124
/// Returns the last submission index that is done.
122-
fn cleanup(&mut self, raw: &B::Device) -> SubmissionIndex {
125+
fn cleanup(&mut self, device: &B::Device) -> SubmissionIndex {
123126
let mut last_done = 0;
124127

125128
for i in (0..self.active.len()).rev() {
126129
if unsafe {
127-
raw.get_fence_status(&self.active[i].fence).unwrap()
130+
device.get_fence_status(&self.active[i].fence).unwrap()
128131
} {
129132
let a = self.active.swap_remove(i);
130133
last_done = last_done.max(a.index);
131-
self.free.extend(a.resources);
134+
self.free.extend(a.resources.into_iter().map(|(_, r)| r));
132135
unsafe {
133-
raw.destroy_fence(a.fence);
136+
device.destroy_fence(a.fence);
134137
}
135138
}
136139
}
137140

138141
for resource in self.free.drain(..) {
139142
match resource {
140-
Resource::Buffer(buf) => unsafe {
141-
raw.destroy_buffer(buf.raw)
143+
NativeResource::Buffer(raw) => unsafe {
144+
device.destroy_buffer(raw)
145+
},
146+
NativeResource::Image(raw) => unsafe {
147+
device.destroy_image(raw)
142148
},
143-
Resource::Texture(tex) => unsafe {
144-
raw.destroy_image(tex.raw)
149+
NativeResource::ImageView(raw) => unsafe {
150+
device.destroy_image_view(raw)
145151
},
146-
Resource::TextureView(view) => unsafe {
147-
raw.destroy_image_view(view.raw)
152+
NativeResource::Framebuffer(raw) => unsafe {
153+
device.destroy_framebuffer(raw)
148154
},
149155
}
150156
}
@@ -167,32 +173,30 @@ impl DestroyedResources<back::Backend> {
167173
if num_refs <= 3 {
168174
let resource_id = self.referenced.swap_remove(i).0;
169175
assert_eq!(num_refs, 3, "Resource {:?} misses some references", resource_id);
170-
let (submit_index, resource) = match resource_id {
176+
let (life_guard, resource) = match resource_id {
171177
ResourceId::Buffer(id) => {
172178
trackers.buffers.remove(id);
173179
let buf = HUB.buffers.unregister(id);
174-
let si = buf.life_guard.submission_index.load(Ordering::Acquire);
175-
(si, Resource::Buffer(buf))
180+
(buf.life_guard, NativeResource::Buffer(buf.raw))
176181
}
177182
ResourceId::Texture(id) => {
178183
trackers.textures.remove(id);
179184
let tex = HUB.textures.unregister(id);
180-
let si = tex.life_guard.submission_index.load(Ordering::Acquire);
181-
(si, Resource::Texture(tex))
185+
(tex.life_guard, NativeResource::Image(tex.raw))
182186
}
183187
ResourceId::TextureView(id) => {
184188
trackers.views.remove(id);
185189
let view = HUB.texture_views.unregister(id);
186-
let si = view.life_guard.submission_index.load(Ordering::Acquire);
187-
(si, Resource::TextureView(view))
190+
(view.life_guard, NativeResource::ImageView(view.raw))
188191
}
189192
};
190-
match self
191-
.active
193+
194+
let submit_index = life_guard.submission_index.load(Ordering::Acquire);
195+
match self.active
192196
.iter_mut()
193197
.find(|a| a.index == submit_index)
194198
{
195-
Some(a) => a.resources.push(resource),
199+
Some(a) => a.resources.push((Some(resource_id), resource)),
196200
None => self.free.push(resource),
197201
}
198202
}
@@ -209,14 +213,49 @@ impl DestroyedResources<back::Backend> {
209213
let resource_id = self.mapped.swap_remove(i).value;
210214
let buf = &buffer_guard[resource_id];
211215
let submit_index = buf.life_guard.submission_index.load(Ordering::Acquire);
212-
match self
213-
.active
216+
self.active
214217
.iter_mut()
215218
.find(|a| a.index == submit_index)
216-
{
217-
Some(a) => a.mapped.push(resource_id),
218-
None => self.ready_to_map.push(resource_id),
219+
.map_or(&mut self.ready_to_map, |a| &mut a.mapped)
220+
.push(resource_id);
221+
}
222+
}
223+
}
224+
225+
fn triage_framebuffers(
226+
&mut self,
227+
framebuffers: &mut FastHashMap<FramebufferKey, <back::Backend as hal::Backend>::Framebuffer>,
228+
) {
229+
let texture_view_guard = HUB.texture_views.read();
230+
let remove_list = framebuffers
231+
.keys()
232+
.filter_map(|key| {
233+
let mut last_submit: SubmissionIndex = 0;
234+
for &at in &key.attachments {
235+
if texture_view_guard.contains(at) {
236+
return None
237+
}
238+
// This attachment is no longer registered.
239+
// Let's see if it's used by any of the active submissions.
240+
let res_id = &Some(ResourceId::TextureView(at));
241+
for a in &self.active {
242+
if a.resources.iter().any(|&(ref id, _)| id == res_id) {
243+
last_submit = last_submit.max(a.index);
244+
}
245+
}
219246
}
247+
Some((key.clone(), last_submit))
248+
})
249+
.collect::<FastHashMap<_,_>>();
250+
251+
for (ref key, submit_index) in remove_list {
252+
let resource = NativeResource::Framebuffer(framebuffers.remove(key).unwrap());
253+
match self.active
254+
.iter_mut()
255+
.find(|a| a.index == submit_index)
256+
{
257+
Some(a) => a.resources.push((None, resource)),
258+
None => self.free.push(resource),
220259
}
221260
}
222261
}
@@ -1073,6 +1112,7 @@ pub extern "C" fn wgpu_queue_submit(
10731112
let last_done = {
10741113
let mut destroyed = device.destroyed.lock();
10751114
destroyed.triage_referenced(&mut *trackers);
1115+
destroyed.triage_framebuffers(&mut *device.framebuffers.lock());
10761116
let last_done = destroyed.cleanup(&device.raw);
10771117
destroyed.handle_mapping(&device.raw);
10781118

wgpu-native/src/hub.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,15 @@ impl<T> ops::IndexMut<Id> for Storage<T> {
100100
}
101101
}
102102

103+
impl<T> Storage<T> {
104+
pub fn contains(&self, id: Id) -> bool {
105+
match self.map.get(id.0 as usize) {
106+
Some(&(_, epoch)) if epoch == id.1 => true,
107+
_ => false
108+
}
109+
}
110+
}
111+
103112
pub struct Registry<T> {
104113
#[cfg(feature = "local")]
105114
identity: Mutex<IdentityManager>,
@@ -136,9 +145,7 @@ impl<T> Registry<T> {
136145
let old = self.data.write().map.insert(id.0 as usize, (value, id.1));
137146
assert!(old.is_none());
138147
}
139-
}
140148

141-
impl<T> Registry<T> {
142149
#[cfg(feature = "local")]
143150
pub fn register_local(&self, value: T) -> Id {
144151
let id = self.identity.lock().alloc();

0 commit comments

Comments
 (0)