@@ -64,7 +64,7 @@ pub(crate) struct RenderPassKey {
64
64
}
65
65
impl Eq for RenderPassKey { }
66
66
67
- #[ derive( Hash , PartialEq ) ]
67
+ #[ derive( Clone , Hash , PartialEq ) ]
68
68
pub ( crate ) struct FramebufferKey {
69
69
pub attachments : AttachmentVec < TextureViewId > ,
70
70
}
@@ -77,16 +77,19 @@ enum ResourceId {
77
77
TextureView ( TextureViewId ) ,
78
78
}
79
79
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 ) ,
84
85
}
85
86
86
87
struct ActiveSubmission < B : hal:: Backend > {
87
88
index : SubmissionIndex ,
88
89
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 > ) > ,
90
93
mapped : Vec < BufferId > ,
91
94
}
92
95
@@ -101,7 +104,7 @@ struct DestroyedResources<B: hal::Backend> {
101
104
active : Vec < ActiveSubmission < B > > ,
102
105
/// Resources that are neither referenced or used, just pending
103
106
/// actual deletion.
104
- free : Vec < Resource < B > > ,
107
+ free : Vec < NativeResource < B > > ,
105
108
ready_to_map : Vec < BufferId > ,
106
109
}
107
110
@@ -119,32 +122,35 @@ impl<B: hal::Backend> DestroyedResources<B> {
119
122
}
120
123
121
124
/// 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 {
123
126
let mut last_done = 0 ;
124
127
125
128
for i in ( 0 ..self . active . len ( ) ) . rev ( ) {
126
129
if unsafe {
127
- raw . get_fence_status ( & self . active [ i] . fence ) . unwrap ( )
130
+ device . get_fence_status ( & self . active [ i] . fence ) . unwrap ( )
128
131
} {
129
132
let a = self . active . swap_remove ( i) ;
130
133
last_done = last_done. max ( a. index ) ;
131
- self . free . extend ( a. resources ) ;
134
+ self . free . extend ( a. resources . into_iter ( ) . map ( | ( _ , r ) | r ) ) ;
132
135
unsafe {
133
- raw . destroy_fence ( a. fence ) ;
136
+ device . destroy_fence ( a. fence ) ;
134
137
}
135
138
}
136
139
}
137
140
138
141
for resource in self . free . drain ( ..) {
139
142
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)
142
148
} ,
143
- Resource :: Texture ( tex ) => unsafe {
144
- raw . destroy_image ( tex . raw )
149
+ NativeResource :: ImageView ( raw ) => unsafe {
150
+ device . destroy_image_view ( raw)
145
151
} ,
146
- Resource :: TextureView ( view ) => unsafe {
147
- raw . destroy_image_view ( view . raw )
152
+ NativeResource :: Framebuffer ( raw ) => unsafe {
153
+ device . destroy_framebuffer ( raw)
148
154
} ,
149
155
}
150
156
}
@@ -167,32 +173,30 @@ impl DestroyedResources<back::Backend> {
167
173
if num_refs <= 3 {
168
174
let resource_id = self . referenced . swap_remove ( i) . 0 ;
169
175
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 {
171
177
ResourceId :: Buffer ( id) => {
172
178
trackers. buffers . remove ( id) ;
173
179
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 ) )
176
181
}
177
182
ResourceId :: Texture ( id) => {
178
183
trackers. textures . remove ( id) ;
179
184
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 ) )
182
186
}
183
187
ResourceId :: TextureView ( id) => {
184
188
trackers. views . remove ( id) ;
185
189
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 ) )
188
191
}
189
192
} ;
190
- match self
191
- . active
193
+
194
+ let submit_index = life_guard. submission_index . load ( Ordering :: Acquire ) ;
195
+ match self . active
192
196
. iter_mut ( )
193
197
. find ( |a| a. index == submit_index)
194
198
{
195
- Some ( a) => a. resources . push ( resource) ,
199
+ Some ( a) => a. resources . push ( ( Some ( resource_id ) , resource) ) ,
196
200
None => self . free . push ( resource) ,
197
201
}
198
202
}
@@ -209,14 +213,49 @@ impl DestroyedResources<back::Backend> {
209
213
let resource_id = self . mapped . swap_remove ( i) . value ;
210
214
let buf = & buffer_guard[ resource_id] ;
211
215
let submit_index = buf. life_guard . submission_index . load ( Ordering :: Acquire ) ;
212
- match self
213
- . active
216
+ self . active
214
217
. iter_mut ( )
215
218
. 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
+ }
219
246
}
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) ,
220
259
}
221
260
}
222
261
}
@@ -1073,6 +1112,7 @@ pub extern "C" fn wgpu_queue_submit(
1073
1112
let last_done = {
1074
1113
let mut destroyed = device. destroyed . lock ( ) ;
1075
1114
destroyed. triage_referenced ( & mut * trackers) ;
1115
+ destroyed. triage_framebuffers ( & mut * device. framebuffers . lock ( ) ) ;
1076
1116
let last_done = destroyed. cleanup ( & device. raw ) ;
1077
1117
destroyed. handle_mapping ( & device. raw ) ;
1078
1118
0 commit comments