use crate::vulkan::scene::Scene; use crate::vulkan::vulkan_context::VulkanContext; use crate::vulkan::window_render_context::WindowRenderContext; use std::sync::Arc; use vulkano::command_buffer::{RenderingAttachmentInfo, RenderingInfo}; use vulkano::render_pass::{AttachmentLoadOp, AttachmentStoreOp}; use vulkano::swapchain::{SwapchainPresentInfo, acquire_next_image}; use vulkano::sync::GpuFuture; use vulkano::{Validated, VulkanError, sync}; use winit::application::ApplicationHandler; use winit::event::WindowEvent; use winit::event_loop::ActiveEventLoop; use winit::window::WindowId; pub struct App { vulkan_context: VulkanContext, window_render_context: Option, scene: Option, } impl From for App { fn from(vulkan_context: VulkanContext) -> Self { Self { vulkan_context, window_render_context: None, scene: None, } } } impl ApplicationHandler for App { fn resumed(&mut self, event_loop: &ActiveEventLoop) { let window_attributes = winit::window::Window::default_attributes() .with_title("Rust ASH Test") .with_inner_size(winit::dpi::PhysicalSize::new( f64::from(800), f64::from(600), )); let window = Arc::new(event_loop.create_window(window_attributes).unwrap()); let surface = self.vulkan_context.create_surface(window.clone()); self.window_render_context = Some(WindowRenderContext::new( window, surface, &self.vulkan_context.device, )); self.scene = Some( Scene::load( &self.vulkan_context, self.window_render_context.as_ref().unwrap(), ) .unwrap(), ); } fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { match event { WindowEvent::CloseRequested => { log::debug!("The close button was pressed; stopping"); event_loop.exit(); } WindowEvent::Resized(_) => { let rcx = self.window_render_context.as_mut().unwrap(); rcx.recreate_swapchain = true; } WindowEvent::RedrawRequested => { let (image_index, acquire_future) = { let rcx = self.window_render_context.as_mut().unwrap(); let window_size = rcx.window.inner_size(); if window_size.width == 0 || window_size.height == 0 { return; } rcx.previous_frame_end.as_mut().unwrap().cleanup_finished(); rcx.update_swapchain().unwrap(); let (image_index, suboptimal, acquire_future) = match acquire_next_image(rcx.swapchain.clone(), None) .map_err(Validated::unwrap) { Ok(r) => r, Err(VulkanError::OutOfDate) => { rcx.recreate_swapchain = true; return; } Err(e) => panic!("failed to acquire next image: {e}"), }; if suboptimal { rcx.recreate_swapchain = true; } (image_index, acquire_future) }; let mut builder = self.vulkan_context.create_render_builder(); { let rcx = self.window_render_context.as_ref().unwrap(); builder .begin_rendering(RenderingInfo { color_attachments: vec![Some(RenderingAttachmentInfo { load_op: AttachmentLoadOp::Clear, store_op: AttachmentStoreOp::Store, clear_value: Some([0.0, 0.0, 0.0, 1.0].into()), ..RenderingAttachmentInfo::image_view( rcx.attachment_image_views[image_index as usize].clone(), ) })], ..Default::default() }) .unwrap() .set_viewport(0, [rcx.viewport.clone()].into_iter().collect()) .unwrap(); } if let Some(scene) = self.scene.as_ref() { scene .render( &self.vulkan_context, &self.window_render_context.as_ref().unwrap(), &mut builder, ) .unwrap(); } builder.end_rendering().unwrap(); let command_buffer = builder.build().unwrap(); { let rcx = self.window_render_context.as_mut().unwrap(); let future = rcx .previous_frame_end .take() .unwrap() .join(acquire_future) .then_execute(self.vulkan_context.graphics_queue.clone(), command_buffer) .unwrap() .then_swapchain_present( self.vulkan_context.graphics_queue.clone(), SwapchainPresentInfo::swapchain_image_index( rcx.swapchain.clone(), image_index, ), ) .then_signal_fence_and_flush(); match future.map_err(Validated::unwrap) { Ok(future) => { rcx.previous_frame_end = Some(future.boxed()); } Err(VulkanError::OutOfDate) => { rcx.recreate_swapchain = true; rcx.previous_frame_end = Some(sync::now(self.vulkan_context.device.clone()).boxed()); } Err(e) => { println!("failed to flush future: {e}"); rcx.previous_frame_end = Some(sync::now(self.vulkan_context.device.clone()).boxed()); } } } } _ => {} } } fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { let rcx = self.window_render_context.as_mut().unwrap(); rcx.window.request_redraw(); } }