summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/integration/src/main.rs97
-rw-r--r--graphics/src/window/compositor.rs5
-rw-r--r--wgpu/src/window/compositor.rs123
-rw-r--r--winit/src/application.rs25
4 files changed, 141 insertions, 109 deletions
diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs
index 9b52f3a5..88d8d023 100644
--- a/examples/integration/src/main.rs
+++ b/examples/integration/src/main.rs
@@ -168,55 +168,64 @@ 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 },
+ );
- let mut encoder = device.create_command_encoder(
- &wgpu::CommandEncoderDescriptor { label: None },
- );
+ let program = state.program();
+
+ {
+ // We clear the frame
+ let mut render_pass = scene.clear(
+ &frame.output.view,
+ &mut encoder,
+ program.background_color(),
+ );
+
+ // Draw the scene
+ scene.draw(&mut render_pass);
+ }
+
+ // And then iced on top
+ let mouse_interaction = renderer.backend_mut().draw(
+ &mut device,
+ &mut staging_belt,
+ &mut encoder,
+ &frame.output.view,
+ &viewport,
+ state.primitive(),
+ &debug.overlay(),
+ );
- let program = state.program();
+ // Then we submit the work
+ staging_belt.finish();
+ queue.submit(Some(encoder.finish()));
- {
- // We clear the frame
- let mut render_pass = scene.clear(
- &frame.output.view,
- &mut encoder,
- program.background_color(),
- );
+ // Update the mouse cursor
+ window.set_cursor_icon(
+ iced_winit::conversion::mouse_interaction(
+ mouse_interaction,
+ ),
+ );
- // Draw the scene
- scene.draw(&mut render_pass);
- }
+ // And recall staging buffers
+ local_pool
+ .spawner()
+ .spawn(staging_belt.recall())
+ .expect("Recall staging buffers");
- // And then iced on top
- let mouse_interaction = renderer.backend_mut().draw(
- &mut device,
- &mut staging_belt,
- &mut encoder,
- &frame.output.view,
- &viewport,
- state.primitive(),
- &debug.overlay(),
- );
-
- // Then we submit the work
- staging_belt.finish();
- queue.submit(Some(encoder.finish()));
-
- // Update the mouse cursor
- window.set_cursor_icon(
- iced_winit::conversion::mouse_interaction(
- mouse_interaction,
- ),
- );
-
- // And recall staging buffers
- local_pool
- .spawner()
- .spawn(staging_belt.recall())
- .expect("Recall staging buffers");
-
- local_pool.run_until_stalled();
+ local_pool.run_until_stalled();
+ }
+ Err(error) => match error {
+ wgpu::SwapChainError::Outdated => {
+ // Try rendering again next frame.
+ window.request_redraw();
+ }
+ _ => panic!("Swapchain error: {:?}", error),
+ },
+ }
}
_ => {}
}
diff --git a/graphics/src/window/compositor.rs b/graphics/src/window/compositor.rs
index 0bc8cbc8..39485153 100644
--- a/graphics/src/window/compositor.rs
+++ b/graphics/src/window/compositor.rs
@@ -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, ()>;
}
diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs
index 492efb42..ad1e609c 100644
--- a/wgpu/src/window/compositor.rs
+++ b/wgpu/src/window/compositor.rs
@@ -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,58 +122,71 @@ 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");
-
- let mut encoder = self.device.create_command_encoder(
- &wgpu::CommandEncoderDescriptor {
- label: Some("iced_wgpu encoder"),
+ ) -> 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 {
+ attachment: &frame.output.view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Clear({
+ let [r, g, b, a] =
+ background_color.into_linear();
+
+ wgpu::Color {
+ r: f64::from(r),
+ g: f64::from(g),
+ b: f64::from(b),
+ a: f64::from(a),
+ }
+ }),
+ store: true,
+ },
+ },
+ ],
+ depth_stencil_attachment: None,
+ });
+
+ let mouse_interaction = renderer.backend_mut().draw(
+ &mut self.device,
+ &mut self.staging_belt,
+ &mut encoder,
+ &frame.output.view,
+ viewport,
+ output,
+ overlay,
+ );
+
+ // Submit work
+ self.staging_belt.finish();
+ self.queue.submit(Some(encoder.finish()));
+
+ // Recall staging buffers
+ self.local_pool
+ .spawner()
+ .spawn(self.staging_belt.recall())
+ .expect("Recall staging belt");
+
+ self.local_pool.run_until_stalled();
+
+ Ok(mouse_interaction)
+ }
+ Err(error) => match error {
+ wgpu::SwapChainError::Outdated => {
+ // Try again next frame.
+ Err(())
+ }
+ _ => panic!("Swapchain error: {:?}", error),
},
- );
-
- 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();
-
- wgpu::Color {
- r: f64::from(r),
- g: f64::from(g),
- b: f64::from(b),
- a: f64::from(a),
- }
- }),
- store: true,
- },
- }],
- depth_stencil_attachment: None,
- });
-
- let mouse_interaction = renderer.backend_mut().draw(
- &mut self.device,
- &mut self.staging_belt,
- &mut encoder,
- &frame.output.view,
- viewport,
- output,
- overlay,
- );
-
- // Submit work
- self.staging_belt.finish();
- self.queue.submit(Some(encoder.finish()));
-
- // Recall staging buffers
- self.local_pool
- .spawner()
- .spawn(self.staging_belt.recall())
- .expect("Recall staging belt");
-
- self.local_pool.run_until_stalled();
-
- mouse_interaction
+ }
}
}
diff --git a/winit/src/application.rs b/winit/src/application.rs
index d1a94864..f19526cb 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -311,27 +311,32 @@ 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();
- debug.render_finished();
+ if new_mouse_interaction != mouse_interaction {
+ window.set_cursor_icon(conversion::mouse_interaction(
+ new_mouse_interaction,
+ ));
- if new_mouse_interaction != mouse_interaction {
- window.set_cursor_icon(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.
+ } else {
+ debug.render_finished();
+
+ // Rendering could not complete, try again next frame.
+ window.request_redraw();
+ }
}
event::Event::WindowEvent {
event: window_event,