#![deny(unsafe_code)] use crate::error::*; use crate::graphics_permanent::PermanentGraphicsState; use crate::graphics_window_dressing::{ WindowDressing, N_SIMULTANEOUS_FRAMES }; use std::cell::RefCell; use vulkanalia::vk::{ self, Handle, HasBuilder, DeviceV1_0, KhrSwapchainExtensionDeviceCommands }; use winit::application::ApplicationHandler; use winit::event::WindowEvent; use winit::event_loop::{ ActiveEventLoop, EventLoop }; use winit::window::WindowId; mod error; mod graphics_permanent; mod graphics_window_dressing; struct Surreality { permanent: RefCell>, window_dressing: RefCell>, frame_index: usize, } impl Surreality { fn new() -> Self { Surreality { permanent: RefCell::new(None), window_dressing: RefCell::new(None), frame_index: 0, } } #[allow(unsafe_code)] fn init(&mut self, event_loop: &ActiveEventLoop) -> Result<()> { let (permanent, physical_device, indices, enable_swapchain) = PermanentGraphicsState::new(event_loop)?; if enable_swapchain.0 { *self.window_dressing.get_mut() = Some(WindowDressing::new(&permanent, physical_device, indices)?); } *self.permanent.get_mut() = Some(permanent); Ok(()) } #[allow(unsafe_code)] fn render(&mut self, window_id: WindowId) -> Result<()> { if let Some(permanent) = self.permanent.borrow().as_ref() && let Some(window_dressing) = self.window_dressing.borrow_mut().as_mut() && window_id == permanent.window.id() { let device = &permanent.device; let frame_index = self.frame_index; let concurrency = &mut window_dressing.concurrency; let image_available_semaphore = &concurrency.image_available_semaphores[frame_index]; let rendering_finished_semaphore = &concurrency.rendering_finished_semaphores[frame_index]; let frame_fence = &concurrency.frame_fences[frame_index]; unsafe { device.wait_for_fences(&[*frame_fence], true, u64::MAX) }?; let image_index = unsafe { device.acquire_next_image_khr(window_dressing.swapchain.swapchain, u64::MAX, *image_available_semaphore, vk::Fence::null()) }?.0 as usize; let image_fence = &concurrency.image_fences[image_index]; if !image_fence.is_null() { unsafe { device.wait_for_fences(&[*image_fence], true, u64::MAX) }?; } concurrency.image_fences[image_index] = *frame_fence; let first_semaphores = [*image_available_semaphore]; let second_semaphores = [*rendering_finished_semaphore]; let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; let command_buffers = [window_dressing.command_buffers[image_index]]; let submit_info = vk::SubmitInfo::builder() .wait_semaphores(&first_semaphores) .wait_dst_stage_mask(&wait_stages) .command_buffers(&command_buffers) .signal_semaphores(&second_semaphores); unsafe { device.reset_fences(&[*frame_fence]) }?; unsafe { device.queue_submit(permanent.graphics_queue, &[submit_info], *frame_fence) }?; let swapchains = [window_dressing.swapchain.swapchain]; let image_indices = [image_index as u32]; let present_info = vk::PresentInfoKHR::builder() .wait_semaphores(&second_semaphores) .swapchains(&swapchains) .image_indices(&image_indices); unsafe { device.queue_present_khr(permanent.presentation_queue, &present_info) }?; self.frame_index = (frame_index + 1) % N_SIMULTANEOUS_FRAMES; } Ok(()) } } impl Drop for Surreality { #[allow(unsafe_code)] fn drop(&mut self) { if let Some(permanent) = self.permanent.replace(None) { unsafe { permanent.device.device_wait_idle() }.unwrap(); if let Some(window_dressing) = self.window_dressing.replace(None) { window_dressing.destroy(&permanent); } permanent.destroy(); } } } impl ApplicationHandler for Surreality { fn resumed(&mut self, event_loop: &ActiveEventLoop) { ignore_errors(move || { self.init(event_loop)?; Ok(()) }); } fn window_event(&mut self, event_loop: &ActiveEventLoop, window_id: WindowId, event: WindowEvent) { match event { WindowEvent::RedrawRequested => { if !event_loop.exiting() { if let Err(e) = self.render(window_id) { eprintln!("Error: {}", e); } } } WindowEvent::CloseRequested => { event_loop.exit(); } _ => { } } } } fn main() -> std::process::ExitCode { let body: fn() -> Result<()> = || { let event_loop = EventLoop::new()?; let mut surreality = Surreality::new(); event_loop.run_app(&mut surreality)?; Ok(()) }; match body() { Ok(()) => std::process::ExitCode::SUCCESS, Err(e) => { eprintln!("Error: {}", e); std::process::ExitCode::from(1) } } }