diff --git a/CHANGELOG.md b/CHANGELOG.md index 015ac462a2..f181007ca8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,18 @@ Pull Request merge. --> +### Public dependency updates +- [raw-window-handle](https://crates.io/raw-window-handle) 0.6 +- [winit](https://crates.io/crates/winit) 0.29 + ### Public dependency updates ### Breaking changes +Changes to `Surface`: +- `Surface::required_extensions` now returns a result. +- `Surface::from_window[_ref]` now take `HasWindowHandle + HasDisplayHandle` as the window and return a new error type. + ### Additions - Partially validated versions of `submit` and `present` commands (called via `QueueGuard`). @@ -18,6 +26,8 @@ ### Bugs fixed +- Incorrect assert condition in `PipelineLayout::is_compatible_with`. + # Version 0.34.1 (2023-10-29) ### Bugs fixed diff --git a/Cargo.toml b/Cargo.toml index 971cc0c03f..b888ecfce8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,11 @@ [workspace] members = [ + "examples/*", "vulkano", "vulkano-macros", "vulkano-shaders", "vulkano-util", - "vulkano-win", + # "vulkano-win", ] resolver = "2" @@ -44,13 +45,19 @@ parking_lot = "0.12" proc-macro2 = "1.0" proc-macro-crate = "1.2" quote = "1.0" -raw-window-handle = "0.5" +raw-window-handle = "0.6" regex = "1.8" serde = "1.0" serde_json = "1.0" shaderc = "0.8" smallvec = "1.8" -syn = "1.0" +syn = "2.0" thread_local = "1.1" vk-parse = "0.12" -winit = "0.28" +winit = "0.29" + +# Only used in examples +cgmath = "0.18" +png = "0.17" +rand = "0.8" +ron = "0.8" diff --git a/examples/Cargo.toml b/examples/Cargo.toml deleted file mode 100644 index 77747fceaf..0000000000 --- a/examples/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[workspace] -members = ["*"] -resolver = "2" - -[workspace.dependencies] -cgmath = "0.18" -png = "0.17" -rand = "0.8" -ron = "0.8" -serde = "1.0" -vulkano = { path = "../vulkano" } -vulkano-macros = { path = "../vulkano-macros" } -vulkano-shaders = { path = "../vulkano-shaders" } -vulkano-util = { path = "../vulkano-util" } -winit = "0.28" diff --git a/examples/async-update/main.rs b/examples/async-update/main.rs index 449a63e9c6..5fa098de7b 100644 --- a/examples/async-update/main.rs +++ b/examples/async-update/main.rs @@ -39,6 +39,7 @@ use cgmath::{Matrix4, Rad}; use rand::Rng; use std::{ + error::Error, hint, sync::{ atomic::{AtomicBool, AtomicU64, Ordering}, @@ -91,18 +92,19 @@ use vulkano::{ Validated, VulkanError, VulkanLibrary, }; use winit::{ - event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, + keyboard::{Key, NamedKey}, window::WindowBuilder, }; const TRANSFER_GRANULARITY: u32 = 4096; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -521,13 +523,15 @@ fn main() { println!("\nPress space to update part of the texture"); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -538,10 +542,10 @@ fn main() { Event::WindowEvent { event: WindowEvent::KeyboardInput { - input: - KeyboardInput { + event: + KeyEvent { + logical_key: Key::Named(NamedKey::Space), state: ElementState::Released, - virtual_keycode: Some(VirtualKeyCode::Space), .. }, .. @@ -550,7 +554,10 @@ fn main() { } => { channel.send(()).unwrap(); } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { let image_extent: [u32; 2] = window.inner_size().into(); if image_extent.contains(&0) { @@ -685,9 +692,10 @@ fn main() { } } } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } #[allow(clippy::too_many_arguments)] diff --git a/examples/buffer-allocator/main.rs b/examples/buffer-allocator/main.rs index c9a708b1f5..371f0c6c0a 100644 --- a/examples/buffer-allocator/main.rs +++ b/examples/buffer-allocator/main.rs @@ -10,6 +10,7 @@ // Modified triangle example to show `SubbufferAllocator`. use std::{ + error::Error, sync::Arc, time::{SystemTime, UNIX_EPOCH}, }; @@ -55,11 +56,11 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -280,13 +281,15 @@ fn main() { let command_buffer_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default()); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -294,7 +297,10 @@ fn main() { } => { recreate_swapchain = true; } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { let image_extent: [u32; 2] = window.inner_size().into(); if image_extent.contains(&0) { @@ -426,9 +432,10 @@ fn main() { } } } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/clear-attachments/main.rs b/examples/clear-attachments/main.rs index 275e8a725f..1f92bf2666 100644 --- a/examples/clear-attachments/main.rs +++ b/examples/clear-attachments/main.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ command_buffer::{ allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, ClearAttachment, @@ -32,14 +32,14 @@ use winit::{ window::WindowBuilder, }; -fn main() { +fn main() -> Result<(), impl Error> { // The start of this example is exactly the same as `triangle`. You should read the `triangle` // example if you haven't done so yet. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -157,140 +157,149 @@ fn main() { let mut recreate_swapchain = false; let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - if image_extent.contains(&0) { - return; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { + recreate_swapchain = true; + } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); - previous_frame_end.as_mut().unwrap().cleanup_finished(); + if image_extent.contains(&0) { + return; + } - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); + previous_frame_end.as_mut().unwrap().cleanup_finished(); - swapchain = new_swapchain; - width = swapchain.image_extent()[0]; - height = swapchain.image_extent()[1]; - framebuffers = window_size_dependent_setup(&new_images, render_pass.clone()); - recreate_swapchain = false; - } + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; + swapchain = new_swapchain; + width = swapchain.image_extent()[0]; + height = swapchain.image_extent()[1]; + framebuffers = window_size_dependent_setup(&new_images, render_pass.clone()); + recreate_swapchain = false; + } - if suboptimal { - recreate_swapchain = true; - } + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - // Clear attachments with clear values and rects information. All the rects will be - // cleared by the same value. Note that the ClearRect offsets and extents are not - // affected by the viewport, they are directly applied to the rendering image. - .clear_attachments( - [ClearAttachment::Color { - color_attachment: 0, - clear_value: [1.0, 0.0, 0.0, 1.0].into(), - }] - .into_iter() - .collect(), - [ - // Fixed offset and extent. - ClearRect { - offset: [0, 0], - extent: [100, 100], - array_layers: 0..1, - }, - // Fixed offset, relative extent. - ClearRect { - offset: [100, 150], - extent: [width / 4, height / 4], - array_layers: 0..1, - }, - // Relative offset and extent. - ClearRect { - offset: [width / 2, height / 2], - extent: [width / 3, height / 5], - array_layers: 0..1, - }, - ] - .into_iter() - .collect(), + if suboptimal { + recreate_swapchain = true; + } + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, ) - .unwrap() - .end_render_pass(Default::default()) .unwrap(); - let command_buffer = builder.build().unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + // Clear attachments with clear values and rects information. All the rects + // will be cleared by the same value. Note that the ClearRect offsets and + // extents are not affected by the viewport, they are directly applied to the + // rendering image. + .clear_attachments( + [ClearAttachment::Color { + color_attachment: 0, + clear_value: [1.0, 0.0, 0.0, 1.0].into(), + }] + .into_iter() + .collect(), + [ + // Fixed offset and extent. + ClearRect { + offset: [0, 0], + extent: [100, 100], + array_layers: 0..1, + }, + // Fixed offset, relative extent. + ClearRect { + offset: [100, 150], + extent: [width / 4, height / 4], + array_layers: 0..1, + }, + // Relative offset and extent. + ClearRect { + offset: [width / 2, height / 2], + extent: [width / 3, height / 5], + array_layers: 0..1, + }, + ] + .into_iter() + .collect(), + ) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); - } - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); - } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/deferred/main.rs b/examples/deferred/main.rs index 23175dddad..48066a9771 100644 --- a/examples/deferred/main.rs +++ b/examples/deferred/main.rs @@ -30,7 +30,7 @@ use crate::{ triangle_draw_system::TriangleDrawSystem, }; use cgmath::{Matrix4, SquareMatrix, Vector3}; -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ command_buffer::allocator::{ StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo, @@ -57,13 +57,13 @@ use winit::{ mod frame; mod triangle_draw_system; -fn main() { +fn main() -> Result<(), impl Error> { // Basic initialization. See the triangle example if you want more details about this. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -186,107 +186,116 @@ fn main() { let mut recreate_swapchain = false; let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - if image_extent.contains(&0) { - return; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); + } + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { + recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); - previous_frame_end.as_mut().unwrap().cleanup_finished(); + if image_extent.contains(&0) { + return; + } - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - let new_images = new_images - .into_iter() - .map(|image| ImageView::new_default(image).unwrap()) - .collect::>(); + previous_frame_end.as_mut().unwrap().cleanup_finished(); - swapchain = new_swapchain; - images = new_images; - recreate_swapchain = false; - } + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + let new_images = new_images + .into_iter() + .map(|image| ImageView::new_default(image).unwrap()) + .collect::>(); - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; + swapchain = new_swapchain; + images = new_images; + recreate_swapchain = false; + } - if suboptimal { - recreate_swapchain = true; - } + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; - let future = previous_frame_end.take().unwrap().join(acquire_future); - let mut frame = frame_system.frame( - future, - images[image_index as usize].clone(), - Matrix4::identity(), - ); - let mut after_future = None; - while let Some(pass) = frame.next_pass() { - match pass { - Pass::Deferred(mut draw_pass) => { - let cb = triangle_draw_system.draw(draw_pass.viewport_dimensions()); - draw_pass.execute(cb); - } - Pass::Lighting(mut lighting) => { - lighting.ambient_light([0.1, 0.1, 0.1]); - lighting.directional_light(Vector3::new(0.2, -0.1, -0.7), [0.6, 0.6, 0.6]); - lighting.point_light(Vector3::new(0.5, -0.5, -0.1), [1.0, 0.0, 0.0]); - lighting.point_light(Vector3::new(-0.9, 0.2, -0.15), [0.0, 1.0, 0.0]); - lighting.point_light(Vector3::new(0.0, 0.5, -0.05), [0.0, 0.0, 1.0]); - } - Pass::Finished(af) => { - after_future = Some(af); + if suboptimal { + recreate_swapchain = true; + } + + let future = previous_frame_end.take().unwrap().join(acquire_future); + let mut frame = frame_system.frame( + future, + images[image_index as usize].clone(), + Matrix4::identity(), + ); + let mut after_future = None; + while let Some(pass) = frame.next_pass() { + match pass { + Pass::Deferred(mut draw_pass) => { + let cb = triangle_draw_system.draw(draw_pass.viewport_dimensions()); + draw_pass.execute(cb); + } + Pass::Lighting(mut lighting) => { + lighting.ambient_light([0.1, 0.1, 0.1]); + lighting + .directional_light(Vector3::new(0.2, -0.1, -0.7), [0.6, 0.6, 0.6]); + lighting.point_light(Vector3::new(0.5, -0.5, -0.1), [1.0, 0.0, 0.0]); + lighting.point_light(Vector3::new(-0.9, 0.2, -0.15), [0.0, 1.0, 0.0]); + lighting.point_light(Vector3::new(0.0, 0.5, -0.05), [0.0, 0.0, 1.0]); + } + Pass::Finished(af) => { + after_future = Some(af); + } } } - } - let future = after_future - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); + let future = after_future + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); - } - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); - } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } diff --git a/examples/gl-interop/main.rs b/examples/gl-interop/main.rs index e035e34b67..dcd4bd8eec 100644 --- a/examples/gl-interop/main.rs +++ b/examples/gl-interop/main.rs @@ -1,8 +1,12 @@ -fn main() { +fn main() -> Result<(), winit::error::EventLoopError> { #[cfg(target_os = "linux")] - linux::main(); + { + linux::main() + } #[cfg(not(target_os = "linux"))] - println!("Not Implemented"); + { + Ok(println!("Not Implemented")) + } } // TODO: Can this be demonstrated for other platforms as well? @@ -80,7 +84,7 @@ mod linux { window::{Window, WindowBuilder}, }; - pub fn main() { + pub fn main() -> Result<(), winit::error::EventLoopError> { let event_loop_gl = winit_glium::event_loop::EventLoop::new(); // For some reason, this must be created before the vulkan window let hrb = glutin::ContextBuilder::new() @@ -102,7 +106,7 @@ mod linux { ) .unwrap(); - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let ( device, _instance, @@ -287,13 +291,15 @@ mod linux { let mut previous_frame_end: Option> = Some(Box::new(now(device.clone()))); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -301,7 +307,10 @@ mod linux { } => { recreate_swapchain = true; } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { queue .with(|mut q| unsafe { q.submit( @@ -441,10 +450,10 @@ mod linux { } }; } - + Event::AboutToWait => window.request_redraw(), _ => (), }; - }); + }) } #[derive(BufferContents, Vertex)] @@ -473,7 +482,7 @@ mod linux { Subbuffer<[MyVertex]>, ) { let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { diff --git a/examples/image-self-copy-blit/main.rs b/examples/image-self-copy-blit/main.rs index d5d70842ca..eac0395390 100644 --- a/examples/image-self-copy-blit/main.rs +++ b/examples/image-self-copy-blit/main.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -57,14 +57,14 @@ use winit::{ window::WindowBuilder, }; -fn main() { +fn main() -> Result<(), impl Error> { // The start of this example is exactly the same as `triangle`. You should read the `triangle` // example if you haven't done so yet. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -415,120 +415,131 @@ fn main() { .boxed(), ); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); - - if image_extent.contains(&0) { - return; - } + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_descriptor_sets( - PipelineBindPoint::Graphics, - pipeline.layout().clone(), - 0, - set.clone(), - ) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .bind_descriptor_sets( + PipelineBindPoint::Graphics, + pipeline.layout().clone(), + 0, + set.clone(), + ) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/image/main.rs b/examples/image/main.rs index 55c1876476..2fbe83c5ab 100644 --- a/examples/image/main.rs +++ b/examples/image/main.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -56,14 +56,14 @@ use winit::{ window::WindowBuilder, }; -fn main() { +fn main() -> Result<(), impl Error> { // The start of this example is exactly the same as `triangle`. You should read the `triangle` // example if you haven't done so yet. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -363,120 +363,131 @@ fn main() { .boxed(), ); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); - - if image_extent.contains(&0) { - return; - } + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_descriptor_sets( - PipelineBindPoint::Graphics, - pipeline.layout().clone(), - 0, - set.clone(), - ) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .bind_descriptor_sets( + PipelineBindPoint::Graphics, + pipeline.layout().clone(), + 0, + set.clone(), + ) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/immutable-sampler/main.rs b/examples/immutable-sampler/main.rs index a0a7b4c11a..fd086473ba 100644 --- a/examples/immutable-sampler/main.rs +++ b/examples/immutable-sampler/main.rs @@ -16,7 +16,7 @@ // - The sampler is added to the descriptor set layout at pipeline creation. // - No sampler is included when building a descriptor set. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -65,11 +65,11 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -381,120 +381,131 @@ fn main() { .boxed(), ); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); - - if image_extent.contains(&0) { - return; - } - - previous_frame_end.as_mut().unwrap().cleanup_finished(); + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_descriptor_sets( - PipelineBindPoint::Graphics, - pipeline.layout().clone(), - 0, - set.clone(), - ) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .bind_descriptor_sets( + PipelineBindPoint::Graphics, + pipeline.layout().clone(), + 0, + set.clone(), + ) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/indirect/main.rs b/examples/indirect/main.rs index 52dc7c6870..d528c01c32 100644 --- a/examples/indirect/main.rs +++ b/examples/indirect/main.rs @@ -23,7 +23,7 @@ // For an explanation of how the rendering of the triangles takes place see the `triangle.rs` // example. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{ allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}, @@ -72,11 +72,11 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -226,9 +226,9 @@ fn main() { void main() { uint idx = gl_GlobalInvocationID.x; - // Each invocation of the compute shader is going to increment the counter, so - // we need to use atomic operations for safety. The previous value of the - // counter is returned so that gives us the offset into the vertex buffer this + // Each invocation of the compute shader is going to increment the counter, so + // we need to use atomic operations for safety. The previous value of the + // counter is returned so that gives us the offset into the vertex buffer this // thread can write it's vertices into. uint offset = atomicAdd(vertices, 6); @@ -375,13 +375,15 @@ fn main() { let command_buffer_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default()); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -389,7 +391,10 @@ fn main() { } => { recreate_swapchain = true; } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { let image_extent: [u32; 2] = window.inner_size().into(); if image_extent.contains(&0) { @@ -538,9 +543,10 @@ fn main() { } } } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/instancing/main.rs b/examples/instancing/main.rs index 6cd95f5261..38867619a4 100644 --- a/examples/instancing/main.rs +++ b/examples/instancing/main.rs @@ -12,7 +12,7 @@ // This is a simple, modified version of the `triangle.rs` example that demonstrates how we can use // the "instancing" technique with vulkano to draw many instances of the triangle. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -71,11 +71,11 @@ struct InstanceData { scale: f32, } -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -319,8 +319,8 @@ fn main() { None, GraphicsPipelineCreateInfo { stages: stages.into_iter().collect(), - // Use the implementations of the `Vertex` trait to describe to vulkano how the two vertex - // types are expected to be used. + // Use the implementations of the `Vertex` trait to describe to vulkano how the two + // vertex types are expected to be used. vertex_input_state: Some(vertex_input_state), input_assembly_state: Some(InputAssemblyState::default()), viewport_state: Some(ViewportState::default()), @@ -350,13 +350,15 @@ fn main() { let command_buffer_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default()); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -364,7 +366,10 @@ fn main() { } => { recreate_swapchain = true; } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { let image_extent: [u32; 2] = window.inner_size().into(); if image_extent.contains(&0) { @@ -465,9 +470,10 @@ fn main() { } } } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/interactive-fractal/app.rs b/examples/interactive-fractal/app.rs index e8095cf7eb..2e9b12ea64 100644 --- a/examples/interactive-fractal/app.rs +++ b/examples/interactive-fractal/app.rs @@ -25,10 +25,8 @@ use vulkano::{ use vulkano_util::{renderer::VulkanoWindowRenderer, window::WindowDescriptor}; use winit::{ dpi::PhysicalPosition, - event::{ - ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, VirtualKeyCode, - WindowEvent, - }, + event::{ElementState, Event, KeyEvent, MouseButton, MouseScrollDelta, WindowEvent}, + keyboard::{Key, NamedKey}, window::Fullscreen, }; @@ -324,9 +322,9 @@ impl InputState { fn handle_input(&mut self, window_size: [f32; 2], event: &Event<()>) { self.window_size = window_size; - if let winit::event::Event::WindowEvent { event, .. } = event { + if let Event::WindowEvent { event, .. } = event { match event { - WindowEvent::KeyboardInput { input, .. } => self.on_keyboard_event(input), + WindowEvent::KeyboardInput { event, .. } => self.on_keyboard_event(event), WindowEvent::MouseInput { state, button, .. } => { self.on_mouse_click_event(*state, *button) } @@ -338,21 +336,19 @@ impl InputState { } /// Matches keyboard events to our defined inputs. - fn on_keyboard_event(&mut self, input: &KeyboardInput) { - if let Some(key_code) = input.virtual_keycode { - match key_code { - VirtualKeyCode::Escape => self.should_quit = state_is_pressed(input.state), - VirtualKeyCode::W => self.pan_up = state_is_pressed(input.state), - VirtualKeyCode::A => self.pan_left = state_is_pressed(input.state), - VirtualKeyCode::S => self.pan_down = state_is_pressed(input.state), - VirtualKeyCode::D => self.pan_right = state_is_pressed(input.state), - VirtualKeyCode::F => self.toggle_full_screen = state_is_pressed(input.state), - VirtualKeyCode::Return => self.randomize_palette = state_is_pressed(input.state), - VirtualKeyCode::Equals => self.increase_iterations = state_is_pressed(input.state), - VirtualKeyCode::Minus => self.decrease_iterations = state_is_pressed(input.state), - VirtualKeyCode::Space => self.toggle_julia = state_is_pressed(input.state), - _ => (), - } + fn on_keyboard_event(&mut self, event: &KeyEvent) { + match event.logical_key.as_ref() { + Key::Named(NamedKey::Escape) => self.should_quit = state_is_pressed(event.state), + Key::Character("w") => self.pan_up = state_is_pressed(event.state), + Key::Character("a") => self.pan_left = state_is_pressed(event.state), + Key::Character("s") => self.pan_down = state_is_pressed(event.state), + Key::Character("d") => self.pan_right = state_is_pressed(event.state), + Key::Character("f") => self.toggle_full_screen = state_is_pressed(event.state), + Key::Named(NamedKey::Enter) => self.randomize_palette = state_is_pressed(event.state), + Key::Character("=") => self.increase_iterations = state_is_pressed(event.state), + Key::Character("-") => self.decrease_iterations = state_is_pressed(event.state), + Key::Named(NamedKey::Space) => self.toggle_julia = state_is_pressed(event.state), + _ => (), } } diff --git a/examples/interactive-fractal/main.rs b/examples/interactive-fractal/main.rs index dcd9a715dd..cf49f7b0ad 100644 --- a/examples/interactive-fractal/main.rs +++ b/examples/interactive-fractal/main.rs @@ -20,6 +20,7 @@ // - A simple `InputState` to interact with the application. use crate::app::FractalApp; +use std::error::Error; use vulkano::{image::ImageUsage, swapchain::PresentMode, sync::GpuFuture}; use vulkano_util::{ context::{VulkanoConfig, VulkanoContext}, @@ -36,9 +37,9 @@ mod fractal_compute_pipeline; mod pixels_draw_pipeline; mod place_over_frame; -fn main() { +fn main() -> Result<(), impl Error> { // Create the event loop. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let context = VulkanoContext::new(VulkanoConfig::default()); let mut windows = VulkanoWindows::default(); let _id = windows.create_window( @@ -74,11 +75,13 @@ fn main() { ); app.print_guide(); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + let renderer = windows.get_primary_renderer_mut().unwrap(); if process_event(renderer, &event, &mut app, render_target_id) { - *control_flow = ControlFlow::Exit; + elwt.exit(); return; } @@ -96,15 +99,20 @@ pub fn process_event( render_target_id: usize, ) -> bool { match &event { - Event::WindowEvent { event, .. } => match event { - WindowEvent::CloseRequested => { - return true; - } - WindowEvent::Resized(..) | WindowEvent::ScaleFactorChanged { .. } => renderer.resize(), - _ => (), - }, - Event::MainEventsCleared => renderer.window().request_redraw(), - Event::RedrawRequested(_) => 'redraw: { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + return true; + } + Event::WindowEvent { + event: WindowEvent::Resized(..) | WindowEvent::ScaleFactorChanged { .. }, + .. + } => renderer.resize(), + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => 'redraw: { // Tasks for redrawing: // 1. Update state based on events // 2. Compute & Render @@ -132,6 +140,7 @@ pub fn process_event( app.max_iters )); } + Event::AboutToWait => renderer.window().request_redraw(), _ => (), } !app.is_running() diff --git a/examples/multi-window-game-of-life/main.rs b/examples/multi-window-game-of-life/main.rs index 023126dd5e..f43624b589 100644 --- a/examples/multi-window-game-of-life/main.rs +++ b/examples/multi-window-game-of-life/main.rs @@ -23,7 +23,7 @@ mod render_pass; use crate::app::{App, RenderPipeline}; use cgmath::Vector2; -use std::time::Instant; +use std::{error::Error, time::Instant}; use vulkano_util::renderer::VulkanoWindowRenderer; use winit::{ event::{ElementState, Event, MouseButton, WindowEvent}, @@ -36,11 +36,11 @@ pub const WINDOW2_WIDTH: f32 = 512.0; pub const WINDOW2_HEIGHT: f32 = 512.0; pub const SCALING: f32 = 2.0; -fn main() { +fn main() -> Result<(), impl Error> { println!("Welcome to Vulkano Game of Life\nUse the mouse to draw life on the grid(s)\n"); // Create event loop. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); // Create app with vulkano context. let mut app = App::default(); @@ -54,7 +54,9 @@ fn main() { let mut mouse_is_pressed_w1 = false; let mut mouse_is_pressed_w2 = false; - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + if process_event( &event, &mut app, @@ -62,8 +64,12 @@ fn main() { &mut mouse_is_pressed_w1, &mut mouse_is_pressed_w2, ) { - *control_flow = ControlFlow::Exit; + elwt.exit(); return; + } else if event == Event::AboutToWait { + for (_, renderer) in app.windows.iter() { + renderer.window().request_redraw(); + } } // Draw life on windows if mouse is down. diff --git a/examples/multi-window/main.rs b/examples/multi-window/main.rs index c210fa807b..8da07b4a8b 100644 --- a/examples/multi-window/main.rs +++ b/examples/multi-window/main.rs @@ -16,7 +16,7 @@ // that you want to learn Vulkan. This means that for example it won't go into details about what a // vertex or a shader is. -use std::{collections::HashMap, sync::Arc}; +use std::{collections::HashMap, error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -51,7 +51,7 @@ use vulkano::{ Validated, VulkanError, VulkanLibrary, }; use winit::{ - event::{ElementState, Event, KeyboardInput, WindowEvent}, + event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, window::{Window, WindowBuilder}, }; @@ -65,11 +65,11 @@ struct WindowSurface { previous_frame_end: Option>, } -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -326,188 +326,198 @@ fn main() { }, ); - event_loop.run(move |event, event_loop, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - window_id, - event: WindowEvent::Resized(_), - .. - } => { - window_surfaces - .get_mut(&window_id) - .unwrap() - .recreate_swapchain = true; - } - Event::WindowEvent { - event: - WindowEvent::KeyboardInput { - input: - KeyboardInput { - state: ElementState::Pressed, - .. - }, - .. - }, - .. - } => { - let window = Arc::new(WindowBuilder::new().build(event_loop).unwrap()); - let surface = Surface::from_window(instance.clone(), window.clone()).unwrap(); - let window_id = window.id(); - let (swapchain, images) = { - let composite_alpha = surface_caps - .supported_composite_alpha - .into_iter() - .next() - .unwrap(); - let image_format = device - .physical_device() - .surface_formats(&surface, Default::default()) - .unwrap()[0] - .0; - - Swapchain::new( - device.clone(), - surface, - SwapchainCreateInfo { - min_image_count: surface_caps.min_image_count.max(2), - image_format, - image_extent: window.inner_size().into(), - image_usage: ImageUsage::COLOR_ATTACHMENT, - composite_alpha, - ..Default::default() + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); + } + Event::WindowEvent { + window_id, + event: WindowEvent::Resized(_), + .. + } => { + window_surfaces + .get_mut(&window_id) + .unwrap() + .recreate_swapchain = true; + } + Event::WindowEvent { + event: + WindowEvent::KeyboardInput { + event: + KeyEvent { + state: ElementState::Pressed, + .. + }, + .. }, - ) - .unwrap() - }; + .. + } => { + let window = Arc::new(WindowBuilder::new().build(elwt).unwrap()); + let surface = Surface::from_window(instance.clone(), window.clone()).unwrap(); + let window_id = window.id(); + let (swapchain, images) = { + let composite_alpha = surface_caps + .supported_composite_alpha + .into_iter() + .next() + .unwrap(); + let image_format = device + .physical_device() + .surface_formats(&surface, Default::default()) + .unwrap()[0] + .0; + + Swapchain::new( + device.clone(), + surface, + SwapchainCreateInfo { + min_image_count: surface_caps.min_image_count.max(2), + image_format, + image_extent: window.inner_size().into(), + image_usage: ImageUsage::COLOR_ATTACHMENT, + composite_alpha, + ..Default::default() + }, + ) + .unwrap() + }; - window_surfaces.insert( + window_surfaces.insert( + window_id, + WindowSurface { + window, + swapchain, + recreate_swapchain: false, + framebuffers: window_size_dependent_setup( + &images, + render_pass.clone(), + &mut viewport, + ), + previous_frame_end: Some(sync::now(device.clone()).boxed()), + }, + ); + } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, window_id, - WindowSurface { + } => { + let WindowSurface { window, swapchain, - recreate_swapchain: false, - framebuffers: window_size_dependent_setup( - &images, - render_pass.clone(), - &mut viewport, - ), - previous_frame_end: Some(sync::now(device.clone()).boxed()), - }, - ); - } - Event::RedrawEventsCleared => { - window_surfaces - .values() - .for_each(|s| s.window.request_redraw()); - } - Event::RedrawRequested(window_id) => { - let WindowSurface { - window, - swapchain, - recreate_swapchain, - framebuffers, - previous_frame_end, - } = window_surfaces.get_mut(&window_id).unwrap(); - - let image_extent: [u32; 2] = window.inner_size().into(); - - if image_extent.contains(&0) { - return; - } + recreate_swapchain, + framebuffers, + previous_frame_end, + } = window_surfaces.get_mut(&window_id).unwrap(); - previous_frame_end.as_mut().unwrap().cleanup_finished(); + let image_extent: [u32; 2] = window.inner_size().into(); - if *recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); + if image_extent.contains(&0) { + return; + } - *swapchain = new_swapchain; - *framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - *recreate_swapchain = false; - } + previous_frame_end.as_mut().unwrap().cleanup_finished(); - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - *recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; + if *recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); - if suboptimal { - *recreate_swapchain = true; - } + *swapchain = new_swapchain; + *framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + *recreate_swapchain = false; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + *recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { + *recreate_swapchain = true; + } - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - match future.map_err(Validated::unwrap) { - Ok(future) => { - *previous_frame_end = Some(future.boxed()); - } - Err(VulkanError::OutOfDate) => { - *recreate_swapchain = true; - *previous_frame_end = Some(sync::now(device.clone()).boxed()); - } - Err(e) => { - println!("failed to flush future: {e}"); - *previous_frame_end = Some(sync::now(device.clone()).boxed()); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + *previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + *recreate_swapchain = true; + *previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + *previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => { + window_surfaces + .values() + .for_each(|s| s.window.request_redraw()); + } + _ => (), } - _ => (), - }); + }) } fn window_size_dependent_setup( diff --git a/examples/occlusion-query/main.rs b/examples/occlusion-query/main.rs index cde850e0cb..883523a7a1 100644 --- a/examples/occlusion-query/main.rs +++ b/examples/occlusion-query/main.rs @@ -11,7 +11,7 @@ // queries. Occlusion queries allow you to query whether, and sometimes how many, pixels pass the // depth test in a range of draw calls. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -54,11 +54,11 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -335,9 +335,9 @@ fn main() { viewport_state: Some(ViewportState::default()), rasterization_state: Some(RasterizationState::default()), multisample_state: Some(MultisampleState::default()), - // Enable depth testing, which is needed for occlusion queries to make sense at all. If you - // disable depth testing, every pixel is considered to pass the depth test, so every query - // will return a nonzero result. + // Enable depth testing, which is needed for occlusion queries to make sense at + // all. If you disable depth testing, every pixel is considered to pass the depth + // test, so every query will return a nonzero result. depth_stencil_state: Some(DepthStencilState { depth: Some(DepthState::simple()), ..Default::default() @@ -373,199 +373,211 @@ fn main() { let mut recreate_swapchain = false; let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - if image_extent.contains(&0) { - return; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = window_size_dependent_setup( - &new_images, - render_pass.clone(), - &mut viewport, - memory_allocator.clone(), - ); - recreate_swapchain = false; + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { + recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + memory_allocator.clone(), + ); + recreate_swapchain = false; + } - if suboptimal { - recreate_swapchain = true; - } + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { + recreate_swapchain = true; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + + // Beginning or resetting a query is unsafe for now. + unsafe { + builder + // A query must be reset before each use, including the first use. This + // must be done outside a render pass. + .reset_query_pool(query_pool.clone(), 0..3) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![ + Some([0.0, 0.0, 1.0, 1.0].into()), + Some(1.0.into()), + ], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + // Begin query 0, then draw the red triangle. Enabling the + // `QueryControlFlags::PRECISE` flag would give exact numeric results. This + // needs the `occlusion_query_precise` feature to be enabled on the device. + .begin_query( + query_pool.clone(), + 0, + QueryControlFlags::empty(), + // QueryControlFlags::PRECISE, + ) + .unwrap() + .bind_vertex_buffers(0, triangle1.clone()) + .unwrap() + .draw(triangle1.len() as u32, 1, 0, 0) + .unwrap() + // End query 0. + .end_query(query_pool.clone(), 0) + .unwrap() + // Begin query 1 for the cyan triangle. + .begin_query(query_pool.clone(), 1, QueryControlFlags::empty()) + .unwrap() + .bind_vertex_buffers(0, triangle2.clone()) + .unwrap() + .draw(triangle2.len() as u32, 1, 0, 0) + .unwrap() + .end_query(query_pool.clone(), 1) + .unwrap() + // Finally, query 2 for the green triangle. + .begin_query(query_pool.clone(), 2, QueryControlFlags::empty()) + .unwrap() + .bind_vertex_buffers(0, triangle3.clone()) + .unwrap() + .draw(triangle3.len() as u32, 1, 0, 0) + .unwrap() + .end_query(query_pool.clone(), 2) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + } - // Beginning or resetting a query is unsafe for now. - unsafe { - builder - // A query must be reset before each use, including the first use. This must be - // done outside a render pass. - .reset_query_pool(query_pool.clone(), 0..3) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() .unwrap() - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into()), Some(1.0.into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) .unwrap() - // Begin query 0, then draw the red triangle. Enabling the - // `QueryControlFlags::PRECISE` flag would give exact numeric results. This - // needs the `occlusion_query_precise` feature to be enabled on the device. - .begin_query( - query_pool.clone(), - 0, - QueryControlFlags::empty(), - // QueryControlFlags::PRECISE, + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), ) - .unwrap() - .bind_vertex_buffers(0, triangle1.clone()) - .unwrap() - .draw(triangle1.len() as u32, 1, 0, 0) - .unwrap() - // End query 0. - .end_query(query_pool.clone(), 0) - .unwrap() - // Begin query 1 for the cyan triangle. - .begin_query(query_pool.clone(), 1, QueryControlFlags::empty()) - .unwrap() - .bind_vertex_buffers(0, triangle2.clone()) - .unwrap() - .draw(triangle2.len() as u32, 1, 0, 0) - .unwrap() - .end_query(query_pool.clone(), 1) - .unwrap() - // Finally, query 2 for the green triangle. - .begin_query(query_pool.clone(), 2, QueryControlFlags::empty()) - .unwrap() - .bind_vertex_buffers(0, triangle3.clone()) - .unwrap() - .draw(triangle3.len() as u32, 1, 0, 0) - .unwrap() - .end_query(query_pool.clone(), 2) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - } + .then_signal_fence_and_flush(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); - } - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); - } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } - } - // Retrieve the query results. This copies the results to a variable on the CPU. You - // can also use the `copy_query_pool_results` function on a command buffer to write - // results to a Vulkano buffer. This could then be used to influence draw operations - // further down the line, either in the same frame or a future frame. - #[rustfmt::skip] - query_pool.get_results( - 0..3, - &mut query_results, - // Block the function call until the results are available. - // NOTE: If not all the queries have actually been executed, then this will - // wait forever for something that never happens! - QueryResultFlags::WAIT - - // Enable this flag to give partial results if available, instead of waiting - // for the full results. - // | QueryResultFlags::PARTIAL - - // Blocking and waiting will ensure the results are always available after the - // function returns. - // - // If you disable waiting, then this flag can be enabled to include the - // availability of each query's results. You need one extra element per query - // in your `query_results` buffer for this. This element will be filled with a - // zero/nonzero value indicating availability. - // | QueryResultFlags::WITH_AVAILABILITY - ) - .unwrap(); + // Retrieve the query results. This copies the results to a variable on the CPU. + // You can also use the `copy_query_pool_results` function on a command buffer to + // write results to a Vulkano buffer. This could then be used to influence draw + // operations further down the line, either in the same frame or a future frame. + #[rustfmt::skip] + query_pool.get_results( + 0..3, + &mut query_results, + // Block the function call until the results are available. + // NOTE: If not all the queries have actually been executed, then this will + // wait forever for something that never happens! + QueryResultFlags::WAIT + + // Enable this flag to give partial results if available, instead of waiting + // for the full results. + // | QueryResultFlags::PARTIAL + + // Blocking and waiting will ensure the results are always available after the + // function returns. + // + // If you disable waiting, then this flag can be enabled to include the + // availability of each query's results. You need one extra element per query + // in your `query_results` buffer for this. This element will be filled with a + // zero/nonzero value indicating availability. + // | QueryResultFlags::WITH_AVAILABILITY + ) + .unwrap(); - // If the `precise` bit was not enabled, then you're only guaranteed to get a boolean - // result here: zero if all pixels were occluded, nonzero if only some were occluded. - // Enabling `precise` will give the exact number of pixels. + // If the `precise` bit was not enabled, then you're only guaranteed to get a + // boolean result here: zero if all pixels were occluded, nonzero if only some were + // occluded. Enabling `precise` will give the exact number of pixels. - // Query 0 (red triangle) will always succeed, because the depth buffer starts empty - // and will never occlude anything. - assert_ne!(query_results[0], 0); + // Query 0 (red triangle) will always succeed, because the depth buffer starts + // empty and will never occlude anything. + assert_ne!(query_results[0], 0); - // Query 1 (cyan triangle) will fail, because it's drawn completely behind the first. - assert_eq!(query_results[1], 0); + // Query 1 (cyan triangle) will fail, because it's drawn completely behind the + // first. + assert_eq!(query_results[1], 0); - // Query 2 (green triangle) will succeed, because it's only partially occluded. - assert_ne!(query_results[2], 0); + // Query 2 (green triangle) will succeed, because it's only partially occluded. + assert_ne!(query_results[2], 0); + } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } fn window_size_dependent_setup( diff --git a/examples/push-descriptors/main.rs b/examples/push-descriptors/main.rs index b1e05eacf3..bfbc479c25 100644 --- a/examples/push-descriptors/main.rs +++ b/examples/push-descriptors/main.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -54,11 +54,11 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -353,127 +353,138 @@ fn main() { .boxed(), ); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); - - if image_extent.contains(&0) { - return; - } + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .push_descriptor_set( - PipelineBindPoint::Graphics, - pipeline.layout().clone(), - 0, - [ - // If the binding is an immutable sampler, using push descriptors - // you must write a dummy value to the binding. - WriteDescriptorSet::none(0), - WriteDescriptorSet::image_view(1, texture.clone()), - ] - .into_iter() - .collect(), - ) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .push_descriptor_set( + PipelineBindPoint::Graphics, + pipeline.layout().clone(), + 0, + [ + // If the binding is an immutable sampler, using push descriptors + // you must write a dummy value to the binding. + WriteDescriptorSet::none(0), + WriteDescriptorSet::image_view(1, texture.clone()), + ] + .into_iter() + .collect(), + ) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/runtime-array/main.rs b/examples/runtime-array/main.rs index 2561849e05..ae438a8351 100644 --- a/examples/runtime-array/main.rs +++ b/examples/runtime-array/main.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::{io::Cursor, sync::Arc}; +use std::{error::Error, io::Cursor, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -57,14 +57,14 @@ use winit::{ window::WindowBuilder, }; -fn main() { +fn main() -> Result<(), impl Error> { // The start of this example is exactly the same as `triangle`. You should read the `triangle` // example if you haven't done so yet. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -484,120 +484,131 @@ fn main() { .boxed(), ); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); - - if image_extent.contains(&0) { - return; - } + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_descriptor_sets( - PipelineBindPoint::Graphics, - pipeline.layout().clone(), - 0, - set.clone(), - ) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .bind_descriptor_sets( + PipelineBindPoint::Graphics, + pipeline.layout().clone(), + 0, + set.clone(), + ) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/runtime-shader/main.rs b/examples/runtime-shader/main.rs index 28065172ad..8a6a11b224 100644 --- a/examples/runtime-shader/main.rs +++ b/examples/runtime-shader/main.rs @@ -21,7 +21,7 @@ // // Vulkano uses shaderc to build your shaders internally. -use std::{fs::File, io::Read, path::Path, sync::Arc}; +use std::{error::Error, fs::File, io::Read, path::Path, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -62,11 +62,11 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -296,113 +296,124 @@ fn main() { let command_buffer_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default()); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - if image_extent.contains(&0) { - return; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; - } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::MultipleSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(graphics_pipeline.clone()) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::MultipleSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(graphics_pipeline.clone()) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/simple-particles/main.rs b/examples/simple-particles/main.rs index 4798492c04..083b105336 100644 --- a/examples/simple-particles/main.rs +++ b/examples/simple-particles/main.rs @@ -12,7 +12,7 @@ // staging buffer and then copying the data to a device-local buffer to be accessed solely by the // GPU through the compute shader and as a vertex array. -use std::{sync::Arc, time::SystemTime}; +use std::{error::Error, sync::Arc, time::SystemTime}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -63,13 +63,13 @@ const WINDOW_HEIGHT: u32 = 600; const PARTICLE_COUNT: usize = 100_000; -fn main() { +fn main() -> Result<(), impl Error> { // The usual Vulkan initialization. Largely the same as example `triangle.rs` until further // commentation is provided. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -521,15 +521,20 @@ fn main() { let start_time = SystemTime::now(); let mut last_frame_time = start_time; - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { let image_extent: [u32; 2] = window.inner_size().into(); if image_extent.contains(&0) { @@ -644,7 +649,8 @@ fn main() { }; previous_fence_index = image_index; } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } diff --git a/examples/teapot/main.rs b/examples/teapot/main.rs index 5354cd1888..c430a7cfb9 100644 --- a/examples/teapot/main.rs +++ b/examples/teapot/main.rs @@ -9,7 +9,7 @@ use self::model::{Normal, Position, INDICES, NORMALS, POSITIONS}; use cgmath::{Matrix3, Matrix4, Point3, Rad, Vector3}; -use std::{sync::Arc, time::Instant}; +use std::{error::Error, sync::Arc, time::Instant}; use vulkano::{ buffer::{ allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}, @@ -55,20 +55,20 @@ use vulkano::{ }; use winit::{ event::{Event, WindowEvent}, - event_loop::{ControlFlow, EventLoop}, + event_loop::EventLoop, window::WindowBuilder, }; mod model; -fn main() { +fn main() -> Result<(), impl Error> { // The start of this example is exactly the same as `triangle`. You should read the `triangle` // example if you haven't done so yet. - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -265,13 +265,13 @@ fn main() { let command_buffer_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default()); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -279,7 +279,10 @@ fn main() { } => { recreate_swapchain = true; } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { let image_extent: [u32; 2] = window.inner_size().into(); if image_extent.contains(&0) { @@ -432,9 +435,10 @@ fn main() { } } } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/tessellation/main.rs b/examples/tessellation/main.rs index eff10e9b62..9de5d95e7a 100644 --- a/examples/tessellation/main.rs +++ b/examples/tessellation/main.rs @@ -21,7 +21,7 @@ // - `tessellation_shaders` and `tessellation_state` are called on the pipeline builder. // - The use of `PrimitiveTopology::PatchList`. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -159,11 +159,11 @@ mod fs { } } -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -414,113 +414,124 @@ fn main() { let command_buffer_allocator = StandardCommandBufferAllocator::new(device.clone(), Default::default()); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - if image_extent.contains(&0) { - return; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; - } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 1, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 1, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/texture-array/main.rs b/examples/texture-array/main.rs index 34e3fe8418..8ac3835607 100644 --- a/examples/texture-array/main.rs +++ b/examples/texture-array/main.rs @@ -7,7 +7,7 @@ // notice may not be copied, modified, or distributed except // according to those terms. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -56,16 +56,16 @@ use winit::{ window::WindowBuilder, }; -fn main() { +fn main() -> Result<(), impl Error> { // This example is about this: // uniform sampler2DArray texture_array; // And not this: // uniform sampler2D array_of_textures[42]; - let event_loop = EventLoop::new(); + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); let instance = Instance::new( library, InstanceCreateInfo { @@ -374,120 +374,131 @@ fn main() { .boxed(), ); - event_loop.run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => { - *control_flow = ControlFlow::Exit; - } - Event::WindowEvent { - event: WindowEvent::Resized(_), - .. - } => { - recreate_swapchain = true; - } - Event::RedrawEventsCleared => { - let image_extent: [u32; 2] = window.inner_size().into(); - - if image_extent.contains(&0) { - return; - } + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); - previous_frame_end.as_mut().unwrap().cleanup_finished(); - - if recreate_swapchain { - let (new_swapchain, new_images) = swapchain - .recreate(SwapchainCreateInfo { - image_extent, - ..swapchain.create_info() - }) - .expect("failed to recreate swapchain"); - - swapchain = new_swapchain; - framebuffers = - window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); - recreate_swapchain = false; + match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => { + elwt.exit(); } - - let (image_index, suboptimal, acquire_future) = - match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { - Ok(r) => r, - Err(VulkanError::OutOfDate) => { - recreate_swapchain = true; - return; - } - Err(e) => panic!("failed to acquire next image: {e}"), - }; - - if suboptimal { + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { recreate_swapchain = true; } + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { + let image_extent: [u32; 2] = window.inner_size().into(); + + if image_extent.contains(&0) { + return; + } - let mut builder = AutoCommandBufferBuilder::primary( - &command_buffer_allocator, - queue.queue_family_index(), - CommandBufferUsage::OneTimeSubmit, - ) - .unwrap(); - builder - .begin_render_pass( - RenderPassBeginInfo { - clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], - ..RenderPassBeginInfo::framebuffer( - framebuffers[image_index as usize].clone(), - ) - }, - Default::default(), - ) - .unwrap() - .set_viewport(0, [viewport.clone()].into_iter().collect()) - .unwrap() - .bind_pipeline_graphics(pipeline.clone()) - .unwrap() - .bind_descriptor_sets( - PipelineBindPoint::Graphics, - pipeline.layout().clone(), - 0, - set.clone(), - ) - .unwrap() - .bind_vertex_buffers(0, vertex_buffer.clone()) - .unwrap() - .draw(vertex_buffer.len() as u32, 3, 0, 0) - .unwrap() - .end_render_pass(Default::default()) - .unwrap(); - let command_buffer = builder.build().unwrap(); - - let future = previous_frame_end - .take() - .unwrap() - .join(acquire_future) - .then_execute(queue.clone(), command_buffer) - .unwrap() - .then_swapchain_present( - queue.clone(), - SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), - ) - .then_signal_fence_and_flush(); - - match future.map_err(Validated::unwrap) { - Ok(future) => { - previous_frame_end = Some(future.boxed()); + previous_frame_end.as_mut().unwrap().cleanup_finished(); + + if recreate_swapchain { + let (new_swapchain, new_images) = swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..swapchain.create_info() + }) + .expect("failed to recreate swapchain"); + + swapchain = new_swapchain; + framebuffers = window_size_dependent_setup( + &new_images, + render_pass.clone(), + &mut viewport, + ); + recreate_swapchain = false; } - Err(VulkanError::OutOfDate) => { + + let (image_index, suboptimal, acquire_future) = + match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) { + Ok(r) => r, + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + return; + } + Err(e) => panic!("failed to acquire next image: {e}"), + }; + + if suboptimal { recreate_swapchain = true; - previous_frame_end = Some(sync::now(device.clone()).boxed()); } - Err(e) => { - println!("failed to flush future: {e}"); - previous_frame_end = Some(sync::now(device.clone()).boxed()); + + let mut builder = AutoCommandBufferBuilder::primary( + &command_buffer_allocator, + queue.queue_family_index(), + CommandBufferUsage::OneTimeSubmit, + ) + .unwrap(); + builder + .begin_render_pass( + RenderPassBeginInfo { + clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())], + ..RenderPassBeginInfo::framebuffer( + framebuffers[image_index as usize].clone(), + ) + }, + Default::default(), + ) + .unwrap() + .set_viewport(0, [viewport.clone()].into_iter().collect()) + .unwrap() + .bind_pipeline_graphics(pipeline.clone()) + .unwrap() + .bind_descriptor_sets( + PipelineBindPoint::Graphics, + pipeline.layout().clone(), + 0, + set.clone(), + ) + .unwrap() + .bind_vertex_buffers(0, vertex_buffer.clone()) + .unwrap() + .draw(vertex_buffer.len() as u32, 3, 0, 0) + .unwrap() + .end_render_pass(Default::default()) + .unwrap(); + let command_buffer = builder.build().unwrap(); + + let future = previous_frame_end + .take() + .unwrap() + .join(acquire_future) + .then_execute(queue.clone(), command_buffer) + .unwrap() + .then_swapchain_present( + queue.clone(), + SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index), + ) + .then_signal_fence_and_flush(); + + match future.map_err(Validated::unwrap) { + Ok(future) => { + previous_frame_end = Some(future.boxed()); + } + Err(VulkanError::OutOfDate) => { + recreate_swapchain = true; + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } + Err(e) => { + println!("failed to flush future: {e}"); + previous_frame_end = Some(sync::now(device.clone()).boxed()); + } } } + Event::AboutToWait => window.request_redraw(), + _ => (), } - _ => (), - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/triangle-v1_3/main.rs b/examples/triangle-v1_3/main.rs index 9a3e3464c3..4e75973c1a 100644 --- a/examples/triangle-v1_3/main.rs +++ b/examples/triangle-v1_3/main.rs @@ -21,7 +21,7 @@ // `khr_dynamic_rendering` extension, or if you want to see how to support older versions, see the // original triangle example. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -62,8 +62,8 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); @@ -74,7 +74,7 @@ fn main() { // All the window-drawing functionalities are part of non-core extensions that we need to // enable manually. To do so, we ask `Surface` for the list of extensions required to draw to // a window. - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); // Now creating the instance. let instance = Instance::new( @@ -515,13 +515,15 @@ fn main() { // that, we store the submission of the previous frame here. let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -529,7 +531,10 @@ fn main() { } => { recreate_swapchain = true; } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { // Do not draw the frame when the screen size is zero. On Windows, this can // occur when minimizing the application. let image_extent: [u32; 2] = window.inner_size().into(); @@ -688,9 +693,10 @@ fn main() { } } } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/examples/triangle/main.rs b/examples/triangle/main.rs index 872af91d0f..c005717e94 100644 --- a/examples/triangle/main.rs +++ b/examples/triangle/main.rs @@ -16,7 +16,7 @@ // that you want to learn Vulkan. This means that for example it won't go into details about what a // vertex or a shader is. -use std::sync::Arc; +use std::{error::Error, sync::Arc}; use vulkano::{ buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, command_buffer::{ @@ -56,8 +56,8 @@ use winit::{ window::WindowBuilder, }; -fn main() { - let event_loop = EventLoop::new(); +fn main() -> Result<(), impl Error> { + let event_loop = EventLoop::new().unwrap(); let library = VulkanLibrary::new().unwrap(); @@ -68,7 +68,7 @@ fn main() { // All the window-drawing functionalities are part of non-core extensions that we need to // enable manually. To do so, we ask `Surface` for the list of extensions required to draw to // a window. - let required_extensions = Surface::required_extensions(&event_loop); + let required_extensions = Surface::required_extensions(&event_loop).unwrap(); // Now creating the instance. let instance = Instance::new( @@ -512,13 +512,15 @@ fn main() { // that, we store the submission of the previous frame here. let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); - event_loop.run(move |event, _, control_flow| { + event_loop.run(move |event, elwt| { + elwt.set_control_flow(ControlFlow::Poll); + match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { - *control_flow = ControlFlow::Exit; + elwt.exit(); } Event::WindowEvent { event: WindowEvent::Resized(_), @@ -526,7 +528,10 @@ fn main() { } => { recreate_swapchain = true; } - Event::RedrawEventsCleared => { + Event::WindowEvent { + event: WindowEvent::RedrawRequested, + .. + } => { // Do not draw the frame when the screen size is zero. On Windows, this can // occur when minimizing the application. let image_extent: [u32; 2] = window.inner_size().into(); @@ -687,9 +692,10 @@ fn main() { } } } + Event::AboutToWait => window.request_redraw(), _ => (), } - }); + }) } /// This function is called once during initialization, then again whenever the window is resized. diff --git a/vulkano-macros/Cargo.toml b/vulkano-macros/Cargo.toml index 5f54724e08..b89ec69273 100644 --- a/vulkano-macros/Cargo.toml +++ b/vulkano-macros/Cargo.toml @@ -20,6 +20,3 @@ syn = { workspace = true } quote = { workspace = true } proc-macro2 = { workspace = true } proc-macro-crate = { workspace = true } - -[dev-dependencies] -vulkano = { workspace = true } diff --git a/vulkano-macros/src/derive_buffer_contents.rs b/vulkano-macros/src/derive_buffer_contents.rs index a3089b5c00..4b5a8872c0 100644 --- a/vulkano-macros/src/derive_buffer_contents.rs +++ b/vulkano-macros/src/derive_buffer_contents.rs @@ -12,31 +12,32 @@ use proc_macro2::TokenStream; use quote::{quote, quote_spanned}; use syn::{ parse_quote, spanned::Spanned, Data, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Ident, - Meta, MetaList, NestedMeta, Result, Type, TypeArray, TypeSlice, WherePredicate, + Result, Type, TypeArray, TypeSlice, WherePredicate, }; -pub fn derive_buffer_contents(mut ast: DeriveInput) -> Result { - let crate_ident = crate::crate_ident(); - +pub fn derive_buffer_contents(crate_ident: &Ident, mut ast: DeriveInput) -> Result { let struct_ident = &ast.ident; - if !ast + let is_repr_rust = ast .attrs .iter() - .filter(|&attr| attr.path.is_ident("repr")) - .map(|attr| attr.parse_meta().unwrap()) - .any(|meta| match meta { - Meta::List(MetaList { nested, .. }) => { - nested.iter().any(|nested_meta| match nested_meta { - NestedMeta::Meta(Meta::Path(path)) => { - path.is_ident("C") || path.is_ident("transparent") - } - _ => false, - }) - } - _ => false, + .filter(|&attr| attr.path().is_ident("repr")) + .map(|attr| { + let mut is_repr_rust = true; + + let _ = attr.parse_nested_meta(|meta| { + if meta.path.is_ident("C") || meta.path.is_ident("transparent") { + is_repr_rust = false; + } + + Ok(()) + }); + + is_repr_rust }) - { + .all(|b| b); + + if is_repr_rust { bail!( "deriving `BufferContents` is only supported for types that are marked `#[repr(C)]` \ or `#[repr(transparent)]`", @@ -60,7 +61,7 @@ pub fn derive_buffer_contents(mut ast: DeriveInput) -> Result { ast.generics.split_for_impl() }; - let layout = write_layout(&crate_ident, &ast)?; + let layout = write_layout(crate_ident, &ast)?; Ok(quote! { #[allow(unsafe_code)] @@ -266,25 +267,28 @@ fn find_innermost_element_type(mut field_type: &Type) -> &Type { #[cfg(test)] mod tests { use super::*; + use proc_macro2::Span; #[test] fn repr() { + let crate_ident = Ident::new("vulkano", Span::call_site()); + let default_repr = parse_quote! { struct Test(u8, [u8]); }; - assert!(derive_buffer_contents(default_repr).is_err()); + assert!(derive_buffer_contents(&crate_ident, default_repr).is_err()); let irellevant_reprs = parse_quote! { #[repr(packed(2), align(16))] struct Test(u8, [u8]); }; - assert!(derive_buffer_contents(irellevant_reprs).is_err()); + assert!(derive_buffer_contents(&crate_ident, irellevant_reprs).is_err()); let transparent_repr = parse_quote! { #[repr(transparent)] struct Test([u8]); }; - assert!(derive_buffer_contents(transparent_repr).is_ok()); + assert!(derive_buffer_contents(&crate_ident, transparent_repr).is_ok()); let multiple_reprs = parse_quote! { #[repr(align(16))] @@ -292,24 +296,28 @@ mod tests { #[repr(packed)] struct Test(u8, [u8]); }; - assert!(derive_buffer_contents(multiple_reprs).is_ok()); + assert!(derive_buffer_contents(&crate_ident, multiple_reprs).is_ok()); } #[test] fn zero_sized() { + let crate_ident = Ident::new("vulkano", Span::call_site()); + let unit = parse_quote! { struct Test; }; - assert!(derive_buffer_contents(unit).is_err()); + assert!(derive_buffer_contents(&crate_ident, unit).is_err()); } #[test] fn unsupported_datatype() { + let crate_ident = Ident::new("vulkano", Span::call_site()); + let enum_ = parse_quote! { #[repr(C)] enum Test { A, B, C } }; - assert!(derive_buffer_contents(enum_).is_err()); + assert!(derive_buffer_contents(&crate_ident, enum_).is_err()); let union = parse_quote! { #[repr(C)] @@ -318,6 +326,6 @@ mod tests { b: f32, } }; - assert!(derive_buffer_contents(union).is_err()); + assert!(derive_buffer_contents(&crate_ident, union).is_err()); } } diff --git a/vulkano-macros/src/derive_vertex.rs b/vulkano-macros/src/derive_vertex.rs index bf4883a9e9..c96408f2fd 100644 --- a/vulkano-macros/src/derive_vertex.rs +++ b/vulkano-macros/src/derive_vertex.rs @@ -16,7 +16,7 @@ use syn::{ Data, DataStruct, Fields, Ident, LitStr, Result, Token, }; -pub fn derive_vertex(ast: syn::DeriveInput) -> Result { +pub fn derive_vertex(crate_ident: &Ident, ast: syn::DeriveInput) -> Result { let struct_name = &ast.ident; let fields = match &ast.data { @@ -27,8 +27,6 @@ pub fn derive_vertex(ast: syn::DeriveInput) -> Result { _ => bail!("expected a struct with named fields"), }; - let crate_ident = crate::crate_ident(); - let mut members = quote! { let mut offset = 0; let mut members = ::std::collections::HashMap::default(); @@ -41,7 +39,7 @@ pub fn derive_vertex(ast: syn::DeriveInput) -> Result { let mut names = vec![field_name_lit.clone()]; let mut format = quote! {}; for attr in &field.attrs { - let attr_ident = if let Some(ident) = attr.path.get_ident() { + let attr_ident = if let Some(ident) = attr.path().get_ident() { ident } else { continue; @@ -134,7 +132,7 @@ struct NameMeta { impl Parse for NameMeta { fn parse(input: ParseStream) -> Result { Ok(Self { - lit_str_list: input.parse_terminated(::parse)?, + lit_str_list: input.parse_terminated(::parse, Token![,])?, }) } } diff --git a/vulkano-macros/src/lib.rs b/vulkano-macros/src/lib.rs index 9649f30e78..a9b0507b0c 100644 --- a/vulkano-macros/src/lib.rs +++ b/vulkano-macros/src/lib.rs @@ -24,8 +24,9 @@ mod derive_vertex; #[proc_macro_derive(Vertex, attributes(name, format))] pub fn derive_vertex(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); + let crate_ident = crate_ident(); - derive_vertex::derive_vertex(ast) + derive_vertex::derive_vertex(&crate_ident, ast) .unwrap_or_else(Error::into_compile_error) .into() } @@ -36,8 +37,9 @@ pub fn derive_vertex(input: TokenStream) -> TokenStream { #[proc_macro_derive(BufferContents)] pub fn derive_buffer_contents(input: TokenStream) -> TokenStream { let ast = parse_macro_input!(input as DeriveInput); + let crate_ident = crate_ident(); - derive_buffer_contents::derive_buffer_contents(ast) + derive_buffer_contents::derive_buffer_contents(&crate_ident, ast) .unwrap_or_else(Error::into_compile_error) .into() } diff --git a/vulkano/Cargo.toml b/vulkano/Cargo.toml index c9a10ddc58..a1d2727d66 100644 --- a/vulkano/Cargo.toml +++ b/vulkano/Cargo.toml @@ -22,7 +22,7 @@ half = { workspace = true, features = ["bytemuck"] } libloading = { workspace = true } once_cell = { workspace = true } parking_lot = { workspace = true, features = ["send_guard"] } -raw-window-handle = { workspace = true } +raw-window-handle = { workspace = true, features = ["std"] } serde = { workspace = true, optional = true } smallvec = { workspace = true } thread_local = { workspace = true } diff --git a/vulkano/src/pipeline/layout.rs b/vulkano/src/pipeline/layout.rs index e687d208ae..a1e53e395d 100644 --- a/vulkano/src/pipeline/layout.rs +++ b/vulkano/src/pipeline/layout.rs @@ -295,7 +295,7 @@ impl PipelineLayout { #[inline] pub fn is_compatible_with(&self, other: &PipelineLayout, num_sets: u32) -> bool { let num_sets = num_sets as usize; - assert!(num_sets >= self.set_layouts.len()); + assert!(num_sets <= self.set_layouts.len()); if self == other { return true; diff --git a/vulkano/src/swapchain/surface.rs b/vulkano/src/swapchain/surface.rs index 28da3313c3..fc14c6f41e 100644 --- a/vulkano/src/swapchain/surface.rs +++ b/vulkano/src/swapchain/surface.rs @@ -22,12 +22,13 @@ use crate::{ #[cfg(any(target_os = "macos", target_os = "ios"))] use objc::{class, msg_send, runtime::Object, sel, sel_impl}; use raw_window_handle::{ - HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, + HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle, }; use smallvec::SmallVec; use std::{ any::Any, - fmt::{Debug, Error as FmtError, Formatter}, + error::Error, + fmt::{Debug, Display, Error as FmtError, Formatter}, mem::MaybeUninit, num::NonZeroU64, ptr, @@ -60,12 +61,14 @@ pub struct Surface { impl Surface { /// Returns the instance extensions required to create a surface from a window of the given /// event loop. - pub fn required_extensions(event_loop: &impl HasRawDisplayHandle) -> InstanceExtensions { + pub fn required_extensions( + event_loop: &impl HasDisplayHandle, + ) -> Result { let mut extensions = InstanceExtensions { khr_surface: true, ..InstanceExtensions::empty() }; - match event_loop.raw_display_handle() { + match event_loop.display_handle()?.as_raw() { RawDisplayHandle::Android(_) => extensions.khr_android_surface = true, // FIXME: `mvk_macos_surface` and `mvk_ios_surface` are deprecated. RawDisplayHandle::AppKit(_) => extensions.mvk_macos_surface = true, @@ -77,14 +80,14 @@ impl Surface { _ => unimplemented!(), } - extensions + Ok(extensions) } /// Creates a new `Surface` from the given `window`. pub fn from_window( instance: Arc, - window: Arc, - ) -> Result, Validated> { + window: Arc, + ) -> Result, FromWindowError> { let mut surface = unsafe { Self::from_window_ref(instance, &*window) }?; Arc::get_mut(&mut surface).unwrap().object = Some(window); @@ -99,43 +102,67 @@ impl Surface { /// - The given `window` must outlive the created surface. pub unsafe fn from_window_ref( instance: Arc, - window: &(impl HasRawWindowHandle + HasRawDisplayHandle), - ) -> Result, Validated> { - match (window.raw_window_handle(), window.raw_display_handle()) { + window: &(impl HasWindowHandle + HasDisplayHandle), + ) -> Result, FromWindowError> { + let window_handle = window + .window_handle() + .map_err(FromWindowError::RetrieveHandle)?; + let display_handle = window + .display_handle() + .map_err(FromWindowError::RetrieveHandle)?; + + match (window_handle.as_raw(), display_handle.as_raw()) { (RawWindowHandle::AndroidNdk(window), RawDisplayHandle::Android(_display)) => { - Self::from_android(instance, window.a_native_window, None) + Self::from_android(instance, window.a_native_window.as_ptr(), None) } #[cfg(target_os = "macos")] (RawWindowHandle::AppKit(window), RawDisplayHandle::AppKit(_display)) => { // Ensure the layer is `CAMetalLayer`. - let layer = get_metal_layer_macos(window.ns_view); + let layer = get_metal_layer_macos(window.ns_view.as_ptr()); Self::from_mac_os(instance, layer as *const (), None) } #[cfg(target_os = "ios")] (RawWindowHandle::UiKit(window), RawDisplayHandle::UiKit(_display)) => { // Ensure the layer is `CAMetalLayer`. - let layer = get_metal_layer_ios(window.ui_view); + let layer = get_metal_layer_ios(window.ui_view.as_ptr()); Self::from_ios(instance, layer, None) } (RawWindowHandle::Wayland(window), RawDisplayHandle::Wayland(display)) => { - Self::from_wayland(instance, display.display, window.surface, None) + Self::from_wayland( + instance, + display.display.as_ptr(), + window.surface.as_ptr(), + None, + ) } (RawWindowHandle::Win32(window), RawDisplayHandle::Windows(_display)) => { - Self::from_win32(instance, window.hinstance, window.hwnd, None) - } - (RawWindowHandle::Xcb(window), RawDisplayHandle::Xcb(display)) => { - Self::from_xcb(instance, display.connection, window.window, None) - } - (RawWindowHandle::Xlib(window), RawDisplayHandle::Xlib(display)) => { - Self::from_xlib(instance, display.display, window.window, None) + Self::from_win32( + instance, + window.hinstance.unwrap().get() as *const (), + window.hwnd.get() as *const (), + None, + ) } + (RawWindowHandle::Xcb(window), RawDisplayHandle::Xcb(display)) => Self::from_xcb( + instance, + display.connection.unwrap().as_ptr(), + window.window.get(), + None, + ), + (RawWindowHandle::Xlib(window), RawDisplayHandle::Xlib(display)) => Self::from_xlib( + instance, + display.display.unwrap().as_ptr(), + window.window, + None, + ), _ => unimplemented!( "the window was created with a windowing API that is not supported \ by Vulkan/Vulkano" ), } + .map_err(FromWindowError::CreateSurface) } /// Creates a `Surface` from a raw handle. @@ -2335,6 +2362,35 @@ pub struct SurfaceCapabilities { pub full_screen_exclusive_supported: bool, } +/// Error that can happen when creating a [`Surface`] from a window. +#[derive(Clone, Debug)] +pub enum FromWindowError { + /// Retrieving the window or display handle failed. + RetrieveHandle(HandleError), + /// Creating the surface failed. + CreateSurface(Validated), +} + +impl Error for FromWindowError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + Self::RetrieveHandle(err) => Some(err), + Self::CreateSurface(err) => Some(err), + } + } +} + +impl Display for FromWindowError { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { + match self { + Self::RetrieveHandle(_) => { + write!(f, "retrieving the window or display handle has failed") + } + Self::CreateSurface(_) => write!(f, "creating the surface has failed"), + } + } +} + #[cfg(test)] mod tests { use crate::{