don't panic when swapchain frame is outdated

This commit is contained in:
Billy Messenger 2020-12-16 10:03:51 -06:00
parent a42b3c6998
commit 4e391013c8
4 changed files with 140 additions and 108 deletions

View file

@ -168,8 +168,8 @@ pub fn main() {
resized = false;
}
let frame = swap_chain.get_current_frame().expect("Next frame");
match swap_chain.get_current_frame() {
Ok(frame) => {
let mut encoder = device.create_command_encoder(
&wgpu::CommandEncoderDescriptor { label: None },
);
@ -218,6 +218,15 @@ pub fn main() {
local_pool.run_until_stalled();
}
Err(error) => match error {
wgpu::SwapChainError::Outdated => {
// Try rendering again next frame.
window.request_redraw();
}
_ => panic!("Swapchain error: {:?}", error),
},
}
}
_ => {}
}
})

View file

@ -40,6 +40,9 @@ pub trait Compositor: Sized {
/// Draws the output primitives to the next frame of the given [`SwapChain`].
///
/// This will return an error if drawing could not be completed on this frame.
/// If an error occurs, try calling this again on the next frame.
///
/// [`SwapChain`]: Self::SwapChain
fn draw<T: AsRef<str>>(
&mut self,
@ -49,5 +52,5 @@ pub trait Compositor: Sized {
background_color: Color,
output: &<Self::Renderer as iced_native::Renderer>::Output,
overlay: &[T],
) -> mouse::Interaction;
) -> Result<mouse::Interaction, ()>;
}

View file

@ -100,7 +100,7 @@ impl iced_graphics::window::Compositor for Compositor {
width: u32,
height: u32,
) -> Self::SwapChain {
self.device.create_swap_chain(
let swap_chain = self.device.create_swap_chain(
surface,
&wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
@ -109,7 +109,9 @@ impl iced_graphics::window::Compositor for Compositor {
width,
height,
},
)
);
swap_chain
}
fn draw<T: AsRef<str>>(
@ -120,22 +122,25 @@ impl iced_graphics::window::Compositor for Compositor {
background_color: Color,
output: &<Self::Renderer as iced_native::Renderer>::Output,
overlay: &[T],
) -> mouse::Interaction {
let frame = swap_chain.get_current_frame().expect("Next frame");
) -> Result<mouse::Interaction, ()> {
match swap_chain.get_current_frame() {
Ok(frame) => {
let mut encoder = self.device.create_command_encoder(
&wgpu::CommandEncoderDescriptor {
label: Some("iced_wgpu encoder"),
},
);
let _ = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
let _ =
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[
wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.output.view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear({
let [r, g, b, a] = background_color.into_linear();
let [r, g, b, a] =
background_color.into_linear();
wgpu::Color {
r: f64::from(r),
@ -146,7 +151,8 @@ impl iced_graphics::window::Compositor for Compositor {
}),
store: true,
},
}],
},
],
depth_stencil_attachment: None,
});
@ -172,6 +178,15 @@ impl iced_graphics::window::Compositor for Compositor {
self.local_pool.run_until_stalled();
mouse_interaction
Ok(mouse_interaction)
}
Err(error) => match error {
wgpu::SwapChainError::Outdated => {
// Try again next frame.
Err(())
}
_ => panic!("Swapchain error: {:?}", error),
},
}
}
}

View file

@ -311,15 +311,14 @@ async fn run_instance<A, E, C>(
viewport_version = current_viewport_version;
}
let new_mouse_interaction = compositor.draw(
if let Ok(new_mouse_interaction) = compositor.draw(
&mut renderer,
&mut swap_chain,
state.viewport(),
state.background_color(),
&primitive,
&debug.overlay(),
);
) {
debug.render_finished();
if new_mouse_interaction != mouse_interaction {
@ -332,6 +331,12 @@ async fn run_instance<A, E, C>(
// TODO: Handle animations!
// Maybe we can use `ControlFlow::WaitUntil` for this.
} else {
debug.render_finished();
// Rendering could not complete, try again next frame.
window.request_redraw();
}
}
event::Event::WindowEvent {
event: window_event,