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

View File

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

View File

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

View File

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

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
command_buffer::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, ClearAttachment,
@ -32,14 +32,14 @@ use winit::{
window::WindowBuilder,
};
fn main() {
fn main() -> Result<(), impl Error> {
// The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet.
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -157,140 +157,149 @@ fn main() {
let mut recreate_swapchain = false;
let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
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 {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
// Clear attachments with clear values and rects information. All the rects will be
// cleared by the same value. Note that the ClearRect offsets and extents are not
// affected by the viewport, they are directly applied to the rendering image.
.clear_attachments(
[ClearAttachment::Color {
color_attachment: 0,
clear_value: [1.0, 0.0, 0.0, 1.0].into(),
}]
.into_iter()
.collect(),
[
// Fixed offset and extent.
ClearRect {
offset: [0, 0],
extent: [100, 100],
array_layers: 0..1,
},
// Fixed offset, relative extent.
ClearRect {
offset: [100, 150],
extent: [width / 4, height / 4],
array_layers: 0..1,
},
// Relative offset and extent.
ClearRect {
offset: [width / 2, height / 2],
extent: [width / 3, height / 5],
array_layers: 0..1,
},
]
.into_iter()
.collect(),
)
.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());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
// 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.

View File

@ -30,7 +30,7 @@ use crate::{
triangle_draw_system::TriangleDrawSystem,
};
use cgmath::{Matrix4, SquareMatrix, Vector3};
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
command_buffer::allocator::{
StandardCommandBufferAllocator, StandardCommandBufferAllocatorCreateInfo,
@ -57,13 +57,13 @@ use winit::{
mod frame;
mod triangle_draw_system;
fn main() {
fn main() -> Result<(), impl Error> {
// Basic initialization. See the triangle example if you want more details about this.
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -186,107 +186,116 @@ fn main() {
let mut recreate_swapchain = false;
let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
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");
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 {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
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);
let mut frame = frame_system.frame(
future,
images[image_index as usize].clone(),
Matrix4::identity(),
);
let mut after_future = None;
while let Some(pass) = frame.next_pass() {
match pass {
Pass::Deferred(mut draw_pass) => {
let cb = triangle_draw_system.draw(draw_pass.viewport_dimensions());
draw_pass.execute(cb);
}
Pass::Lighting(mut lighting) => {
lighting.ambient_light([0.1, 0.1, 0.1]);
lighting.directional_light(Vector3::new(0.2, -0.1, -0.7), [0.6, 0.6, 0.6]);
lighting.point_light(Vector3::new(0.5, -0.5, -0.1), [1.0, 0.0, 0.0]);
lighting.point_light(Vector3::new(-0.9, 0.2, -0.15), [0.0, 1.0, 0.0]);
lighting.point_light(Vector3::new(0.0, 0.5, -0.05), [0.0, 0.0, 1.0]);
}
Pass::Finished(af) => {
after_future = Some(af);
}
if image_extent.contains(&0) {
return;
}
}
let future = after_future
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
previous_frame_end.as_mut().unwrap().cleanup_finished();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
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;
}
Err(VulkanError::OutOfDate) => {
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let future = previous_frame_end.take().unwrap().join(acquire_future);
let mut frame = frame_system.frame(
future,
images[image_index as usize].clone(),
Matrix4::identity(),
);
let mut after_future = None;
while let Some(pass) = frame.next_pass() {
match pass {
Pass::Deferred(mut draw_pass) => {
let cb = triangle_draw_system.draw(draw_pass.viewport_dimensions());
draw_pass.execute(cb);
}
Pass::Lighting(mut lighting) => {
lighting.ambient_light([0.1, 0.1, 0.1]);
lighting
.directional_light(Vector3::new(0.2, -0.1, -0.7), [0.6, 0.6, 0.6]);
lighting.point_light(Vector3::new(0.5, -0.5, -0.1), [1.0, 0.0, 0.0]);
lighting.point_light(Vector3::new(-0.9, 0.2, -0.15), [0.0, 1.0, 0.0]);
lighting.point_light(Vector3::new(0.0, 0.5, -0.05), [0.0, 0.0, 1.0]);
}
Pass::Finished(af) => {
after_future = Some(af);
}
}
}
let future = after_future
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
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")]
linux::main();
{
linux::main()
}
#[cfg(not(target_os = "linux"))]
println!("Not Implemented");
{
Ok(println!("Not Implemented"))
}
}
// TODO: Can this be demonstrated for other platforms as well?
@ -80,7 +84,7 @@ mod linux {
window::{Window, WindowBuilder},
};
pub fn main() {
pub fn main() -> Result<(), winit::error::EventLoopError> {
let event_loop_gl = winit_glium::event_loop::EventLoop::new();
// For some reason, this must be created before the vulkan window
let hrb = glutin::ContextBuilder::new()
@ -102,7 +106,7 @@ mod linux {
)
.unwrap();
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let (
device,
_instance,
@ -287,13 +291,15 @@ mod linux {
let mut previous_frame_end: Option<Box<dyn GpuFuture>> =
Some(Box::new(now(device.clone())));
event_loop.run(move |event, _, control_flow| {
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
elwt.exit();
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
@ -301,7 +307,10 @@ mod linux {
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
queue
.with(|mut q| unsafe {
q.submit(
@ -441,10 +450,10 @@ mod linux {
}
};
}
Event::AboutToWait => window.request_redraw(),
_ => (),
};
});
})
}
#[derive(BufferContents, Vertex)]
@ -473,7 +482,7 @@ mod linux {
Subbuffer<[MyVertex]>,
) {
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -57,14 +57,14 @@ use winit::{
window::WindowBuilder,
};
fn main() {
fn main() -> Result<(), impl Error> {
// The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet.
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -415,120 +415,131 @@ fn main() {
.boxed(),
);
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -56,14 +56,14 @@ use winit::{
window::WindowBuilder,
};
fn main() {
fn main() -> Result<(), impl Error> {
// The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet.
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -363,120 +363,131 @@ fn main() {
.boxed(),
);
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

@ -16,7 +16,7 @@
// - The sampler is added to the descriptor set layout at pipeline creation.
// - No sampler is included when building a descriptor set.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -65,11 +65,11 @@ use winit::{
window::WindowBuilder,
};
fn main() {
let event_loop = EventLoop::new();
fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -381,120 +381,131 @@ fn main() {
.boxed(),
);
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

@ -23,7 +23,7 @@
// For an explanation of how the rendering of the triangles takes place see the `triangle.rs`
// example.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
@ -72,11 +72,11 @@ use winit::{
window::WindowBuilder,
};
fn main() {
let event_loop = EventLoop::new();
fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -375,13 +375,15 @@ fn main() {
let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default());
event_loop.run(move |event, _, control_flow| {
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
elwt.exit();
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
@ -389,7 +391,10 @@ fn main() {
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) {
@ -538,9 +543,10 @@ fn main() {
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

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

View File

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

View File

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

View File

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

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
// vertex or a shader is.
use std::{collections::HashMap, sync::Arc};
use std::{collections::HashMap, error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -51,7 +51,7 @@ use vulkano::{
Validated, VulkanError, VulkanLibrary,
};
use winit::{
event::{ElementState, Event, KeyboardInput, WindowEvent},
event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop},
window::{Window, WindowBuilder},
};
@ -65,11 +65,11 @@ struct WindowSurface {
previous_frame_end: Option<Box<dyn GpuFuture>>,
}
fn main() {
let event_loop = EventLoop::new();
fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -326,188 +326,198 @@ fn main() {
},
);
event_loop.run(move |event, event_loop, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
window_id,
event: WindowEvent::Resized(_),
..
} => {
window_surfaces
.get_mut(&window_id)
.unwrap()
.recreate_swapchain = true;
}
Event::WindowEvent {
event:
WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
..
},
..
},
..
} => {
let window = Arc::new(WindowBuilder::new().build(event_loop).unwrap());
let surface = Surface::from_window(instance.clone(), window.clone()).unwrap();
let window_id = window.id();
let (swapchain, images) = {
let composite_alpha = surface_caps
.supported_composite_alpha
.into_iter()
.next()
.unwrap();
let image_format = device
.physical_device()
.surface_formats(&surface, Default::default())
.unwrap()[0]
.0;
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
Swapchain::new(
device.clone(),
surface,
SwapchainCreateInfo {
min_image_count: surface_caps.min_image_count.max(2),
image_format,
image_extent: window.inner_size().into(),
image_usage: ImageUsage::COLOR_ATTACHMENT,
composite_alpha,
..Default::default()
},
)
.unwrap()
};
window_surfaces.insert(
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
Event::WindowEvent {
window_id,
WindowSurface {
window,
swapchain,
recreate_swapchain: false,
framebuffers: window_size_dependent_setup(
&images,
render_pass.clone(),
&mut viewport,
),
previous_frame_end: Some(sync::now(device.clone()).boxed()),
},
);
}
Event::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::Resized(_),
..
} => {
window_surfaces
.get_mut(&window_id)
.unwrap()
.recreate_swapchain = true;
}
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();
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}"),
Swapchain::new(
device.clone(),
surface,
SwapchainCreateInfo {
min_image_count: surface_caps.min_image_count.max(2),
image_format,
image_extent: window.inner_size().into(),
image_usage: ImageUsage::COLOR_ATTACHMENT,
composite_alpha,
..Default::default()
},
)
.unwrap()
};
if suboptimal {
*recreate_swapchain = true;
}
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
window_surfaces.insert(
window_id,
WindowSurface {
window,
swapchain,
recreate_swapchain: false,
framebuffers: window_size_dependent_setup(
&images,
render_pass.clone(),
&mut viewport,
),
previous_frame_end: Some(sync::now(device.clone()).boxed()),
},
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();
);
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
window_id,
} => {
let WindowSurface {
window,
swapchain,
recreate_swapchain,
framebuffers,
previous_frame_end,
} = window_surfaces.get_mut(&window_id).unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
let image_extent: [u32; 2] = window.inner_size().into();
match future.map_err(Validated::unwrap) {
Ok(future) => {
*previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
*previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
*previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_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(

View File

@ -11,7 +11,7 @@
// queries. Occlusion queries allow you to query whether, and sometimes how many, pixels pass the
// depth test in a range of draw calls.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -54,11 +54,11 @@ use winit::{
window::WindowBuilder,
};
fn main() {
let event_loop = EventLoop::new();
fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -335,9 +335,9 @@ fn main() {
viewport_state: Some(ViewportState::default()),
rasterization_state: Some(RasterizationState::default()),
multisample_state: Some(MultisampleState::default()),
// Enable depth testing, which is needed for occlusion queries to make sense at all. If you
// disable depth testing, every pixel is considered to pass the depth test, so every query
// will return a nonzero result.
// Enable depth testing, which is needed for occlusion queries to make sense at
// all. If you disable depth testing, every pixel is considered to pass the depth
// test, so every query will return a nonzero result.
depth_stencil_state: Some(DepthStencilState {
depth: Some(DepthState::simple()),
..Default::default()
@ -373,199 +373,211 @@ fn main() {
let mut recreate_swapchain = false;
let mut previous_frame_end = Some(sync::now(device.clone()).boxed());
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers = window_size_dependent_setup(
&new_images,
render_pass.clone(),
&mut viewport,
memory_allocator.clone(),
);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
// Beginning or resetting a query is unsafe for now.
unsafe {
builder
// A query must be reset before each use, including the first use. This must be
// done outside a render pass.
.reset_query_pool(query_pool.clone(), 0..3)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into()), Some(1.0.into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
// Begin query 0, then draw the red triangle. Enabling the
// `QueryControlFlags::PRECISE` flag would give exact numeric results. This
// needs the `occlusion_query_precise` feature to be enabled on the device.
.begin_query(
query_pool.clone(),
0,
QueryControlFlags::empty(),
// QueryControlFlags::PRECISE,
)
.unwrap()
.bind_vertex_buffers(0, triangle1.clone())
.unwrap()
.draw(triangle1.len() as u32, 1, 0, 0)
.unwrap()
// End query 0.
.end_query(query_pool.clone(), 0)
.unwrap()
// Begin query 1 for the cyan triangle.
.begin_query(query_pool.clone(), 1, QueryControlFlags::empty())
.unwrap()
.bind_vertex_buffers(0, triangle2.clone())
.unwrap()
.draw(triangle2.len() as u32, 1, 0, 0)
.unwrap()
.end_query(query_pool.clone(), 1)
.unwrap()
// Finally, query 2 for the green triangle.
.begin_query(query_pool.clone(), 2, QueryControlFlags::empty())
.unwrap()
.bind_vertex_buffers(0, triangle3.clone())
.unwrap()
.draw(triangle3.len() as u32, 1, 0, 0)
.unwrap()
.end_query(query_pool.clone(), 2)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
}
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());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
// 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);
}
// 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(),
_ => (),
}
_ => (),
});
})
}
fn window_size_dependent_setup(

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -54,11 +54,11 @@ use winit::{
window::WindowBuilder,
};
fn main() {
let event_loop = EventLoop::new();
fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -353,127 +353,138 @@ fn main() {
.boxed(),
);
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.push_descriptor_set(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
[
// If the binding is an immutable sampler, using push descriptors
// you must write a dummy value to the binding.
WriteDescriptorSet::none(0),
WriteDescriptorSet::image_view(1, texture.clone()),
]
.into_iter()
.collect(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.push_descriptor_set(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
[
// If the binding is an immutable sampler, using push descriptors
// you must write a dummy value to the binding.
WriteDescriptorSet::none(0),
WriteDescriptorSet::image_view(1, texture.clone()),
]
.into_iter()
.collect(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::{io::Cursor, sync::Arc};
use std::{error::Error, io::Cursor, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -57,14 +57,14 @@ use winit::{
window::WindowBuilder,
};
fn main() {
fn main() -> Result<(), impl Error> {
// The start of this example is exactly the same as `triangle`. You should read the `triangle`
// example if you haven't done so yet.
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -484,120 +484,131 @@ fn main() {
.boxed(),
);
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

@ -21,7 +21,7 @@
//
// Vulkano uses shaderc to build your shaders internally.
use std::{fs::File, io::Read, path::Path, sync::Arc};
use std::{error::Error, fs::File, io::Read, path::Path, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -62,11 +62,11 @@ use winit::{
window::WindowBuilder,
};
fn main() {
let event_loop = EventLoop::new();
fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -296,113 +296,124 @@ fn main() {
let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default());
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::MultipleSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(graphics_pipeline.clone())
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::MultipleSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(graphics_pipeline.clone())
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

@ -12,7 +12,7 @@
// staging buffer and then copying the data to a device-local buffer to be accessed solely by the
// GPU through the compute shader and as a vertex array.
use std::{sync::Arc, time::SystemTime};
use std::{error::Error, sync::Arc, time::SystemTime};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -63,13 +63,13 @@ const WINDOW_HEIGHT: u32 = 600;
const PARTICLE_COUNT: usize = 100_000;
fn main() {
fn main() -> Result<(), impl Error> {
// The usual Vulkan initialization. Largely the same as example `triangle.rs` until further
// commentation is provided.
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -521,15 +521,20 @@ fn main() {
let start_time = SystemTime::now();
let mut last_frame_time = start_time;
event_loop.run(move |event, _, control_flow| {
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
elwt.exit();
}
Event::RedrawEventsCleared => {
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
if image_extent.contains(&0) {
@ -644,7 +649,8 @@ fn main() {
};
previous_fence_index = image_index;
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
});
})
}

View File

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

View File

@ -21,7 +21,7 @@
// - `tessellation_shaders` and `tessellation_state` are called on the pipeline builder.
// - The use of `PrimitiveTopology::PatchList`.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -159,11 +159,11 @@ mod fs {
}
}
fn main() {
let event_loop = EventLoop::new();
fn main() -> Result<(), impl Error> {
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -414,113 +414,124 @@ fn main() {
let command_buffer_allocator =
StandardCommandBufferAllocator::new(device.clone(), Default::default());
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 0.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 1, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::sync::Arc;
use std::{error::Error, sync::Arc};
use vulkano::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage},
command_buffer::{
@ -56,16 +56,16 @@ use winit::{
window::WindowBuilder,
};
fn main() {
fn main() -> Result<(), impl Error> {
// This example is about this:
// uniform sampler2DArray texture_array;
// And not this:
// uniform sampler2D array_of_textures[42];
let event_loop = EventLoop::new();
let event_loop = EventLoop::new().unwrap();
let library = VulkanLibrary::new().unwrap();
let required_extensions = Surface::required_extensions(&event_loop);
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
let instance = Instance::new(
library,
InstanceCreateInfo {
@ -374,120 +374,131 @@ fn main() {
.boxed(),
);
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::RedrawEventsCleared => {
let image_extent: [u32; 2] = window.inner_size().into();
event_loop.run(move |event, elwt| {
elwt.set_control_flow(ControlFlow::Poll);
if image_extent.contains(&0) {
return;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
elwt.exit();
}
previous_frame_end.as_mut().unwrap().cleanup_finished();
if recreate_swapchain {
let (new_swapchain, new_images) = swapchain
.recreate(SwapchainCreateInfo {
image_extent,
..swapchain.create_info()
})
.expect("failed to recreate swapchain");
swapchain = new_swapchain;
framebuffers =
window_size_dependent_setup(&new_images, render_pass.clone(), &mut viewport);
recreate_swapchain = false;
}
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
return;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
Event::WindowEvent {
event: WindowEvent::Resized(_),
..
} => {
recreate_swapchain = true;
}
Event::WindowEvent {
event: WindowEvent::RedrawRequested,
..
} => {
let image_extent: [u32; 2] = window.inner_size().into();
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 3, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
if image_extent.contains(&0) {
return;
}
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;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
let mut builder = AutoCommandBufferBuilder::primary(
&command_buffer_allocator,
queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
builder
.begin_render_pass(
RenderPassBeginInfo {
clear_values: vec![Some([0.0, 0.0, 1.0, 1.0].into())],
..RenderPassBeginInfo::framebuffer(
framebuffers[image_index as usize].clone(),
)
},
Default::default(),
)
.unwrap()
.set_viewport(0, [viewport.clone()].into_iter().collect())
.unwrap()
.bind_pipeline_graphics(pipeline.clone())
.unwrap()
.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
set.clone(),
)
.unwrap()
.bind_vertex_buffers(0, vertex_buffer.clone())
.unwrap()
.draw(vertex_buffer.len() as u32, 3, 0, 0)
.unwrap()
.end_render_pass(Default::default())
.unwrap();
let command_buffer = builder.build().unwrap();
let future = previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(queue.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
queue.clone(),
SwapchainPresentInfo::swapchain_image_index(swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
previous_frame_end = Some(future.boxed());
}
Err(VulkanError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
Err(e) => {
println!("failed to flush future: {e}");
previous_frame_end = Some(sync::now(device.clone()).boxed());
}
}
}
Event::AboutToWait => window.request_redraw(),
_ => (),
}
_ => (),
});
})
}
/// This function is called once during initialization, then again whenever the window is resized.

View File

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

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

View File

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

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 format = quote! {};
for attr in &field.attrs {
let attr_ident = if let Some(ident) = attr.path.get_ident() {
let attr_ident = if let Some(ident) = attr.path().get_ident() {
ident
} else {
continue;
@ -134,7 +134,7 @@ struct NameMeta {
impl Parse for NameMeta {
fn parse(input: ParseStream) -> Result<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 }
once_cell = { workspace = true }
parking_lot = { workspace = true, features = ["send_guard"] }
raw-window-handle = { workspace = true }
raw-window-handle = { workspace = true, features = ["std"] }
serde = { workspace = true, optional = true }
smallvec = { workspace = true }
thread_local = { workspace = true }

View File

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