Update dependencies (#2385)

* Update winit

* Update raw-window-handle

* Update syn

* Remove vulkano-win from the workspace
This commit is contained in:
marc0246 2023-10-31 18:47:17 +01:00 committed by GitHub
parent 3664c079f7
commit 4a77d39b85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 1852 additions and 1596 deletions

View File

@ -4,7 +4,7 @@ members = [
"vulkano-macros", "vulkano-macros",
"vulkano-shaders", "vulkano-shaders",
"vulkano-util", "vulkano-util",
"vulkano-win", # "vulkano-win",
] ]
resolver = "2" resolver = "2"
@ -44,13 +44,13 @@ parking_lot = "0.12"
proc-macro2 = "1.0" proc-macro2 = "1.0"
proc-macro-crate = "1.2" proc-macro-crate = "1.2"
quote = "1.0" quote = "1.0"
raw-window-handle = "0.5" raw-window-handle = "0.6"
regex = "1.8" regex = "1.8"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
shaderc = "0.8" shaderc = "0.8"
smallvec = "1.8" smallvec = "1.8"
syn = "1.0" syn = "2.0"
thread_local = "1.1" thread_local = "1.1"
vk-parse = "0.12" vk-parse = "0.12"
winit = "0.28" winit = "0.29"

View File

@ -12,4 +12,4 @@ vulkano = { path = "../vulkano" }
vulkano-macros = { path = "../vulkano-macros" } vulkano-macros = { path = "../vulkano-macros" }
vulkano-shaders = { path = "../vulkano-shaders" } vulkano-shaders = { path = "../vulkano-shaders" }
vulkano-util = { path = "../vulkano-util" } vulkano-util = { path = "../vulkano-util" }
winit = "0.28" winit = "0.29"

View File

@ -39,6 +39,7 @@
use cgmath::{Matrix4, Rad}; use cgmath::{Matrix4, Rad};
use rand::Rng; use rand::Rng;
use std::{ use std::{
error::Error,
hint, hint,
sync::{ sync::{
atomic::{AtomicBool, AtomicU64, Ordering}, atomic::{AtomicBool, AtomicU64, Ordering},
@ -91,18 +92,19 @@ use vulkano::{
Validated, VulkanError, VulkanLibrary, Validated, VulkanError, VulkanLibrary,
}; };
use winit::{ use winit::{
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
keyboard::{Key, NamedKey},
window::WindowBuilder, window::WindowBuilder,
}; };
const TRANSFER_GRANULARITY: u32 = 4096; const TRANSFER_GRANULARITY: u32 = 4096;
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -521,13 +523,15 @@ fn main() {
println!("\nPress space to update part of the texture"); 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -538,10 +542,10 @@ fn main() {
Event::WindowEvent { Event::WindowEvent {
event: event:
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
input: event:
KeyboardInput { KeyEvent {
logical_key: Key::Named(NamedKey::Space),
state: ElementState::Released, state: ElementState::Released,
virtual_keycode: Some(VirtualKeyCode::Space),
.. ..
}, },
.. ..
@ -550,7 +554,10 @@ fn main() {
} => { } => {
channel.send(()).unwrap(); channel.send(()).unwrap();
} }
Event::RedrawEventsCleared => { Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into(); let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) { if image_extent.contains(&0) {
@ -685,9 +692,10 @@ fn main() {
} }
} }
} }
Event::AboutToWait => window.request_redraw(),
_ => (), _ => (),
} }
}); })
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]

View File

@ -10,6 +10,7 @@
// Modified triangle example to show `SubbufferAllocator`. // Modified triangle example to show `SubbufferAllocator`.
use std::{ use std::{
error::Error,
sync::Arc, sync::Arc,
time::{SystemTime, UNIX_EPOCH}, time::{SystemTime, UNIX_EPOCH},
}; };
@ -55,11 +56,11 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -280,13 +281,15 @@ fn main() {
let command_buffer_allocator = let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default()); 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -294,7 +297,10 @@ fn main() {
} => { } => {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into(); let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) { 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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
command_buffer::{ command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, ClearAttachment, allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, ClearAttachment,
@ -32,14 +32,14 @@ use winit::{
window::WindowBuilder, 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` // The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet. // 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 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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -157,140 +157,149 @@ fn main() {
let mut recreate_swapchain = false; let mut recreate_swapchain = false;
let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
if recreate_swapchain { } => {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
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;
}
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; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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(),
)
.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) => {
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;
width = swapchain.image_extent()[0];
height = swapchain.image_extent()[1];
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone());
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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(),
)
.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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -30,7 +30,7 @@ use crate::{
triangle_draw_system::TriangleDrawSystem, triangle_draw_system::TriangleDrawSystem,
}; };
use cgmath::{Matrix4, SquareMatrix, Vector3}; use cgmath::{Matrix4, SquareMatrix, Vector3};
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
command_buffer::allocator::{ command_buffer::allocator::{
StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo, StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo,
@ -57,13 +57,13 @@ use winit::{
mod frame; mod frame;
mod triangle_draw_system; mod triangle_draw_system;
fn main() { fn main() -> Result<(), impl Error> {
// Basic initialization. See the triangle example if you want more details about this. // 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 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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -186,107 +186,116 @@ fn main() {
let mut recreate_swapchain = false; let mut recreate_swapchain = false;
let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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::<Vec<_>>();
swapchain = new_swapchain;
images = new_images;
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let future = previous_frame_end.take().unwrap().join(acquire_future); if image_extent.contains(&0) {
let mut frame = frame_system.frame( return;
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 previous_frame_end.as_mut().unwrap().cleanup_finished();
.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) { if recreate_swapchain {
Ok(future) => { let (new_swapchain, new_images) = swapchain
previous_frame_end = Some(future.boxed()); .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::<Vec<_>>();
swapchain = new_swapchain;
images = new_images;
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; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let future = previous_frame_end.take().unwrap().join(acquire_future);
previous_frame_end = Some(sync::now(device.clone()).boxed()); 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();
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(),
_ => (),
} }
_ => (), })
});
} }

View File

@ -1,8 +1,12 @@
fn main() { fn main() -> Result<(), winit::error::EventLoopError> {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
linux::main(); {
linux::main()
}
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
println!("Not Implemented"); {
Ok(println!("Not Implemented"))
}
} }
// TODO: Can this be demonstrated for other platforms as well? // TODO: Can this be demonstrated for other platforms as well?
@ -80,7 +84,7 @@ mod linux {
window::{Window, WindowBuilder}, window::{Window, WindowBuilder},
}; };
pub fn main() { pub fn main() -> Result<(), winit::error::EventLoopError> {
let event_loop_gl = winit_glium::event_loop::EventLoop::new(); let event_loop_gl = winit_glium::event_loop::EventLoop::new();
// For some reason, this must be created before the vulkan window // For some reason, this must be created before the vulkan window
let hrb = glutin::ContextBuilder::new() let hrb = glutin::ContextBuilder::new()
@ -102,7 +106,7 @@ mod linux {
) )
.unwrap(); .unwrap();
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let ( let (
device, device,
_instance, _instance,
@ -287,13 +291,15 @@ mod linux {
let mut previous_frame_end: Option<Box<dyn GpuFuture>> = let mut previous_frame_end: Option<Box<dyn GpuFuture>> =
Some(Box::new(now(device.clone()))); 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -301,7 +307,10 @@ mod linux {
} => { } => {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
queue queue
.with(|mut q| unsafe { .with(|mut q| unsafe {
q.submit( q.submit(
@ -441,10 +450,10 @@ mod linux {
} }
}; };
} }
Event::AboutToWait => window.request_redraw(),
_ => (), _ => (),
}; };
}); })
} }
#[derive(BufferContents, Vertex)] #[derive(BufferContents, Vertex)]
@ -473,7 +482,7 @@ mod linux {
Subbuffer<[MyVertex]>, Subbuffer<[MyVertex]>,
) { ) {
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -57,14 +57,14 @@ use winit::{
window::WindowBuilder, 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` // The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet. // 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 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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -415,120 +415,131 @@ fn main() {
.boxed(), .boxed(),
); );
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -56,14 +56,14 @@ use winit::{
window::WindowBuilder, 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` // The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet. // 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 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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -363,120 +363,131 @@ fn main() {
.boxed(), .boxed(),
); );
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -16,7 +16,7 @@
// - The sampler is added to the descriptor set layout at pipeline creation. // - The sampler is added to the descriptor set layout at pipeline creation.
// - No sampler is included when building a descriptor set. // - No sampler is included when building a descriptor set.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -65,11 +65,11 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -381,120 +381,131 @@ fn main() {
.boxed(), .boxed(),
); );
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -23,7 +23,7 @@
// For an explanation of how the rendering of the triangles takes place see the `triangle.rs` // For an explanation of how the rendering of the triangles takes place see the `triangle.rs`
// example. // example.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{ buffer::{
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}, allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
@ -72,11 +72,11 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -226,9 +226,9 @@ fn main() {
void main() { void main() {
uint idx = gl_GlobalInvocationID.x; uint idx = gl_GlobalInvocationID.x;
// Each invocation of the compute shader is going to increment the counter, so // 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 // 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 // counter is returned so that gives us the offset into the vertex buffer this
// thread can write it's vertices into. // thread can write it's vertices into.
uint offset = atomicAdd(vertices, 6); uint offset = atomicAdd(vertices, 6);
@ -375,13 +375,15 @@ fn main() {
let command_buffer_allocator = let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default()); 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -389,7 +391,10 @@ fn main() {
} => { } => {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into(); let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) { 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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -12,7 +12,7 @@
// This is a simple, modified version of the `triangle.rs` example that demonstrates how we can use // 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. // the "instancing" technique with vulkano to draw many instances of the triangle.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -71,11 +71,11 @@ struct InstanceData {
scale: f32, scale: f32,
} }
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -319,8 +319,8 @@ fn main() {
None, None,
GraphicsPipelineCreateInfo { GraphicsPipelineCreateInfo {
stages: stages.into_iter().collect(), stages: stages.into_iter().collect(),
// Use the implementations of the `Vertex` trait to describe to vulkano how the two vertex // Use the implementations of the `Vertex` trait to describe to vulkano how the two
// types are expected to be used. // vertex types are expected to be used.
vertex_input_state: Some(vertex_input_state), vertex_input_state: Some(vertex_input_state),
input_assembly_state: Some(InputAssemblyState::default()), input_assembly_state: Some(InputAssemblyState::default()),
viewport_state: Some(ViewportState::default()), viewport_state: Some(ViewportState::default()),
@ -350,13 +350,15 @@ fn main() {
let command_buffer_allocator = let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default()); 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -364,7 +366,10 @@ fn main() {
} => { } => {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into(); let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) { 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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -25,10 +25,8 @@ use vulkano::{
use vulkano_util::{renderer::VulkanoWindowRenderer, window::WindowDescriptor}; use vulkano_util::{renderer::VulkanoWindowRenderer, window::WindowDescriptor};
use winit::{ use winit::{
dpi::PhysicalPosition, dpi::PhysicalPosition,
event::{ event::{ElementState, Event, KeyEvent, MouseButton, MouseScrollDelta, WindowEvent},
ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, VirtualKeyCode, keyboard::{Key, NamedKey},
WindowEvent,
},
window::Fullscreen, window::Fullscreen,
}; };
@ -324,9 +322,9 @@ impl InputState {
fn handle_input(&mut self, window_size: [f32; 2], event: &Event<()>) { fn handle_input(&mut self, window_size: [f32; 2], event: &Event<()>) {
self.window_size = window_size; self.window_size = window_size;
if let winit::event::Event::WindowEvent { event, .. } = event { if let Event::WindowEvent { event, .. } = event {
match event { match event {
WindowEvent::KeyboardInput { input, .. } => self.on_keyboard_event(input), WindowEvent::KeyboardInput { event, .. } => self.on_keyboard_event(event),
WindowEvent::MouseInput { state, button, .. } => { WindowEvent::MouseInput { state, button, .. } => {
self.on_mouse_click_event(*state, *button) self.on_mouse_click_event(*state, *button)
} }
@ -338,21 +336,19 @@ impl InputState {
} }
/// Matches keyboard events to our defined inputs. /// Matches keyboard events to our defined inputs.
fn on_keyboard_event(&mut self, input: &KeyboardInput) { fn on_keyboard_event(&mut self, event: &KeyEvent) {
if let Some(key_code) = input.virtual_keycode { match event.logical_key.as_ref() {
match key_code { Key::Named(NamedKey::Escape) => self.should_quit = state_is_pressed(event.state),
VirtualKeyCode::Escape => self.should_quit = state_is_pressed(input.state), Key::Character("w") => self.pan_up = state_is_pressed(event.state),
VirtualKeyCode::W => self.pan_up = state_is_pressed(input.state), Key::Character("a") => self.pan_left = state_is_pressed(event.state),
VirtualKeyCode::A => self.pan_left = state_is_pressed(input.state), Key::Character("s") => self.pan_down = state_is_pressed(event.state),
VirtualKeyCode::S => self.pan_down = state_is_pressed(input.state), Key::Character("d") => self.pan_right = state_is_pressed(event.state),
VirtualKeyCode::D => self.pan_right = state_is_pressed(input.state), Key::Character("f") => self.toggle_full_screen = state_is_pressed(event.state),
VirtualKeyCode::F => self.toggle_full_screen = state_is_pressed(input.state), Key::Named(NamedKey::Enter) => self.randomize_palette = state_is_pressed(event.state),
VirtualKeyCode::Return => self.randomize_palette = state_is_pressed(input.state), Key::Character("=") => self.increase_iterations = state_is_pressed(event.state),
VirtualKeyCode::Equals => self.increase_iterations = state_is_pressed(input.state), Key::Character("-") => self.decrease_iterations = state_is_pressed(event.state),
VirtualKeyCode::Minus => self.decrease_iterations = state_is_pressed(input.state), Key::Named(NamedKey::Space) => self.toggle_julia = state_is_pressed(event.state),
VirtualKeyCode::Space => self.toggle_julia = state_is_pressed(input.state), _ => (),
_ => (),
}
} }
} }

View File

@ -20,6 +20,7 @@
// - A simple `InputState` to interact with the application. // - A simple `InputState` to interact with the application.
use crate::app::FractalApp; use crate::app::FractalApp;
use std::error::Error;
use vulkano::{image::ImageUsage, swapchain::PresentMode, sync::GpuFuture}; use vulkano::{image::ImageUsage, swapchain::PresentMode, sync::GpuFuture};
use vulkano_util::{ use vulkano_util::{
context::{VulkanoConfig, VulkanoContext}, context::{VulkanoConfig, VulkanoContext},
@ -36,9 +37,9 @@ mod fractal_compute_pipeline;
mod pixels_draw_pipeline; mod pixels_draw_pipeline;
mod place_over_frame; mod place_over_frame;
fn main() { fn main() -> Result<(), impl Error> {
// Create the event loop. // Create the event loop.
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let context = VulkanoContext::new(VulkanoConfig::default()); let context = VulkanoContext::new(VulkanoConfig::default());
let mut windows = VulkanoWindows::default(); let mut windows = VulkanoWindows::default();
let _id = windows.create_window( let _id = windows.create_window(
@ -74,11 +75,13 @@ fn main() {
); );
app.print_guide(); 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(); let renderer = windows.get_primary_renderer_mut().unwrap();
if process_event(renderer, &event, &mut app, render_target_id) { if process_event(renderer, &event, &mut app, render_target_id) {
*control_flow = ControlFlow::Exit; elwt.exit();
return; return;
} }
@ -96,15 +99,20 @@ pub fn process_event(
render_target_id: usize, render_target_id: usize,
) -> bool { ) -> bool {
match &event { match &event {
Event::WindowEvent { event, .. } => match event { Event::WindowEvent {
WindowEvent::CloseRequested => { event: WindowEvent::CloseRequested,
return true; ..
} } => {
WindowEvent::Resized(..) | WindowEvent::ScaleFactorChanged { .. } => renderer.resize(), return true;
_ => (), }
}, Event::WindowEvent {
Event::MainEventsCleared => renderer.window().request_redraw(), event: WindowEvent::Resized(..) | WindowEvent::ScaleFactorChanged { .. },
Event::RedrawRequested(_) => 'redraw: { ..
} => renderer.resize(),
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => 'redraw: {
// Tasks for redrawing: // Tasks for redrawing:
// 1. Update state based on events // 1. Update state based on events
// 2. Compute & Render // 2. Compute & Render
@ -132,6 +140,7 @@ pub fn process_event(
app.max_iters app.max_iters
)); ));
} }
Event::AboutToWait => renderer.window().request_redraw(),
_ => (), _ => (),
} }
!app.is_running() !app.is_running()

View File

@ -23,7 +23,7 @@ mod render_pass;
use crate::app::{App, RenderPipeline}; use crate::app::{App, RenderPipeline};
use cgmath::Vector2; use cgmath::Vector2;
use std::time::Instant; use std::{error::Error, time::Instant};
use vulkano_util::renderer::VulkanoWindowRenderer; use vulkano_util::renderer::VulkanoWindowRenderer;
use winit::{ use winit::{
event::{ElementState, Event, MouseButton, WindowEvent}, 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 WINDOW2_HEIGHT: f32 = 512.0;
pub const SCALING: f32 = 2.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"); println!("Welcome to Vulkano Game of Life\nUse the mouse to draw life on the grid(s)\n");
// Create event loop. // Create event loop.
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
// Create app with vulkano context. // Create app with vulkano context.
let mut app = App::default(); let mut app = App::default();
@ -54,7 +54,9 @@ fn main() {
let mut mouse_is_pressed_w1 = false; let mut mouse_is_pressed_w1 = false;
let mut mouse_is_pressed_w2 = 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( if process_event(
&event, &event,
&mut app, &mut app,
@ -62,8 +64,12 @@ fn main() {
&mut mouse_is_pressed_w1, &mut mouse_is_pressed_w1,
&mut mouse_is_pressed_w2, &mut mouse_is_pressed_w2,
) { ) {
*control_flow = ControlFlow::Exit; elwt.exit();
return; return;
} else if event == Event::AboutToWait {
for (_, renderer) in app.windows.iter() {
renderer.window().request_redraw();
}
} }
// Draw life on windows if mouse is down. // Draw life on windows if mouse is down.

View File

@ -16,7 +16,7 @@
// that you want to learn Vulkan. This means that for example it won't go into details about what a // 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. // vertex or a shader is.
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -51,7 +51,7 @@ use vulkano::{
Validated, VulkanError, VulkanLibrary, Validated, VulkanError, VulkanLibrary,
}; };
use winit::{ use winit::{
event::{ElementState, Event, KeyboardInput, WindowEvent}, event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
window::{Window, WindowBuilder}, window::{Window, WindowBuilder},
}; };
@ -65,11 +65,11 @@ struct WindowSurface {
previous_frame_end: Option<Box<dyn GpuFuture>>, previous_frame_end: Option<Box<dyn GpuFuture>>,
} }
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -326,188 +326,198 @@ fn main() {
}, },
); );
event_loop.run(move |event, event_loop, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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( match event {
device.clone(), Event::WindowEvent {
surface, event: WindowEvent::CloseRequested,
SwapchainCreateInfo { ..
min_image_count: surface_caps.min_image_count.max(2), } => {
image_format, elwt.exit();
image_extent: window.inner_size().into(), }
image_usage: ImageUsage::COLOR_ATTACHMENT, Event::WindowEvent {
composite_alpha,
..Default::default()
},
)
.unwrap()
};
window_surfaces.insert(
window_id, window_id,
WindowSurface { event: WindowEvent::Resized(_),
window, ..
swapchain, } => {
recreate_swapchain: false, window_surfaces
framebuffers: window_size_dependent_setup( .get_mut(&window_id)
&images, .unwrap()
render_pass.clone(), .recreate_swapchain = true;
&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;
} }
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
event:
KeyEvent {
state: ElementState::Pressed,
..
},
..
},
..
} => {
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;
previous_frame_end.as_mut().unwrap().cleanup_finished(); Swapchain::new(
device.clone(),
if *recreate_swapchain { surface,
let (new_swapchain, new_images) = swapchain SwapchainCreateInfo {
.recreate(SwapchainCreateInfo { min_image_count: surface_caps.min_image_count.max(2),
image_extent, image_format,
..swapchain.create_info() image_extent: window.inner_size().into(),
}) image_usage: ImageUsage::COLOR_ATTACHMENT,
.expect("failed to recreate swapchain"); composite_alpha,
..Default::default()
*swapchain = new_swapchain; },
*framebuffers = )
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport); .unwrap()
*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 { window_surfaces.insert(
*recreate_swapchain = true; window_id,
} WindowSurface {
window,
let mut builder = AutoCommandBufferBuilder::primary( swapchain,
&command_buffer_allocator, recreate_swapchain: false,
queue.queue_family_index(), framebuffers: window_size_dependent_setup(
CommandBufferUsage::OneTimeSubmit, &images,
) render_pass.clone(),
.unwrap(); &mut viewport,
),
builder previous_frame_end: Some(sync::now(device.clone()).boxed()),
.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() Event::WindowEvent {
.set_viewport(0, [viewport.clone()].into_iter().collect()) event: WindowEvent::RedrawRequested,
.unwrap() window_id,
.bind_pipeline_graphics(pipeline.clone()) } => {
.unwrap() let WindowSurface {
.bind_vertex_buffers(0, vertex_buffer.clone()) window,
.unwrap() swapchain,
.draw(vertex_buffer.len() as u32, 1, 0, 0) recreate_swapchain,
.unwrap() framebuffers,
.end_render_pass(Default::default()) previous_frame_end,
.unwrap(); } = window_surfaces.get_mut(&window_id).unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end let image_extent: [u32; 2] = window.inner_size().into();
.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) { if image_extent.contains(&0) {
Ok(future) => { return;
*previous_frame_end = Some(future.boxed());
} }
Err(VulkanError::OutOfDate) => {
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 {
*recreate_swapchain = true; *recreate_swapchain = true;
*previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
*previous_frame_end = Some(sync::now(device.clone()).boxed()); &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_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( fn window_size_dependent_setup(

View File

@ -11,7 +11,7 @@
// queries. Occlusion queries allow you to query whether, and sometimes how many, pixels pass the // queries. Occlusion queries allow you to query whether, and sometimes how many, pixels pass the
// depth test in a range of draw calls. // depth test in a range of draw calls.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -54,11 +54,11 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -335,9 +335,9 @@ fn main() {
viewport_state: Some(ViewportState::default()), viewport_state: Some(ViewportState::default()),
rasterization_state: Some(RasterizationState::default()), rasterization_state: Some(RasterizationState::default()),
multisample_state: Some(MultisampleState::default()), multisample_state: Some(MultisampleState::default()),
// Enable depth testing, which is needed for occlusion queries to make sense at all. If you // Enable depth testing, which is needed for occlusion queries to make sense at
// disable depth testing, every pixel is considered to pass the depth test, so every query // all. If you disable depth testing, every pixel is considered to pass the depth
// will return a nonzero result. // test, so every query will return a nonzero result.
depth_stencil_state: Some(DepthStencilState { depth_stencil_state: Some(DepthStencilState {
depth: Some(DepthState::simple()), depth: Some(DepthState::simple()),
..Default::default() ..Default::default()
@ -373,199 +373,211 @@ fn main() {
let mut recreate_swapchain = false; let mut recreate_swapchain = false;
let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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;
}
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; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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();
}
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) => {
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;
}
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; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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();
} }
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());
}
}
// 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.
// 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 2 (green triangle) will succeed, because it's only partially occluded.
assert_ne!(query_results[2], 0);
} }
Event::AboutToWait => window.request_redraw(),
// 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.
// 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 2 (green triangle) will succeed, because it's only partially occluded.
assert_ne!(query_results[2], 0);
} }
_ => (), })
});
} }
fn window_size_dependent_setup( fn window_size_dependent_setup(

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -54,11 +54,11 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -353,127 +353,138 @@ fn main() {
.boxed(), .boxed(),
); );
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::{io::Cursor, sync::Arc}; use std::{error::Error, io::Cursor, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -57,14 +57,14 @@ use winit::{
window::WindowBuilder, 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` // The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet. // 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 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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -484,120 +484,131 @@ fn main() {
.boxed(), .boxed(),
); );
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -21,7 +21,7 @@
// //
// Vulkano uses shaderc to build your shaders internally. // 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::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -62,11 +62,11 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -296,113 +296,124 @@ fn main() {
let command_buffer_allocator = let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default()); StandardCommandBufferAllocator::new(device.clone(), Default::default());
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -12,7 +12,7 @@
// staging buffer and then copying the data to a device-local buffer to be accessed solely by the // 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. // 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::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -63,13 +63,13 @@ const WINDOW_HEIGHT: u32 = 600;
const PARTICLE_COUNT: usize = 100_000; 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 // The usual Vulkan initialization. Largely the same as example `triangle.rs` until further
// commentation is provided. // commentation is provided.
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -521,15 +521,20 @@ fn main() {
let start_time = SystemTime::now(); let start_time = SystemTime::now();
let mut last_frame_time = start_time; 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, 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(); let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) { if image_extent.contains(&0) {
@ -644,7 +649,8 @@ fn main() {
}; };
previous_fence_index = image_index; previous_fence_index = image_index;
} }
Event::AboutToWait => window.request_redraw(),
_ => (), _ => (),
} }
}); })
} }

View File

@ -9,7 +9,7 @@
use self::model::{Normal, Position, INDICES, NORMALS, POSITIONS}; use self::model::{Normal, Position, INDICES, NORMALS, POSITIONS};
use cgmath::{Matrix3, Matrix4, Point3, Rad, Vector3}; use cgmath::{Matrix3, Matrix4, Point3, Rad, Vector3};
use std::{sync::Arc, time::Instant}; use std::{error::Error, sync::Arc, time::Instant};
use vulkano::{ use vulkano::{
buffer::{ buffer::{
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo}, allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
@ -55,20 +55,20 @@ use vulkano::{
}; };
use winit::{ use winit::{
event::{Event, WindowEvent}, event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::EventLoop,
window::WindowBuilder, window::WindowBuilder,
}; };
mod model; 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` // The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet. // 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 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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -265,13 +265,13 @@ fn main() {
let command_buffer_allocator = let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default()); StandardCommandBufferAllocator::new(device.clone(), Default::default());
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, elwt| {
match event { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -279,7 +279,10 @@ fn main() {
} => { } => {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::RedrawEventsCleared => { Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into(); let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) { 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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -21,7 +21,7 @@
// - `tessellation_shaders` and `tessellation_state` are called on the pipeline builder. // - `tessellation_shaders` and `tessellation_state` are called on the pipeline builder.
// - The use of `PrimitiveTopology::PatchList`. // - The use of `PrimitiveTopology::PatchList`.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -159,11 +159,11 @@ mod fs {
} }
} }
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -414,113 +414,124 @@ fn main() {
let command_buffer_allocator = let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default()); StandardCommandBufferAllocator::new(device.clone(), Default::default());
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -56,16 +56,16 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
// This example is about this: // This example is about this:
// uniform sampler2DArray texture_array; // uniform sampler2DArray texture_array;
// And not this: // And not this:
// uniform sampler2D array_of_textures[42]; // uniform sampler2D array_of_textures[42];
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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( let instance = Instance::new(
library, library,
InstanceCreateInfo { InstanceCreateInfo {
@ -374,120 +374,131 @@ fn main() {
.boxed(), .boxed(),
); );
event_loop.run(move |event, _, control_flow| match event { event_loop.run(move |event, elwt| {
Event::WindowEvent { elwt.set_control_flow(ControlFlow::Poll);
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) { match event {
return; Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
} }
Event::WindowEvent {
previous_frame_end.as_mut().unwrap().cleanup_finished(); event: WindowEvent::Resized(_),
..
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 {
recreate_swapchain = true; recreate_swapchain = true;
} }
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary( if image_extent.contains(&0) {
&command_buffer_allocator, return;
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) => {
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 {
recreate_swapchain = true; recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
} }
Err(e) => {
println!("failed to flush future: {e}"); let mut builder = AutoCommandBufferBuilder::primary(
previous_frame_end = Some(sync::now(device.clone()).boxed()); &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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -21,7 +21,7 @@
// `khr_dynamic_rendering` extension, or if you want to see how to support older versions, see the // `khr_dynamic_rendering` extension, or if you want to see how to support older versions, see the
// original triangle example. // original triangle example.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -62,8 +62,8 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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 // 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 // enable manually. To do so, we ask `Surface` for the list of extensions required to draw to
// a window. // a window.
let required_extensions = Surface::required_extensions(&event_loop); let required_extensions = Surface::required_extensions(&event_loop).unwrap();
// Now creating the instance. // Now creating the instance.
let instance = Instance::new( let instance = Instance::new(
@ -515,13 +515,15 @@ fn main() {
// that, we store the submission of the previous frame here. // that, we store the submission of the previous frame here.
let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -529,7 +531,10 @@ fn main() {
} => { } => {
recreate_swapchain = true; 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 // Do not draw the frame when the screen size is zero. On Windows, this can
// occur when minimizing the application. // occur when minimizing the application.
let image_extent: [u32; 2] = window.inner_size().into(); 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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -16,7 +16,7 @@
// that you want to learn Vulkan. This means that for example it won't go into details about what a // 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. // vertex or a shader is.
use std::sync::Arc; use std::{error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage}, buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{ command_buffer::{
@ -56,8 +56,8 @@ use winit::{
window::WindowBuilder, window::WindowBuilder,
}; };
fn main() { fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::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 // 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 // enable manually. To do so, we ask `Surface` for the list of extensions required to draw to
// a window. // a window.
let required_extensions = Surface::required_extensions(&event_loop); let required_extensions = Surface::required_extensions(&event_loop).unwrap();
// Now creating the instance. // Now creating the instance.
let instance = Instance::new( let instance = Instance::new(
@ -512,13 +512,15 @@ fn main() {
// that, we store the submission of the previous frame here. // that, we store the submission of the previous frame here.
let mut previous_frame_end = Some(sync::now(device.clone()).boxed()); 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 { match event {
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
*control_flow = ControlFlow::Exit; elwt.exit();
} }
Event::WindowEvent { Event::WindowEvent {
event: WindowEvent::Resized(_), event: WindowEvent::Resized(_),
@ -526,7 +528,10 @@ fn main() {
} => { } => {
recreate_swapchain = true; 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 // Do not draw the frame when the screen size is zero. On Windows, this can
// occur when minimizing the application. // occur when minimizing the application.
let image_extent: [u32; 2] = window.inner_size().into(); 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. /// This function is called once during initialization, then again whenever the window is resized.

View File

@ -12,7 +12,7 @@ use proc_macro2::TokenStream;
use quote::{quote, quote_spanned}; use quote::{quote, quote_spanned};
use syn::{ use syn::{
parse_quote, spanned::Spanned, Data, DeriveInput, Fields, FieldsNamed, FieldsUnnamed, Ident, 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<TokenStream> { pub fn derive_buffer_contents(mut ast: DeriveInput) -> Result<TokenStream> {
@ -20,23 +20,26 @@ pub fn derive_buffer_contents(mut ast: DeriveInput) -> Result<TokenStream> {
let struct_ident = &ast.ident; let struct_ident = &ast.ident;
if !ast let is_repr_rust = ast
.attrs .attrs
.iter() .iter()
.filter(|&attr| attr.path.is_ident("repr")) .filter(|&attr| attr.path().is_ident("repr"))
.map(|attr| attr.parse_meta().unwrap()) .map(|attr| {
.any(|meta| match meta { let mut is_repr_rust = true;
Meta::List(MetaList { nested, .. }) => {
nested.iter().any(|nested_meta| match nested_meta { let _ = attr.parse_nested_meta(|meta| {
NestedMeta::Meta(Meta::Path(path)) => { if meta.path.is_ident("C") || meta.path.is_ident("transparent") {
path.is_ident("C") || path.is_ident("transparent") is_repr_rust = false;
} }
_ => false,
}) Ok(())
} });
_ => false,
is_repr_rust
}) })
{ .all(|b| b);
if is_repr_rust {
bail!( bail!(
"deriving `BufferContents` is only supported for types that are marked `#[repr(C)]` \ "deriving `BufferContents` is only supported for types that are marked `#[repr(C)]` \
or `#[repr(transparent)]`", or `#[repr(transparent)]`",

View File

@ -41,7 +41,7 @@ pub fn derive_vertex(ast: syn::DeriveInput) -> Result<TokenStream> {
let mut names = vec![field_name_lit.clone()]; let mut names = vec![field_name_lit.clone()];
let mut format = quote! {}; let mut format = quote! {};
for attr in &field.attrs { 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 ident
} else { } else {
continue; continue;
@ -134,7 +134,7 @@ struct NameMeta {
impl Parse for NameMeta { impl Parse for NameMeta {
fn parse(input: ParseStream) -> Result<Self> { fn parse(input: ParseStream) -> Result<Self> {
Ok(Self { Ok(Self {
lit_str_list: input.parse_terminated(<LitStr as Parse>::parse)?, lit_str_list: input.parse_terminated(<LitStr as Parse>::parse, Token![,])?,
}) })
} }
} }

View File

@ -22,7 +22,7 @@ half = { workspace = true, features = ["bytemuck"] }
libloading = { workspace = true } libloading = { workspace = true }
once_cell = { workspace = true } once_cell = { workspace = true }
parking_lot = { workspace = true, features = ["send_guard"] } parking_lot = { workspace = true, features = ["send_guard"] }
raw-window-handle = { workspace = true } raw-window-handle = { workspace = true, features = ["std"] }
serde = { workspace = true, optional = true } serde = { workspace = true, optional = true }
smallvec = { workspace = true } smallvec = { workspace = true }
thread_local = { workspace = true } thread_local = { workspace = true }

View File

@ -22,12 +22,13 @@ use crate::{
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
use objc::{class, msg_send, runtime::Object, sel, sel_impl}; use objc::{class, msg_send, runtime::Object, sel, sel_impl};
use raw_window_handle::{ use raw_window_handle::{
HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle,
}; };
use smallvec::SmallVec; use smallvec::SmallVec;
use std::{ use std::{
any::Any, any::Any,
fmt::{Debug, Error as FmtError, Formatter}, error::Error,
fmt::{Debug, Display, Error as FmtError, Formatter},
mem::MaybeUninit, mem::MaybeUninit,
num::NonZeroU64, num::NonZeroU64,
ptr, ptr,
@ -60,12 +61,14 @@ pub struct Surface {
impl Surface { impl Surface {
/// Returns the instance extensions required to create a surface from a window of the given /// Returns the instance extensions required to create a surface from a window of the given
/// event loop. /// event loop.
pub fn required_extensions(event_loop: &impl HasRawDisplayHandle) -> InstanceExtensions { pub fn required_extensions(
event_loop: &impl HasDisplayHandle,
) -> Result<InstanceExtensions, HandleError> {
let mut extensions = InstanceExtensions { let mut extensions = InstanceExtensions {
khr_surface: true, khr_surface: true,
..InstanceExtensions::empty() ..InstanceExtensions::empty()
}; };
match event_loop.raw_display_handle() { match event_loop.display_handle()?.as_raw() {
RawDisplayHandle::Android(_) => extensions.khr_android_surface = true, RawDisplayHandle::Android(_) => extensions.khr_android_surface = true,
// FIXME: `mvk_macos_surface` and `mvk_ios_surface` are deprecated. // FIXME: `mvk_macos_surface` and `mvk_ios_surface` are deprecated.
RawDisplayHandle::AppKit(_) => extensions.mvk_macos_surface = true, RawDisplayHandle::AppKit(_) => extensions.mvk_macos_surface = true,
@ -77,14 +80,14 @@ impl Surface {
_ => unimplemented!(), _ => unimplemented!(),
} }
extensions Ok(extensions)
} }
/// Creates a new `Surface` from the given `window`. /// Creates a new `Surface` from the given `window`.
pub fn from_window( pub fn from_window(
instance: Arc<Instance>, instance: Arc<Instance>,
window: Arc<impl HasRawWindowHandle + HasRawDisplayHandle + Any + Send + Sync>, window: Arc<impl HasWindowHandle + HasDisplayHandle + Any + Send + Sync>,
) -> Result<Arc<Self>, Validated<VulkanError>> { ) -> Result<Arc<Self>, FromWindowError> {
let mut surface = unsafe { Self::from_window_ref(instance, &*window) }?; let mut surface = unsafe { Self::from_window_ref(instance, &*window) }?;
Arc::get_mut(&mut surface).unwrap().object = Some(window); Arc::get_mut(&mut surface).unwrap().object = Some(window);
@ -99,43 +102,67 @@ impl Surface {
/// - The given `window` must outlive the created surface. /// - The given `window` must outlive the created surface.
pub unsafe fn from_window_ref( pub unsafe fn from_window_ref(
instance: Arc<Instance>, instance: Arc<Instance>,
window: &(impl HasRawWindowHandle + HasRawDisplayHandle), window: &(impl HasWindowHandle + HasDisplayHandle),
) -> Result<Arc<Self>, Validated<VulkanError>> { ) -> Result<Arc<Self>, FromWindowError> {
match (window.raw_window_handle(), window.raw_display_handle()) { 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)) => { (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")] #[cfg(target_os = "macos")]
(RawWindowHandle::AppKit(window), RawDisplayHandle::AppKit(_display)) => { (RawWindowHandle::AppKit(window), RawDisplayHandle::AppKit(_display)) => {
// Ensure the layer is `CAMetalLayer`. // 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) Self::from_mac_os(instance, layer as *const (), None)
} }
#[cfg(target_os = "ios")] #[cfg(target_os = "ios")]
(RawWindowHandle::UiKit(window), RawDisplayHandle::UiKit(_display)) => { (RawWindowHandle::UiKit(window), RawDisplayHandle::UiKit(_display)) => {
// Ensure the layer is `CAMetalLayer`. // 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) Self::from_ios(instance, layer, None)
} }
(RawWindowHandle::Wayland(window), RawDisplayHandle::Wayland(display)) => { (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)) => { (RawWindowHandle::Win32(window), RawDisplayHandle::Windows(_display)) => {
Self::from_win32(instance, window.hinstance, window.hwnd, None) Self::from_win32(
} instance,
(RawWindowHandle::Xcb(window), RawDisplayHandle::Xcb(display)) => { window.hinstance.unwrap().get() as *const (),
Self::from_xcb(instance, display.connection, window.window, None) window.hwnd.get() as *const (),
} None,
(RawWindowHandle::Xlib(window), RawDisplayHandle::Xlib(display)) => { )
Self::from_xlib(instance, display.display, window.window, 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!( _ => unimplemented!(
"the window was created with a windowing API that is not supported \ "the window was created with a windowing API that is not supported \
by Vulkan/Vulkano" by Vulkan/Vulkano"
), ),
} }
.map_err(FromWindowError::CreateSurface)
} }
/// Creates a `Surface` from a raw handle. /// Creates a `Surface` from a raw handle.
@ -2335,6 +2362,35 @@ pub struct SurfaceCapabilities {
pub full_screen_exclusive_supported: bool, 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<VulkanError>),
}
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)] #[cfg(test)]
mod tests { mod tests {
use crate::{ use crate::{