don't panic when swapchain frame is outdated
This commit is contained in:
parent
a42b3c6998
commit
4e391013c8
4 changed files with 140 additions and 108 deletions
|
|
@ -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();
|
||||
|
||||
let program = state.program();
|
||||
{
|
||||
// We clear the frame
|
||||
let mut render_pass = scene.clear(
|
||||
&frame.output.view,
|
||||
&mut encoder,
|
||||
program.background_color(),
|
||||
);
|
||||
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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(),
|
||||
);
|
||||
|
||||
// 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();
|
||||
}
|
||||
Err(error) => match error {
|
||||
wgpu::SwapChainError::Outdated => {
|
||||
// Try rendering again next frame.
|
||||
window.request_redraw();
|
||||
}
|
||||
_ => panic!("Swapchain error: {:?}", error),
|
||||
},
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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, ()>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
) -> 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 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue