add custom error for Compositor::draw()

This commit is contained in:
Billy Messenger 2021-07-22 13:08:13 -05:00
parent 191288771f
commit a7d2834a6d
5 changed files with 69 additions and 30 deletions

View file

@ -220,11 +220,13 @@ pub fn main() {
local_pool.run_until_stalled(); local_pool.run_until_stalled();
} }
Err(error) => match error { Err(error) => match error {
wgpu::SwapChainError::Outdated => { wgpu::SwapChainError::OutOfMemory => {
panic!("Swapchain error: {}. Rendering cannot continue.", error)
}
_ => {
// Try rendering again next frame. // Try rendering again next frame.
window.request_redraw(); window.request_redraw();
} }
_ => panic!("Swapchain error: {:?}", error),
}, },
} }
} }

View file

@ -4,7 +4,7 @@ mod compositor;
#[cfg(feature = "opengl")] #[cfg(feature = "opengl")]
mod gl_compositor; mod gl_compositor;
pub use compositor::Compositor; pub use compositor::{Compositor, CompositorDrawError};
#[cfg(feature = "opengl")] #[cfg(feature = "opengl")]
pub use gl_compositor::GLCompositor; pub use gl_compositor::GLCompositor;

View file

@ -43,9 +43,6 @@ pub trait Compositor: Sized {
/// Draws the output primitives to the next frame of the given [`SwapChain`]. /// 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 /// [`SwapChain`]: Self::SwapChain
fn draw<T: AsRef<str>>( fn draw<T: AsRef<str>>(
&mut self, &mut self,
@ -55,5 +52,33 @@ pub trait Compositor: Sized {
background_color: Color, background_color: Color,
output: &<Self::Renderer as iced_native::Renderer>::Output, output: &<Self::Renderer as iced_native::Renderer>::Output,
overlay: &[T], overlay: &[T],
) -> Result<mouse::Interaction, ()>; ) -> Result<mouse::Interaction, CompositorDrawError>;
}
/// Result of an unsuccessful call to [`Compositor::draw`].
#[derive(Debug)]
pub enum CompositorDrawError {
/// The swapchain is outdated. Try rendering again next frame.
SwapchainOutdated(Box<dyn std::error::Error>),
/// A fatal swapchain error occured. Rendering cannot continue.
FatalSwapchainError(Box<dyn std::error::Error>),
}
impl std::error::Error for CompositorDrawError {}
impl std::fmt::Display for CompositorDrawError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CompositorDrawError::SwapchainOutdated(e) => write!(
f,
"Swapchain is outdated: {}. Try rendering next frame.",
e
),
CompositorDrawError::FatalSwapchainError(e) => write!(
f,
"Fatal swapchain error: {}. Rendering cannot continue.",
e
),
}
}
} }

View file

@ -135,7 +135,8 @@ impl iced_graphics::window::Compositor for Compositor {
background_color: Color, background_color: Color,
output: &<Self::Renderer as iced_native::Renderer>::Output, output: &<Self::Renderer as iced_native::Renderer>::Output,
overlay: &[T], overlay: &[T],
) -> Result<mouse::Interaction, ()> { ) -> Result<mouse::Interaction, iced_graphics::window::CompositorDrawError>
{
match swap_chain.get_current_frame() { match swap_chain.get_current_frame() {
Ok(frame) => { Ok(frame) => {
let mut encoder = self.device.create_command_encoder( let mut encoder = self.device.create_command_encoder(
@ -152,7 +153,7 @@ impl iced_graphics::window::Compositor for Compositor {
ops: wgpu::Operations { ops: wgpu::Operations {
load: wgpu::LoadOp::Clear({ load: wgpu::LoadOp::Clear({
let [r, g, b, a] = background_color.into_linear(); let [r, g, b, a] = background_color.into_linear();
wgpu::Color { wgpu::Color {
r: f64::from(r), r: f64::from(r),
g: f64::from(g), g: f64::from(g),
@ -165,7 +166,7 @@ impl iced_graphics::window::Compositor for Compositor {
}], }],
depth_stencil_attachment: None, depth_stencil_attachment: None,
}); });
let mouse_interaction = renderer.backend_mut().draw( let mouse_interaction = renderer.backend_mut().draw(
&mut self.device, &mut self.device,
&mut self.staging_belt, &mut self.staging_belt,
@ -175,28 +176,28 @@ impl iced_graphics::window::Compositor for Compositor {
output, output,
overlay, overlay,
); );
// Submit work // Submit work
self.staging_belt.finish(); self.staging_belt.finish();
self.queue.submit(Some(encoder.finish())); self.queue.submit(Some(encoder.finish()));
// Recall staging buffers // Recall staging buffers
self.local_pool self.local_pool
.spawner() .spawner()
.spawn(self.staging_belt.recall()) .spawn(self.staging_belt.recall())
.expect("Recall staging belt"); .expect("Recall staging belt");
self.local_pool.run_until_stalled(); self.local_pool.run_until_stalled();
Ok(mouse_interaction) Ok(mouse_interaction)
} }
Err(error) => match error { Err(error) => match error {
wgpu::SwapChainError::OutOfMemory => { wgpu::SwapChainError::OutOfMemory => {
panic!("Wgpu swapchain error: {:?}", error); Err(iced_graphics::window::CompositorDrawError::FatalSwapchainError(Box::new(error)))
} }
_ => { _ => {
// Try again next frame. // Try again next frame.
Err(()) Err(iced_graphics::window::CompositorDrawError::SwapchainOutdated(Box::new(error)))
} }
}, },
} }

View file

@ -366,7 +366,7 @@ async fn run_instance<A, E, C>(
viewport_version = current_viewport_version; viewport_version = current_viewport_version;
} }
if let Ok(new_mouse_interaction) = compositor.draw( match compositor.draw(
&mut renderer, &mut renderer,
&mut swap_chain, &mut swap_chain,
state.viewport(), state.viewport(),
@ -374,23 +374,34 @@ async fn run_instance<A, E, C>(
&primitive, &primitive,
&debug.overlay(), &debug.overlay(),
) { ) {
debug.render_finished(); Ok(new_mouse_interaction) => {
debug.render_finished();
if new_mouse_interaction != mouse_interaction { if new_mouse_interaction != mouse_interaction {
window.set_cursor_icon(conversion::mouse_interaction( window.set_cursor_icon(
new_mouse_interaction, conversion::mouse_interaction(
)); new_mouse_interaction,
),
);
mouse_interaction = new_mouse_interaction; mouse_interaction = new_mouse_interaction;
}
// TODO: Handle animations!
// Maybe we can use `ControlFlow::WaitUntil` for this.
} }
Err(error) => match error {
window::CompositorDrawError::SwapchainOutdated(_) => {
debug.render_finished();
// TODO: Handle animations! // Swapchain is outdated. Try rendering again next frame.
// Maybe we can use `ControlFlow::WaitUntil` for this. window.request_redraw();
} else { }
debug.render_finished(); window::CompositorDrawError::FatalSwapchainError(e) => {
// Fatal swapchain error. Rendering cannot continue.
// Rendering could not complete, try again next frame. panic!("{}", e);
window.request_redraw(); }
},
} }
} }
event::Event::WindowEvent { event::Event::WindowEvent {