@@ -44,6 +44,12 @@ impl Drop for SurfaceInner {
44
44
}
45
45
}
46
46
47
+ #[ derive( Debug ) ]
48
+ struct FrameNotFound {
49
+ drawable : metal:: Drawable ,
50
+ texture : metal:: Texture ,
51
+ }
52
+
47
53
48
54
impl SurfaceInner {
49
55
pub fn new ( view : * mut Object , layer : CAMetalLayer ) -> Self {
@@ -61,7 +67,7 @@ impl SurfaceInner {
61
67
}
62
68
}
63
69
64
- fn next_frame < ' a > ( & self , frames : & ' a [ Frame ] ) -> Result < ( usize , MutexGuard < ' a , FrameInner > ) , ( ) > {
70
+ fn next_frame < ' a > ( & self , frames : & ' a [ Frame ] ) -> Result < ( usize , MutexGuard < ' a , FrameInner > ) , FrameNotFound > {
65
71
let layer_ref = self . render_layer . lock ( ) ;
66
72
autoreleasepool ( || { // for the drawable
67
73
let ( drawable, texture_temp) : ( & metal:: DrawableRef , & metal:: TextureRef ) = unsafe {
@@ -79,7 +85,10 @@ impl SurfaceInner {
79
85
debug ! ( "next is frame[{}]" , index) ;
80
86
Ok ( ( index, frame) )
81
87
}
82
- None => Err ( ( ) ) ,
88
+ None => Err ( FrameNotFound {
89
+ drawable : drawable. to_owned ( ) ,
90
+ texture : texture_temp. to_owned ( ) ,
91
+ } ) ,
83
92
}
84
93
} )
85
94
}
@@ -105,6 +114,9 @@ struct FrameInner {
105
114
/// If there is `None`, `available == false` means that the frame has already
106
115
/// been acquired and the `drawable` will appear at some point.
107
116
available : bool ,
117
+ /// Stays true for as long as the drawable is circulating through the
118
+ /// CAMetalLayer's frame queue.
119
+ linked : bool ,
108
120
last_frame : usize ,
109
121
}
110
122
@@ -152,16 +164,23 @@ impl Drop for Swapchain {
152
164
impl Swapchain {
153
165
/// Returns the drawable for the specified swapchain image index,
154
166
/// marks the index as free for future use.
155
- pub ( crate ) fn take_drawable ( & self , index : hal:: SwapImageIndex ) -> metal:: Drawable {
167
+ pub ( crate ) fn take_drawable ( & self , index : hal:: SwapImageIndex ) -> Result < metal:: Drawable , ( ) > {
156
168
let mut frame = self
157
169
. frames [ index as usize ]
158
170
. inner
159
171
. lock ( ) ;
160
- assert ! ( !frame. available) ;
161
- frame. available = true ;
162
- frame. drawable
163
- . take ( )
164
- . expect ( "Drawable has not been acquired!" )
172
+ assert ! ( !frame. available && frame. linked) ;
173
+
174
+ match frame. drawable . take ( ) {
175
+ Some ( drawable) => {
176
+ frame. available = true ;
177
+ Ok ( drawable)
178
+ }
179
+ None => {
180
+ frame. linked = false ;
181
+ Err ( ( ) )
182
+ }
183
+ }
165
184
}
166
185
167
186
fn signal_sync ( & self , sync : hal:: FrameSync < Backend > ) {
@@ -199,10 +218,21 @@ impl SwapchainImage {
199
218
}
200
219
// wait for new frames to come until we meet the chosen one
201
220
let mut count = 1 ;
202
- while self . surface . next_frame ( & self . frames ) . unwrap ( ) . 0 != self . index as usize {
203
- count += 1 ;
204
- }
205
- debug ! ( "Swapchain image is ready after {} frames" , count) ;
221
+ loop {
222
+ match self . surface . next_frame ( & self . frames ) {
223
+ Ok ( ( index, _) ) if index == self . index as usize => {
224
+ debug ! ( "Swapchain image is ready after {} frames" , count) ;
225
+ break
226
+ }
227
+ Ok ( _) => {
228
+ count += 1 ;
229
+ }
230
+ Err ( _e) => {
231
+ debug ! ( "Swapchain drawables are changed" ) ;
232
+ break
233
+ }
234
+ }
235
+ }
206
236
count
207
237
}
208
238
}
@@ -323,6 +353,7 @@ impl Device {
323
353
inner : Mutex :: new ( FrameInner {
324
354
drawable,
325
355
available : true ,
356
+ linked : true ,
326
357
last_frame : 0 ,
327
358
} ) ,
328
359
texture : texture. to_owned ( ) ,
@@ -413,6 +444,9 @@ impl hal::Swapchain<Backend> for Swapchain {
413
444
}
414
445
415
446
let frame = self . frames [ oldest_index] . inner . lock ( ) ;
447
+ if !frame. linked {
448
+ return Err ( hal:: AcquireError :: OutOfDate ) ;
449
+ }
416
450
( oldest_index, frame)
417
451
}
418
452
} ;
0 commit comments