Fix wayland resize issue (#1089)

Some drivers dont enforce a swapchain extent, so you need to check for
resize events from the os and then recreate the swapchain.
I took this opportunity to refactor the examples a bunch.
I want to do some more refactoring to make things consistent but I'll
leave that for a follow up PR.
This commit is contained in:
Lucas Kent 2018-10-28 08:16:30 +11:00 committed by GitHub
parent 753ee299d8
commit 2153177210
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 430 additions and 321 deletions

View File

@ -64,6 +64,7 @@ fn main() {
let mut events_loop = winit::EventsLoop::new();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let window = surface.window();
let queue_family = physical.queue_families().find(|&q| {
q.supports_graphics() && surface.is_supported(q).unwrap_or(false)
@ -86,7 +87,12 @@ fn main() {
let (mut swapchain, mut images) = {
let caps = surface.capabilities(physical)
.expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
let dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format,
@ -108,9 +114,12 @@ fn main() {
previous_frame_end.cleanup_finished();
if recreate_swapchain {
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap();
dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (new_swapchain, new_images) = match swapchain.recreate_with_dimension(dimensions) {
Ok(r) => r,
@ -125,8 +134,7 @@ fn main() {
recreate_swapchain = false;
}
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(),
None) {
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
recreate_swapchain = true;
@ -179,6 +187,7 @@ fn main() {
events_loop.poll_events(|ev| {
match ev {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true,
winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true,
_ => ()
}
});

View File

@ -19,6 +19,12 @@ extern crate vulkano_win;
use vulkano_win::VkSurfaceBuild;
use vulkano::sync::GpuFuture;
use vulkano_shaders::vulkano_shader;
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract};
use vulkano::command_buffer::DynamicState;
use vulkano::image::SwapchainImage;
use vulkano::pipeline::viewport::Viewport;
use winit::Window;
use std::sync::Arc;
@ -35,8 +41,7 @@ fn main() {
let mut events_loop = winit::EventsLoop::new();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let mut dimensions;
let window = surface.window();
let queue_family = physical.queue_families().find(|&q| q.supports_graphics() &&
surface.is_supported(q).unwrap_or(false))
@ -51,10 +56,17 @@ fn main() {
.expect("failed to create device");
let queue = queues.next().unwrap();
let (mut swapchain, mut images) = {
let (mut swapchain, images) = {
let caps = surface.capabilities(physical).expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
let dimensions = if let Some(dimensions) = window.get_inner_size() {
// convert to physical pixels
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
// The window no longer exists so exit the application.
return;
};
let usage = caps.supported_usage_flags;
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
@ -83,7 +95,7 @@ fn main() {
let vs = vs::Shader::load(device.clone()).expect("failed to create shader module");
let fs = fs::Shader::load(device.clone()).expect("failed to create shader module");
let renderpass = Arc::new(
let render_pass = Arc::new(
single_pass_renderpass!(device.clone(),
attachments: {
color: {
@ -127,7 +139,7 @@ fn main() {
.viewports_dynamic_scissors_irrelevant(1)
.fragment_shader(fs.main_entry_point(), ())
.blend_alpha_blending()
.render_pass(vulkano::framebuffer::Subpass::from(renderpass.clone(), 0).unwrap())
.render_pass(vulkano::framebuffer::Subpass::from(render_pass.clone(), 0).unwrap())
.build(device.clone())
.unwrap());
@ -136,74 +148,48 @@ fn main() {
.build().unwrap()
);
let mut framebuffers: Option<Vec<Arc<vulkano::framebuffer::Framebuffer<_,_>>>> = None;
let mut dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None };
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state);
let mut recreate_swapchain = false;
let mut previous_frame_end = Box::new(tex_future) as Box<GpuFuture>;
let mut dynamic_state = vulkano::command_buffer::DynamicState {
line_width: None,
viewports: Some(vec![vulkano::pipeline::viewport::Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]),
scissors: None,
};
loop {
previous_frame_end.cleanup_finished();
if recreate_swapchain {
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap_or([1024, 768]);
let dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (new_swapchain, new_images) = match swapchain.recreate_with_dimension(dimensions) {
Ok(r) => r,
Err(vulkano::swapchain::SwapchainCreationError::UnsupportedDimensions) => {
continue;
},
Err(vulkano::swapchain::SwapchainCreationError::UnsupportedDimensions) => continue,
Err(err) => panic!("{:?}", err)
};
swapchain = new_swapchain;
images = new_images;
framebuffers = None;
dynamic_state.viewports = Some(vec![vulkano::pipeline::viewport::Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]);
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone(), &mut dynamic_state);
recreate_swapchain = false;
}
if framebuffers.is_none() {
framebuffers = Some(images.iter().map(|image| {
Arc::new(vulkano::framebuffer::Framebuffer::start(renderpass.clone())
.add(image.clone()).unwrap()
.build().unwrap())
}).collect::<Vec<_>>());
}
let (image_num, future) = match vulkano::swapchain::acquire_next_image(swapchain.clone(),
None) {
let (image_num, future) = match vulkano::swapchain::acquire_next_image(swapchain.clone(), None) {
Ok(r) => r,
Err(vulkano::swapchain::AcquireError::OutOfDate) => {
recreate_swapchain = true;
continue;
},
}
Err(err) => panic!("{:?}", err)
};
let cb = vulkano::command_buffer::AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family())
.unwrap()
.begin_render_pass(
framebuffers.as_ref().unwrap()[image_num].clone(), false,
framebuffers[image_num].clone(), false,
vec![[0.0, 0.0, 1.0, 1.0].into()]).unwrap()
.draw(pipeline.clone(),
&dynamic_state,
@ -235,6 +221,7 @@ fn main() {
events_loop.poll_events(|ev| {
match ev {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true,
winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true,
_ => ()
}
});
@ -242,6 +229,30 @@ fn main() {
}
}
/// This method is called once during initialization then again whenever the window is resized
fn window_size_dependent_setup(
images: &[Arc<SwapchainImage<Window>>],
render_pass: Arc<RenderPassAbstract + Send + Sync>,
dynamic_state: &mut DynamicState
) -> Vec<Arc<FramebufferAbstract + Send + Sync>> {
let dimensions = images[0].dimensions();
let viewport = Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
};
dynamic_state.viewports = Some(vec!(viewport));
images.iter().map(|image| {
Arc::new(
Framebuffer::start(render_pass.clone())
.add(image.clone()).unwrap()
.build().unwrap()
) as Arc<FramebufferAbstract + Send + Sync>
}).collect::<Vec<_>>()
}
vulkano_shader!{
mod_name: vs,
ty: "vertex",

View File

@ -35,20 +35,21 @@ use vulkano::descriptor::pipeline_layout::PipelineLayoutDescPcRange;
use vulkano::device::Device;
use vulkano::device::DeviceExtensions;
use vulkano::format;
use vulkano::framebuffer::Framebuffer;
use vulkano::framebuffer::Subpass;
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, Subpass, RenderPassAbstract};
use vulkano::image::SwapchainImage;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::pipeline::shader::GraphicsShaderType;
use vulkano::pipeline::shader::ShaderInterfaceDef;
use vulkano::pipeline::shader::ShaderInterfaceDefEntry;
use vulkano::pipeline::shader::ShaderModule;
use vulkano::pipeline::shader::{GraphicsShaderType, ShaderInterfaceDef, ShaderInterfaceDefEntry, ShaderModule};
use vulkano::pipeline::vertex::SingleBufferDefinition;
use vulkano::pipeline::viewport::Viewport;
use vulkano::swapchain::Swapchain;
use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError};
use vulkano::swapchain;
use vulkano::sync::GpuFuture;
use vulkano::sync;
use vulkano_win::VkSurfaceBuild;
use winit::Window;
use std::borrow::Cow;
use std::ffi::CStr;
use std::fs::File;
@ -73,12 +74,9 @@ fn main() {
.next()
.expect("no graphics device");
let mut events_loop = winit::EventsLoop::new();
let surface = winit::WindowBuilder::new()
.with_decorations(false)
.with_title("particle storm")
.build_vk_surface(&events_loop, instance.clone())
.unwrap();
let (graphics_device, mut queues) = {
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let window = surface.window();
let (device, mut queues) = {
let graphical_queue_family = physical
.queue_families()
.find(|&q| q.supports_graphics() && surface.is_supported(q).unwrap_or(false))
@ -96,17 +94,17 @@ fn main() {
};
let graphics_queue = queues.next().unwrap();
let (swapchain, images) = {
let (mut swapchain, images) = {
let caps = surface
.capabilities(graphics_device.physical_device())
.capabilities(device.physical_device())
.expect("failure to get surface capabilities");
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
let dimensions = caps.current_extent.unwrap_or([1024, 768]);
let usage = caps.supported_usage_flags;
let present = caps.present_modes.iter().next().unwrap();
Swapchain::new(
graphics_device.clone(),
device.clone(),
surface.clone(),
caps.min_image_count,
format,
@ -114,17 +112,17 @@ fn main() {
1,
usage,
&graphics_queue,
vk::swapchain::SurfaceTransform::Identity,
vk::swapchain::CompositeAlpha::Opaque,
present,
SurfaceTransform::Identity,
alpha,
PresentMode::Fifo,
true,
None,
).expect("failed to create swapchain")
};
let renderpass = Arc::new(
let render_pass = Arc::new(
single_pass_renderpass!(
graphics_device.clone(), attachments: {
device.clone(), attachments: {
color: {
load: Clear,
store: Store,
@ -146,7 +144,7 @@ fn main() {
f.read_to_end(&mut v).unwrap();
// Create a ShaderModule on a device the same Shader::load does it.
// NOTE: You will have to verify correctness of the data by yourself!
unsafe { ShaderModule::new(graphics_device.clone(), &v) }.unwrap()
unsafe { ShaderModule::new(device.clone(), &v) }.unwrap()
};
let fs = {
@ -154,7 +152,7 @@ fn main() {
.expect("Can't find file src/bin/runtime-shader/frag.spv");
let mut v = vec![];
f.read_to_end(&mut v).unwrap();
unsafe { ShaderModule::new(graphics_device.clone(), &v) }.unwrap()
unsafe { ShaderModule::new(device.clone(), &v) }.unwrap()
};
// This structure will tell Vulkan how input entries of our vertex shader
@ -387,25 +385,20 @@ fn main() {
.vertex_input(SingleBufferDefinition::<Vertex>::new())
.vertex_shader(vert_main, ())
.triangle_list()
.viewports([
Viewport {
origin: [0.0, 0.0],
depth_range: 0.0..1.0,
dimensions: [images[0].dimensions()[0] as f32,
images[0].dimensions()[1] as f32],
},
].iter().cloned())
.viewports_dynamic_scissors_irrelevant(1)
.fragment_shader(frag_main, ())
.cull_mode_front()
.front_face_counter_clockwise()
.depth_stencil_disabled()
.render_pass(Subpass::from(renderpass.clone(), 0).unwrap())
.build(graphics_device.clone())
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
.build(device.clone())
.unwrap(),
);
let mut recreate_swapchain = false;
let vertex_buffer = CpuAccessibleBuffer::from_iter(
graphics_device.clone(),
device.clone(),
BufferUsage::all(),
[
Vertex { position: [-1.0, 1.0], color: [1.0, 0.0, 0.0] },
@ -418,27 +411,45 @@ fn main() {
// note that passing wrong types, providing sets at wrong indexes will cause
// descriptor set builder to return Err!
let framebuffers: Vec<_> = images
.iter()
.map(|image| Arc::new(
Framebuffer::start(renderpass.clone())
.add(image.clone()).unwrap()
.build().unwrap(),
))
.collect();
let mut dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None };
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state);
let mut previous_frame_end = Box::new(sync::now(device.clone())) as Box<GpuFuture>;
loop {
events_loop.poll_events(|_| ());
previous_frame_end.cleanup_finished();
let (image_num, acquire_future) =
vk::swapchain::acquire_next_image(
swapchain.clone(),
None,
).expect("failed to acquire swapchain in time");
if recreate_swapchain {
// Get the new dimensions for the viewport/framebuffers.
let dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let command_buffer = AutoCommandBufferBuilder
::new(
graphics_device.clone(),
let (new_swapchain, new_images) = match swapchain.recreate_with_dimension(dimensions) {
Ok(r) => r,
Err(SwapchainCreationError::UnsupportedDimensions) => continue,
Err(err) => panic!("{:?}", err)
};
swapchain = new_swapchain;
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone(), &mut dynamic_state);
recreate_swapchain = false;
}
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
recreate_swapchain = true;
continue;
},
Err(err) => panic!("{:?}", err)
};
let command_buffer = AutoCommandBufferBuilder::new(
device.clone(),
graphics_queue.family(),
).unwrap()
.begin_render_pass(
@ -448,7 +459,7 @@ fn main() {
).unwrap()
.draw(
graphics_pipeline.clone(),
&DynamicState::none(),
&dynamic_state,
vertex_buffer.clone(),
(),
(),
@ -456,10 +467,57 @@ fn main() {
.end_render_pass().unwrap()
.build().unwrap();
acquire_future
let future = previous_frame_end.join(acquire_future)
.then_execute(graphics_queue.clone(), command_buffer).unwrap()
.then_swapchain_present(graphics_queue.clone(), swapchain.clone(), image_num)
.then_signal_fence_and_flush().unwrap()
.wait(None).unwrap();
.then_signal_fence_and_flush();
match future {
Ok(future) => {
previous_frame_end = Box::new(future) as Box<_>;
}
Err(vulkano::sync::FlushError::OutOfDate) => {
recreate_swapchain = true;
previous_frame_end = Box::new(vulkano::sync::now(device.clone())) as Box<_>;
}
Err(e) => {
println!("{:?}", e);
previous_frame_end = Box::new(vulkano::sync::now(device.clone())) as Box<_>;
}
}
let mut done = false;
events_loop.poll_events(|ev| {
match ev {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true,
winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true,
_ => ()
}
});
if done { return; }
}
}
/// This method is called once during initialization then again whenever the window is resized
fn window_size_dependent_setup(
images: &[Arc<SwapchainImage<Window>>],
render_pass: Arc<RenderPassAbstract + Send + Sync>,
dynamic_state: &mut DynamicState
) -> Vec<Arc<FramebufferAbstract + Send + Sync>> {
let dimensions = images[0].dimensions();
let viewport = Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
};
dynamic_state.viewports = Some(vec!(viewport));
images.iter().map(|image| {
Arc::new(
Framebuffer::start(render_pass.clone())
.add(image.clone()).unwrap()
.build().unwrap()
) as Arc<FramebufferAbstract + Send + Sync>
}).collect::<Vec<_>>()
}

View File

@ -18,84 +18,95 @@ extern crate vulkano_shaders;
extern crate vulkano_win;
use vulkano_win::VkSurfaceBuild;
use vulkano::buffer::cpu_pool::CpuBufferPool;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use vulkano::device::{Device, DeviceExtensions};
use vulkano::format::Format;
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, Subpass, RenderPassAbstract};
use vulkano::image::SwapchainImage;
use vulkano::image::attachment::AttachmentImage;
use vulkano::instance::Instance;
use vulkano::instance::PhysicalDevice;
use vulkano::pipeline::{GraphicsPipeline, GraphicsPipelineAbstract};
use vulkano::pipeline::vertex::TwoBuffersDefinition;
use vulkano::pipeline::viewport::Viewport;
use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError};
use vulkano::swapchain;
use vulkano::sync::GpuFuture;
use vulkano_shaders::vulkano_shader;
use winit::Window;
use cgmath::{Matrix3, Matrix4, Point3, Vector3, Rad};
use examples::{Vertex, Normal, VERTICES, NORMALS, INDICES};
use std::sync::Arc;
use std::iter;
fn main() {
// 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 extensions = vulkano_win::required_extensions();
let instance = vulkano::instance::Instance::new(None, &extensions, None).expect("failed to create instance");
let instance = Instance::new(None, &extensions, None).expect("failed to create instance");
let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
.next().expect("no device available");
let physical = PhysicalDevice::enumerate(&instance).next().expect("no device available");
println!("Using device: {} (type: {:?})", physical.name(), physical.ty());
let mut events_loop = winit::EventsLoop::new();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let window = surface.window();
let mut dimensions;
let queue_family = physical.queue_families().find(|&q| q.supports_graphics() &&
surface.is_supported(q).unwrap_or(false))
.expect("couldn't find a graphical queue family");
let device_ext = vulkano::device::DeviceExtensions {
khr_swapchain: true,
.. vulkano::device::DeviceExtensions::none()
// unlike the triangle example we need to keep track of the width and height so we can calculate
// render the teapot with the correct aspect ratio.
let mut dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (device, mut queues) = vulkano::device::Device::new(physical, physical.supported_features(),
&device_ext, [(queue_family, 0.5)].iter().cloned())
.expect("failed to create device");
let queue_family = physical.queue_families().find(|&q|
q.supports_graphics() && surface.is_supported(q).unwrap_or(false)
).expect("couldn't find a graphical queue family");
let device_ext = DeviceExtensions { khr_swapchain: true, .. DeviceExtensions::none() };
let (device, mut queues) = Device::new(
physical, physical.supported_features(), &device_ext, [(queue_family, 0.5)].iter().cloned()
).expect("failed to create device");
let queue = queues.next().unwrap();
let (mut swapchain, mut images) = {
let (mut swapchain, images) = {
let caps = surface.capabilities(physical).expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
let usage = caps.supported_usage_flags;
let format = caps.supported_formats[0].0;
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
vulkano::swapchain::Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format, dimensions, 1,
usage, &queue, vulkano::swapchain::SurfaceTransform::Identity,
alpha,
vulkano::swapchain::PresentMode::Fifo, true, None).expect("failed to create swapchain")
Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format, dimensions, 1,
usage, &queue, SurfaceTransform::Identity, alpha, PresentMode::Fifo, true, None).expect("failed to create swapchain")
};
let vertices = VERTICES.iter().cloned();
let vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), vertices).unwrap();
let mut depth_buffer = vulkano::image::attachment::AttachmentImage::transient(device.clone(), dimensions, vulkano::format::D16Unorm).unwrap();
let normals = NORMALS.iter().cloned();
let normals_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), normals).unwrap();
let vertex_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
::from_iter(device.clone(), vulkano::buffer::BufferUsage::all(), examples::VERTICES.iter().cloned())
.expect("failed to create buffer");
let indices = INDICES.iter().cloned();
let index_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::all(), indices).unwrap();
let normals_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
::from_iter(device.clone(), vulkano::buffer::BufferUsage::all(), examples::NORMALS.iter().cloned())
.expect("failed to create buffer");
let index_buffer = vulkano::buffer::cpu_access::CpuAccessibleBuffer
::from_iter(device.clone(), vulkano::buffer::BufferUsage::all(), examples::INDICES.iter().cloned())
.expect("failed to create buffer");
// note: this teapot was meant for OpenGL where the origin is at the lower left
// instead the origin is at the upper left in Vulkan, so we reverse the Y axis
let mut proj = cgmath::perspective(cgmath::Rad(std::f32::consts::FRAC_PI_2), { dimensions[0] as f32 / dimensions[1] as f32 }, 0.01, 100.0);
let view = cgmath::Matrix4::look_at(cgmath::Point3::new(0.3, 0.3, 1.0), cgmath::Point3::new(0.0, 0.0, 0.0), cgmath::Vector3::new(0.0, -1.0, 0.0));
let scale = cgmath::Matrix4::from_scale(0.01);
let uniform_buffer = vulkano::buffer::cpu_pool::CpuBufferPool::<vs::ty::Data>
::new(device.clone(), vulkano::buffer::BufferUsage::all());
let uniform_buffer = CpuBufferPool::<vs::ty::Data>::new(device.clone(), BufferUsage::all());
let vs = vs::Shader::load(device.clone()).expect("failed to create shader module");
let fs = fs::Shader::load(device.clone()).expect("failed to create shader module");
let renderpass = Arc::new(
let render_pass = Arc::new(
single_pass_renderpass!(device.clone(),
attachments: {
color: {
@ -118,86 +129,53 @@ fn main() {
).unwrap()
);
let pipeline = Arc::new(vulkano::pipeline::GraphicsPipeline::start()
.vertex_input(vulkano::pipeline::vertex::TwoBuffersDefinition::new())
.vertex_shader(vs.main_entry_point(), ())
.triangle_list()
.viewports_dynamic_scissors_irrelevant(1)
.fragment_shader(fs.main_entry_point(), ())
.depth_stencil_simple_depth()
.render_pass(vulkano::framebuffer::Subpass::from(renderpass.clone(), 0).unwrap())
.build(device.clone())
.unwrap());
let mut framebuffers: Option<Vec<Arc<vulkano::framebuffer::Framebuffer<_,_>>>> = None;
let (mut pipeline, mut framebuffers) = window_size_dependent_setup(device.clone(), &vs, &fs, &images, render_pass.clone());
let mut recreate_swapchain = false;
let mut previous_frame = Box::new(vulkano::sync::now(device.clone())) as Box<GpuFuture>;
let rotation_start = std::time::Instant::now();
let mut dynamic_state = vulkano::command_buffer::DynamicState {
line_width: None,
viewports: Some(vec![vulkano::pipeline::viewport::Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]),
scissors: None,
};
loop {
previous_frame.cleanup_finished();
if recreate_swapchain {
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap_or([1024, 768]);
dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (new_swapchain, new_images) = match swapchain.recreate_with_dimension(dimensions) {
Ok(r) => r,
Err(vulkano::swapchain::SwapchainCreationError::UnsupportedDimensions) => {
continue;
},
Err(SwapchainCreationError::UnsupportedDimensions) => continue,
Err(err) => panic!("{:?}", err)
};
swapchain = new_swapchain;
images = new_images;
depth_buffer = vulkano::image::attachment::AttachmentImage::transient(device.clone(), dimensions, vulkano::format::D16Unorm).unwrap();
framebuffers = None;
proj = cgmath::perspective(cgmath::Rad(std::f32::consts::FRAC_PI_2), { dimensions[0] as f32 / dimensions[1] as f32 }, 0.01, 100.0);
dynamic_state.viewports = Some(vec![vulkano::pipeline::viewport::Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]);
let (new_pipeline, new_framebuffers) = window_size_dependent_setup(device.clone(), &vs, &fs, &new_images, render_pass.clone());
pipeline = new_pipeline;
framebuffers = new_framebuffers;
recreate_swapchain = false;
}
if framebuffers.is_none() {
framebuffers = Some(images.iter().map(|image| {
Arc::new(vulkano::framebuffer::Framebuffer::start(renderpass.clone())
.add(image.clone()).unwrap()
.add(depth_buffer.clone()).unwrap()
.build().unwrap())
}).collect::<Vec<_>>());
}
let uniform_buffer_subbuffer = {
let elapsed = rotation_start.elapsed();
let rotation = elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 / 1_000_000_000.0;
let rotation = cgmath::Matrix3::from_angle_y(cgmath::Rad(rotation as f32));
let rotation = Matrix3::from_angle_y(Rad(rotation as f32));
// note: this teapot was meant for OpenGL where the origin is at the lower left
// instead the origin is at the upper left in Vulkan, so we reverse the Y axis
let aspect_ratio = dimensions[0] as f32 / dimensions[1] as f32;
let proj = cgmath::perspective(Rad(std::f32::consts::FRAC_PI_2), aspect_ratio, 0.01, 100.0);
let view = Matrix4::look_at(Point3::new(0.3, 0.3, 1.0), Point3::new(0.0, 0.0, 0.0), Vector3::new(0.0, -1.0, 0.0));
let scale = Matrix4::from_scale(0.01);
let uniform_data = vs::ty::Data {
world : cgmath::Matrix4::from(rotation).into(),
view : (view * scale).into(),
proj : proj.into(),
world: Matrix4::from(rotation).into(),
view: (view * scale).into(),
proj: proj.into(),
};
uniform_buffer.next(uniform_data).unwrap()
@ -208,27 +186,26 @@ fn main() {
.build().unwrap()
);
let (image_num, acquire_future) = match vulkano::swapchain::acquire_next_image(swapchain.clone(),
None) {
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
Ok(r) => r,
Err(vulkano::swapchain::AcquireError::OutOfDate) => {
Err(AcquireError::OutOfDate) => {
recreate_swapchain = true;
continue;
},
}
Err(err) => panic!("{:?}", err)
};
let command_buffer = vulkano::command_buffer::AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap()
let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap()
.begin_render_pass(
framebuffers.as_ref().unwrap()[image_num].clone(), false,
framebuffers[image_num].clone(), false,
vec![
[0.0, 0.0, 1.0, 1.0].into(),
1f32.into()
]).unwrap()
.draw_indexed(
pipeline.clone(),
&dynamic_state,
(vertex_buffer.clone(), normals_buffer.clone()),
&DynamicState::none(),
vec!(vertex_buffer.clone(), normals_buffer.clone()),
index_buffer.clone(), set.clone(), ()).unwrap()
.end_render_pass().unwrap()
.build().unwrap();
@ -256,6 +233,7 @@ fn main() {
events_loop.poll_events(|ev| {
match ev {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true,
winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true,
_ => ()
}
});
@ -263,6 +241,50 @@ fn main() {
}
}
/// This method is called once during initialization then again whenever the window is resized
fn window_size_dependent_setup(
device: Arc<Device>,
vs: &vs::Shader,
fs: &fs::Shader,
images: &[Arc<SwapchainImage<Window>>],
render_pass: Arc<RenderPassAbstract + Send + Sync>,
) -> (Arc<GraphicsPipelineAbstract + Send + Sync>, Vec<Arc<FramebufferAbstract + Send + Sync>> ) {
let dimensions = images[0].dimensions();
let depth_buffer = AttachmentImage::transient(device.clone(), dimensions, Format::D16Unorm).unwrap();
let framebuffers = images.iter().map(|image| {
Arc::new(
Framebuffer::start(render_pass.clone())
.add(image.clone()).unwrap()
.add(depth_buffer.clone()).unwrap()
.build().unwrap()
) as Arc<FramebufferAbstract + Send + Sync>
}).collect::<Vec<_>>();
// In the triangle example we use a dynamic viewport, as its a simple example.
// However in the teapot example, we recreate the pipelines with a hardcoded viewport instead.
// This allows the driver to optimize things, at the cost of slower window resizes.
// https://computergraphics.stackexchange.com/questions/5742/vulkan-best-way-of-updating-pipeline-viewport
let pipeline = Arc::new(GraphicsPipeline::start()
.vertex_input(TwoBuffersDefinition::<Vertex, Normal>::new())
.vertex_shader(vs.main_entry_point(), ())
.triangle_list()
.viewports_dynamic_scissors_irrelevant(1)
.viewports(iter::once(Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}))
.fragment_shader(fs.main_entry_point(), ())
.depth_stencil_simple_depth()
.render_pass(Subpass::from(render_pass.clone(), 0).unwrap())
.build(device.clone())
.unwrap());
(pipeline, framebuffers)
}
vulkano_shader!{
mod_name: vs,
ty: "vertex",

View File

@ -26,26 +26,22 @@ extern crate vulkano_win;
use vulkano_win::VkSurfaceBuild;
use vulkano::buffer::BufferUsage;
use vulkano::buffer::CpuAccessibleBuffer;
use vulkano::command_buffer::AutoCommandBufferBuilder;
use vulkano::command_buffer::DynamicState;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use vulkano::device::Device;
use vulkano::framebuffer::Framebuffer;
use vulkano::framebuffer::Subpass;
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, Subpass, RenderPassAbstract};
use vulkano::image::SwapchainImage;
use vulkano::instance::Instance;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::pipeline::viewport::Viewport;
use vulkano::swapchain;
use vulkano::swapchain::PresentMode;
use vulkano::swapchain::SurfaceTransform;
use vulkano::swapchain::Swapchain;
use vulkano::swapchain::AcquireError;
use vulkano::swapchain::SwapchainCreationError;
use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError};
use vulkano::sync::now;
use vulkano::sync::GpuFuture;
use vulkano_shaders::vulkano_shader;
use winit::Window;
use std::sync::Arc;
vulkano_shader!{
@ -148,6 +144,7 @@ fn main() {
let mut events_loop = winit::EventsLoop::new();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let window = surface.window();
let queue = physical.queue_families().find(|&q| {
q.supports_graphics() && surface.is_supported(q).unwrap_or(false)
@ -163,13 +160,17 @@ fn main() {
};
let queue = queues.next().unwrap();
let mut dimensions;
let mut dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (mut swapchain, mut images) = {
let (mut swapchain, images) = {
let caps = surface.capabilities(physical)
.expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
let alpha = caps.supported_composite_alpha.iter().next().unwrap();
let format = caps.supported_formats[0].0;
@ -234,25 +235,20 @@ fn main() {
.build(device.clone())
.unwrap());
let mut framebuffers: Option<Vec<Arc<vulkano::framebuffer::Framebuffer<_,_>>>> = None;
let mut recreate_swapchain = false;
let mut previous_frame_end = Box::new(now(device.clone())) as Box<GpuFuture>;
let mut dynamic_state = DynamicState {
line_width: None,
viewports: Some(vec![Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]),
scissors: None,
};
let mut dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None };
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state);
loop {
previous_frame_end.cleanup_finished();
if recreate_swapchain {
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap();
dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (new_swapchain, new_images) = match swapchain.recreate_with_dimension(dimensions) {
Ok(r) => r,
@ -263,27 +259,12 @@ fn main() {
};
swapchain = new_swapchain;
images = new_images;
framebuffers = None;
dynamic_state.viewports = Some(vec![Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]);
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone(), &mut dynamic_state);
recreate_swapchain = false;
}
if framebuffers.is_none() {
framebuffers = Some(images.iter().map(|image| {
Arc::new(Framebuffer::start(render_pass.clone())
.add(image.clone()).unwrap()
.build().unwrap())
}).collect::<Vec<_>>());
}
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(),
None) {
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
recreate_swapchain = true;
@ -293,8 +274,7 @@ fn main() {
};
let command_buffer = AutoCommandBufferBuilder::primary_one_time_submit(device.clone(), queue.family()).unwrap()
.begin_render_pass(framebuffers.as_ref().unwrap()[image_num].clone(), false,
vec![[0.0, 0.0, 0.0, 1.0].into()])
.begin_render_pass(framebuffers[image_num].clone(), false, vec![[0.0, 0.0, 0.0, 1.0].into()])
.unwrap()
.draw(pipeline.clone(),
&dynamic_state,
@ -327,9 +307,33 @@ fn main() {
events_loop.poll_events(|ev| {
match ev {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true,
winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true,
_ => ()
}
});
if done { return }
}
}
fn window_size_dependent_setup(
images: &[Arc<SwapchainImage<Window>>],
render_pass: Arc<RenderPassAbstract + Send + Sync>,
dynamic_state: &mut DynamicState
) -> Vec<Arc<FramebufferAbstract + Send + Sync>> {
let dimensions = images[0].dimensions();
let viewport = Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
};
dynamic_state.viewports = Some(vec!(viewport));
images.iter().map(|image| {
Arc::new(
Framebuffer::start(render_pass.clone())
.add(image.clone()).unwrap()
.build().unwrap()
) as Arc<FramebufferAbstract + Send + Sync>
}).collect::<Vec<_>>()
}

View File

@ -32,27 +32,24 @@ extern crate vulkano_win;
use vulkano_win::VkSurfaceBuild;
use vulkano::buffer::BufferUsage;
use vulkano::buffer::CpuAccessibleBuffer;
use vulkano::command_buffer::AutoCommandBufferBuilder;
use vulkano::command_buffer::DynamicState;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::command_buffer::{AutoCommandBufferBuilder, DynamicState};
use vulkano::device::Device;
use vulkano::framebuffer::Framebuffer;
use vulkano::framebuffer::Subpass;
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, Subpass, RenderPassAbstract};
use vulkano::image::SwapchainImage;
use vulkano::instance::Instance;
use vulkano::instance::PhysicalDevice;
use vulkano::pipeline::GraphicsPipeline;
use vulkano::pipeline::viewport::Viewport;
use vulkano::swapchain::{AcquireError, PresentMode, SurfaceTransform, Swapchain, SwapchainCreationError};
use vulkano::swapchain;
use vulkano::swapchain::PresentMode;
use vulkano::swapchain::SurfaceTransform;
use vulkano::swapchain::Swapchain;
use vulkano::swapchain::AcquireError;
use vulkano::swapchain::SwapchainCreationError;
use vulkano::sync::now;
use vulkano::sync::GpuFuture;
use vulkano::sync::now;
use vulkano_shaders::vulkano_shader;
use winit::Window;
use std::sync::Arc;
// TODO: Move this back to the middle of the example, it makes for a more coherent sequential explanation (check git history)
@ -117,8 +114,7 @@ fn main() {
//
// For the sake of the example we are just going to use the first device, which should work
// most of the time.
let physical = vulkano::instance::PhysicalDevice::enumerate(&instance)
.next().expect("no device available");
let physical = PhysicalDevice::enumerate(&instance).next().expect("no device available");
// Some little debug infos.
println!("Using device: {} (type: {:?})", physical.name(), physical.ty());
@ -135,6 +131,7 @@ fn main() {
// window and a cross-platform Vulkan surface that represents the surface of the window.
let mut events_loop = winit::EventsLoop::new();
let surface = winit::WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap();
let window = surface.window();
// The next step is to choose which GPU queue will execute our draw commands.
//
@ -185,21 +182,25 @@ fn main() {
// iterator and throw it away.
let queue = queues.next().unwrap();
// The dimensions of the surface.
// This variable needs to be mutable since the viewport can change size.
let mut dimensions;
// The dimensions of the window, only used to initially setup the swapchain.
let initial_dimensions = if let Some(dimensions) = window.get_inner_size() {
// convert to physical pixels
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
// The window no longer exists so exit the application.
return;
};
// Before we can draw on the surface, we have to create what is called a swapchain. Creating
// a swapchain allocates the color buffers that will contain the image that will ultimately
// be visible on the screen. These images are returned alongside with the swapchain.
let (mut swapchain, mut images) = {
let (mut swapchain, images) = {
// Querying the capabilities of the surface. When we create the swapchain we can only
// pass values that are allowed by the capabilities.
let caps = surface.capabilities(physical)
.expect("failed to get surface capabilities");
dimensions = caps.current_extent.unwrap_or([1024, 768]);
// We choose the dimensions of the swapchain to match the current extent of the surface.
// If `caps.current_extent` is `None`, this means that the window size will be determined
// by the dimensions of the swapchain, in which case we just use the width and height defined above.
@ -213,7 +214,7 @@ fn main() {
// Please take a look at the docs for the meaning of the parameters we didn't mention.
Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format,
dimensions, 1, caps.supported_usage_flags, &queue,
initial_dimensions, 1, caps.supported_usage_flags, &queue,
SurfaceTransform::Identity, alpha, PresentMode::Fifo, true,
None).expect("failed to create swapchain")
};
@ -293,12 +294,16 @@ fn main() {
.build(device.clone())
.unwrap());
// Dynamic viewports allow us to recreate just the viewport when the window is resized
// Otherwise we would have to recreate the whole pipeline.
let mut dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None };
// The render pass we created above only describes the layout of our framebuffers. Before we
// can draw we also need to create the actual framebuffers.
//
// Since we need to draw to multiple images, we are going to create a different framebuffer for
// each image.
let mut framebuffers: Option<Vec<Arc<vulkano::framebuffer::Framebuffer<_,_>>>> = None;
let mut framebuffers = window_size_dependent_setup(&images, render_pass.clone(), &mut dynamic_state);
// Initialization is finally finished!
@ -321,16 +326,6 @@ fn main() {
// that, we store the submission of the previous frame here.
let mut previous_frame_end = Box::new(now(device.clone())) as Box<GpuFuture>;
let mut dynamic_state = DynamicState {
line_width: None,
viewports: Some(vec![Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]),
scissors: None,
};
loop {
// It is important to call this function from time to time, otherwise resources will keep
// accumulating and you will eventually reach an out of memory error.
@ -338,47 +333,33 @@ fn main() {
// already processed, and frees the resources that are no longer needed.
previous_frame_end.cleanup_finished();
// If the swapchain needs to be recreated, recreate it
// Whenever the window resizes we need to recreate everything dependent on the window size.
// In this example that includes the swapchain, the framebuffers and the dynamic state viewport.
if recreate_swapchain {
// Get the new dimensions for the viewport/framebuffers.
dimensions = surface.capabilities(physical)
.expect("failed to get surface capabilities")
.current_extent.unwrap();
let dimensions = if let Some(dimensions) = window.get_inner_size() {
let dimensions: (u32, u32) = dimensions.to_physical(window.get_hidpi_factor()).into();
[dimensions.0, dimensions.1]
} else {
return;
};
let (new_swapchain, new_images) = match swapchain.recreate_with_dimension(dimensions) {
Ok(r) => r,
// This error tends to happen when the user is manually resizing the window.
// Simply restarting the loop is the easiest way to fix this issue.
Err(SwapchainCreationError::UnsupportedDimensions) => {
continue;
},
Err(SwapchainCreationError::UnsupportedDimensions) => continue,
Err(err) => panic!("{:?}", err)
};
swapchain = new_swapchain;
images = new_images;
framebuffers = None;
dynamic_state.viewports = Some(vec![Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
}]);
// Because framebuffers contains an Arc on the old swapchain, we need to
// recreate framebuffers as well.
framebuffers = window_size_dependent_setup(&new_images, render_pass.clone(), &mut dynamic_state);
recreate_swapchain = false;
}
// Because framebuffers contains an Arc on the old swapchain, we need to
// recreate framebuffers as well.
if framebuffers.is_none() {
framebuffers = Some(images.iter().map(|image| {
Arc::new(Framebuffer::start(render_pass.clone())
.add(image.clone()).unwrap()
.build().unwrap())
}).collect::<Vec<_>>());
}
// Before we can draw on the output, we have to *acquire* an image from the swapchain. If
// no image is available (which happens if you submit draw commands too quickly), then the
// function will block.
@ -386,8 +367,7 @@ fn main() {
//
// This function can block if no image is available. The parameter is an optional timeout
// after which the function call will return an error.
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(),
None) {
let (image_num, acquire_future) = match swapchain::acquire_next_image(swapchain.clone(), None) {
Ok(r) => r,
Err(AcquireError::OutOfDate) => {
recreate_swapchain = true;
@ -413,7 +393,7 @@ fn main() {
// The third parameter builds the list of values to clear the attachments with. The API
// is similar to the list of attachments when building the framebuffers, except that
// only the attachments that use `load: Clear` appear in the list.
.begin_render_pass(framebuffers.as_ref().unwrap()[image_num].clone(), false,
.begin_render_pass(framebuffers[image_num].clone(), false,
vec![[0.0, 0.0, 1.0, 1.0].into()])
.unwrap()
@ -475,9 +455,34 @@ fn main() {
events_loop.poll_events(|ev| {
match ev {
winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true,
winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true,
_ => ()
}
});
if done { return; }
}
}
/// This method is called once during initialization then again whenever the window is resized
fn window_size_dependent_setup(
images: &[Arc<SwapchainImage<Window>>],
render_pass: Arc<RenderPassAbstract + Send + Sync>,
dynamic_state: &mut DynamicState
) -> Vec<Arc<FramebufferAbstract + Send + Sync>> {
let dimensions = images[0].dimensions();
let viewport = Viewport {
origin: [0.0, 0.0],
dimensions: [dimensions[0] as f32, dimensions[1] as f32],
depth_range: 0.0 .. 1.0,
};
dynamic_state.viewports = Some(vec!(viewport));
images.iter().map(|image| {
Arc::new(
Framebuffer::start(render_pass.clone())
.add(image.clone()).unwrap()
.build().unwrap()
) as Arc<FramebufferAbstract + Send + Sync>
}).collect::<Vec<_>>()
}