mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-21 14:24:18 +00:00
Update dependencies (#2385)
* Update winit * Update raw-window-handle * Update syn * Remove vulkano-win from the workspace
This commit is contained in:
parent
3664c079f7
commit
4a77d39b85
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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)]
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
_ => (),
|
||||
}
|
||||
_ => (),
|
||||
});
|
||||
})
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -23,7 +23,7 @@
|
||||
// For an explanation of how the rendering of the triangles takes place see the `triangle.rs`
|
||||
// example.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{error::Error, sync::Arc};
|
||||
use vulkano::{
|
||||
buffer::{
|
||||
allocator::{SubbufferAllocator, SubbufferAllocatorCreateInfo},
|
||||
@ -72,11 +72,11 @@ use winit::{
|
||||
window::WindowBuilder,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let event_loop = EventLoop::new();
|
||||
fn main() -> Result<(), impl Error> {
|
||||
let event_loop = EventLoop::new().unwrap();
|
||||
|
||||
let library = VulkanLibrary::new().unwrap();
|
||||
let required_extensions = Surface::required_extensions(&event_loop);
|
||||
let required_extensions = Surface::required_extensions(&event_loop).unwrap();
|
||||
let instance = Instance::new(
|
||||
library,
|
||||
InstanceCreateInfo {
|
||||
@ -226,9 +226,9 @@ fn main() {
|
||||
void main() {
|
||||
uint idx = gl_GlobalInvocationID.x;
|
||||
|
||||
// Each invocation of the compute shader is going to increment the counter, so
|
||||
// we need to use atomic operations for safety. The previous value of the
|
||||
// counter is returned so that gives us the offset into the vertex buffer this
|
||||
// Each invocation of the compute shader is going to increment the counter, so
|
||||
// we need to use atomic operations for safety. The previous value of the
|
||||
// counter is returned so that gives us the offset into the vertex buffer this
|
||||
// thread can write it's vertices into.
|
||||
uint offset = atomicAdd(vertices, 6);
|
||||
|
||||
@ -375,13 +375,15 @@ fn main() {
|
||||
let command_buffer_allocator =
|
||||
StandardCommandBufferAllocator::new(device.clone(), Default::default());
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
event_loop.run(move |event, elwt| {
|
||||
elwt.set_control_flow(ControlFlow::Poll);
|
||||
|
||||
match event {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::CloseRequested,
|
||||
..
|
||||
} => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
elwt.exit();
|
||||
}
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::Resized(_),
|
||||
@ -389,7 +391,10 @@ fn main() {
|
||||
} => {
|
||||
recreate_swapchain = true;
|
||||
}
|
||||
Event::RedrawEventsCleared => {
|
||||
Event::WindowEvent {
|
||||
event: WindowEvent::RedrawRequested,
|
||||
..
|
||||
} => {
|
||||
let image_extent: [u32; 2] = window.inner_size().into();
|
||||
|
||||
if image_extent.contains(&0) {
|
||||
@ -538,9 +543,10 @@ fn main() {
|
||||
}
|
||||
}
|
||||
}
|
||||
Event::AboutToWait => window.request_redraw(),
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
/// This function is called once during initialization, then again whenever the window is resized.
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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.
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
_ => (),
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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)]`",
|
||||
|
@ -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![,])?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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::{
|
||||
|
Loading…
Reference in New Issue
Block a user