Rust Vulkano Tutorial(1) Window Creation(3) Resize
前回のプログラムは、ウィンドウのリサイズに対応していません。
ウインドウを拡大したとき、描画領域ののサイズが対応していません。
3 ウィンドウのリサイズ
ウインドウのリサイズに対応するには、ウィンドウをリサイズしたとき、
スワップチェーンとフレームバッファを再作成し、スワップチェーン・
イメージの取得、コマンドの実行を行います。これらの処理は、リサイズが
行われる度に実行するので、繰り返し処理(loop)の中で行います。
また、ウィンドウのリサイズに対応して、スワップチェーンの再作成を
recreate_swapchainフラッグでコントロールします。
ウィンドウのリサイズに関する部分は次のようになります。
let window = surface.window(); let mut recreate_swapchain = false; loop { previous_frame_end.cleanup_finished(); if recreate_swapchain { let dimensions = window.get_inner_size().unwrap(); let win_width = dimensions.width; let win_height = dimensions.height; let (new_swapchain, new_images) = swapchain.recreate_with_dimension([win_width as u32, win_height as u32]) .expect("swapcahain not recreate"); swapchain = new_swapchain; framebuffer = new_images.iter().map(|image| { Arc::new(Framebuffer::start(render_pass.clone()) .add(image.clone()).unwrap() .build().unwrap()) }).collect::<Vec<_>>(); 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::primary_one_time_submit( device.clone(), queue.family()).unwrap() .begin_render_pass(framebuffer[image_num].clone(), false, vec![[0.0, 0.0, 1.0, 1.0].into()]) .unwrap() .end_render_pass() .unwrap() .build() .unwrap(); let _future = previous_frame_end.join(acquire_future) .then_execute(queue.clone(), command_buffer).unwrap() .then_swapchain_present(queue.clone(), swapchain.clone(), image_num) .then_signal_fence_and_flush(); previous_frame_end = Box::new(sync::now(device.clone())) as Box<_>; events_loop.poll_events(|event| { match event { winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true, winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true, _ => () } }); if done { return; } }
全体のプログラム
#[macro_use] extern crate vulkano; extern crate vulkano_win; extern crate winit; use vulkano_win::VkSurfaceBuild; use winit::EventsLoop; use winit::WindowBuilder; use vulkano::instance::{Instance, PhysicalDevice}; use vulkano::device::Device; use vulkano::swapchain; use vulkano::swapchain::{AcquireError, Swapchain, SurfaceTransform, PresentMode}; use vulkano::framebuffer::Framebuffer; use vulkano::command_buffer::AutoCommandBufferBuilder; use vulkano::sync; use vulkano::sync::GpuFuture; use std::sync::Arc; fn main() { let instance = { let extensions = vulkano_win::required_extensions(); Instance::new(None, &extensions, None).expect("failed to create Vulkan instance") }; let mut events_loop = EventsLoop::new(); let surface = WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap(); let window = surface.window(); let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); let queue_family = physical.queue_families().find(|&q| { q.supports_graphics() && surface.is_supported(q).unwrap_or(false) }).unwrap(); let (device, mut queues) = { let device_ext = vulkano::device::DeviceExtensions { khr_swapchain: true, .. vulkano::device::DeviceExtensions::none() }; 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 caps = surface.capabilities(physical) .expect("failed to get surface capabilities"); let dimensions = caps.current_extent.unwrap_or([1280, 1024]); let alpha = caps.supported_composite_alpha.iter().next().unwrap(); let format = caps.supported_formats[0].0; let (mut swapchain, images) = Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format, dimensions, 1, caps.supported_usage_flags, &queue, SurfaceTransform::Identity, alpha, PresentMode::Fifo, true, None) .expect("failed to create swapchain"); let render_pass = Arc::new(single_pass_renderpass!(device.clone(), attachments: { color: { load: Clear, store: Store, format: swapchain.format(), samples: 1, } }, pass: { color: [color], depth_stencil: {} } ).unwrap()); let mut framebuffer = images.iter().map(|image| { Arc::new(Framebuffer::start(render_pass.clone()) .add(image.clone()).unwrap() .build().unwrap()) }).collect::<Vec<_>>(); let mut previous_frame_end = Box::new(sync::now(device.clone())) as Box<GpuFuture>; let mut recreate_swapchain = false; let mut done = false; loop { previous_frame_end.cleanup_finished(); if recreate_swapchain { let dimensions = window.get_inner_size().unwrap(); let win_width = dimensions.width; let win_height = dimensions.height; let (new_swapchain, new_images) = swapchain.recreate_with_dimension([win_width as u32, win_height as u32]) .expect("swapcahain not recreate"); swapchain = new_swapchain; framebuffer = new_images.iter().map(|image| { Arc::new(Framebuffer::start(render_pass.clone()) .add(image.clone()).unwrap() .build().unwrap()) }).collect::<Vec<_>>(); 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::primary_one_time_submit( device.clone(), queue.family()).unwrap() .begin_render_pass(framebuffer[image_num].clone(), false, vec![[0.0, 0.0, 1.0, 1.0].into()]) .unwrap() .end_render_pass() .unwrap() .build() .unwrap(); let _future = previous_frame_end.join(acquire_future) .then_execute(queue.clone(), command_buffer).unwrap() .then_swapchain_present(queue.clone(), swapchain.clone(), image_num) .then_signal_fence_and_flush(); previous_frame_end = Box::new(sync::now(device.clone())) as Box<_>; events_loop.poll_events(|event| { match event { winit::Event::WindowEvent { event: winit::WindowEvent::CloseRequested, .. } => done = true, winit::Event::WindowEvent { event: winit::WindowEvent::Resized(_), .. } => recreate_swapchain = true, _ => () } }); if done { return; } } }