diff --git a/.vscode/settings.json b/.vscode/settings.json index da0bc4c..1861fc7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,8 @@ "swapchain", "vulkano", "winit" + ], + "rust-analyzer.linkedProjects": [ + ".\\Cargo.toml" ] } \ No newline at end of file diff --git a/src/application.rs b/src/application.rs new file mode 100644 index 0000000..25c4dd2 --- /dev/null +++ b/src/application.rs @@ -0,0 +1,238 @@ +pub mod halvar { + use std::sync::Arc; + use vulkano::{ + device::{ + physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, + QueueCreateInfo, QueueFlags, + }, + image::{ImageUsage, SwapchainImage}, + instance::{Instance, InstanceCreateInfo}, + swapchain::{Surface, Swapchain, SwapchainCreateInfo}, + VulkanLibrary, + }; + use vulkano_win::VkSurfaceBuild; + use winit::{ + dpi::LogicalSize, + event::{Event, WindowEvent}, + event_loop::EventLoop, + window::{Window, WindowBuilder}, + }; + + pub struct Application { + instance: Arc, + surface: Arc, + device: Arc, + queue: Arc, + swapchain: Arc, + images: Vec>, + event_loop: EventLoop<()>, + } + + impl Application { + pub fn new() -> Self { + let instance = Self::create_instance(); + let event_loop = EventLoop::new(); + let surface = WindowBuilder::new() + .with_title("Halvar") + .with_inner_size(LogicalSize::new(800, 600)) + .build_vk_surface(&event_loop, instance.clone()) + .unwrap(); + + let (device, queue) = Self::create_device(&instance, &surface); + + let (swapchain, images) = Self::create_swapchain(&device, &surface); + + Application { + instance, + surface, + device, + queue, + swapchain, + images, + event_loop, + } + } + + pub fn create_instance() -> Arc { + let library = VulkanLibrary::new().unwrap(); + + let required_extensions = vulkano_win::required_extensions(&library); + + Instance::new( + library, + InstanceCreateInfo { + enabled_extensions: required_extensions, + engine_name: Some("Halvar".into()), + enumerate_portability: true, + ..Default::default() + }, + ) + .unwrap() + } + + pub fn create_device( + instance: &Arc, + surface: &Arc, + ) -> (Arc, Arc) { + let device_extensions = DeviceExtensions { + khr_swapchain: true, + ..DeviceExtensions::empty() + }; + + let (physical_device, queue_family_index) = instance + .enumerate_physical_devices() + .unwrap() + .filter(|p| p.supported_extensions().contains(&device_extensions)) + .filter_map(|p| { + p.queue_family_properties() + .iter() + .enumerate() + .position(|(i, q)| { + q.queue_flags.intersects(QueueFlags::GRAPHICS) + && p.surface_support(i as u32, surface).unwrap_or(false) + }) + .map(|i| (p, i as u32)) + }) + .min_by_key(|(p, _)| match p.properties().device_type { + PhysicalDeviceType::DiscreteGpu => 0, + PhysicalDeviceType::IntegratedGpu => 1, + PhysicalDeviceType::VirtualGpu => 2, + PhysicalDeviceType::Cpu => 3, + PhysicalDeviceType::Other => 4, + _ => 5, + }) + .expect("No suitable physical device found"); + + // Some little debug infos. + println!( + "Using device: {} (type: {:?})", + physical_device.properties().device_name, + physical_device.properties().device_type, + ); + + let (device, mut queues) = Device::new( + physical_device, + DeviceCreateInfo { + enabled_extensions: device_extensions, + queue_create_infos: vec![QueueCreateInfo { + queue_family_index, + ..Default::default() + }], + + ..Default::default() + }, + ) + .unwrap(); + + let queue: Arc = queues.next().unwrap(); + + (device, queue) + } + + pub fn create_swapchain( + device: &Arc, + surface: &Arc, + ) -> (Arc, Vec>) { + let surface_capabilities = device + .physical_device() + .surface_capabilities(surface, Default::default()) + .unwrap(); + + let image_format = Some( + device + .physical_device() + .surface_formats(surface, Default::default()) + .unwrap()[0] + .0, + ); + + let window = surface.object().unwrap().downcast_ref::().unwrap(); + + Swapchain::new( + device.clone(), + surface.clone(), + SwapchainCreateInfo { + min_image_count: surface_capabilities.min_image_count, + image_format, + image_extent: window.inner_size().into(), + image_usage: ImageUsage::COLOR_ATTACHMENT, + composite_alpha: surface_capabilities + .supported_composite_alpha + .into_iter() + .next() + .unwrap(), + ..Default::default() + }, + ) + .unwrap() + } + + pub fn run(mut self) { + if Arc::strong_count(&self.instance) == 0 { + println!("Cannot run application without a vulkan instance"); + return; + } + if Arc::strong_count(&self.device) == 0 { + println!("Cannot run application without a vulkan device"); + return; + } + if Arc::strong_count(&self.queue) == 0 { + println!("Cannot run application without a vulkan queue"); + return; + } + if Arc::strong_count(&self.surface) == 0 { + println!("Cannot run application without a vulkan surface"); + return; + } + if Arc::strong_count(&self.swapchain) == 0 { + println!("Cannot run application without a vulkan swapchain"); + return; + } + if Vec::is_empty(&self.images) { + println!("Cannot run application without vulkan images"); + return; + } + + let mut recreate_swapchain = false; + + self.event_loop + .run(move |event, _, control_flow| match event { + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => control_flow.set_exit(), + Event::WindowEvent { + event: WindowEvent::Resized(_), + .. + } => { + recreate_swapchain = true; + } + Event::RedrawEventsCleared => { + let window = self + .surface + .object() + .unwrap() + .downcast_ref::() + .unwrap(); + let image_extent: [u32; 2] = window.inner_size().into(); + + // If the window size is zero then don't draw anything + if image_extent.contains(&0) { return; } + + if recreate_swapchain { + let (new_swapchain, _new_images) = self.swapchain + .recreate(SwapchainCreateInfo { + image_extent, + ..self.swapchain.create_info() + }) + .expect("Failed to recreate swapchain"); + + self.swapchain = new_swapchain; + recreate_swapchain = false; + } + } + _ => (), + }); + } + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 9328b89..eede6e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,223 +2,24 @@ extern crate vulkano; extern crate vulkano_win; extern crate winit; -mod halvar { - use std::sync::Arc; - use vulkano::{ - device::{ - physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, Queue, - QueueCreateInfo, QueueFlags, - }, - image::{ImageUsage, SwapchainImage}, - instance::{Instance, InstanceCreateInfo}, - swapchain::{Surface, Swapchain, SwapchainCreateInfo}, - VulkanLibrary, - }; - use vulkano_win::VkSurfaceBuild; - use winit::{ - dpi::LogicalSize, - event::{Event, WindowEvent}, - event_loop::EventLoop, - window::{Window, WindowBuilder}, - }; - - pub struct Application { - instance: Arc, - surface: Arc, - device: Arc, - queue: Arc, - swapchain: Arc, - images: Vec>, - event_loop: EventLoop<()>, - } - - impl Application { - pub fn new() -> Self { - let instance = Self::create_instance(); - let event_loop = EventLoop::new(); - let surface = WindowBuilder::new() - .with_title("Halvar") - .with_inner_size(LogicalSize::new(800, 600)) - .build_vk_surface(&event_loop, instance.clone()) - .unwrap(); - - let (device, queue) = Self::create_device(&instance, &surface); - - let (swapchain, images) = Self::create_swapchain(&device, &surface); - - Application { - instance, - surface, - device, - queue, - swapchain, - images, - event_loop, - } - } - - pub fn create_instance() -> Arc { - let library = VulkanLibrary::new().unwrap(); - - let required_extensions = vulkano_win::required_extensions(&library); - - Instance::new( - library, - InstanceCreateInfo { - enabled_extensions: required_extensions, - engine_name: Some("Halvar".into()), - enumerate_portability: true, - ..Default::default() - }, - ) - .unwrap() - } - - pub fn create_device( - instance: &Arc, - surface: &Arc, - ) -> (Arc, Arc) { - let device_extensions = DeviceExtensions { - khr_swapchain: true, - ..DeviceExtensions::empty() - }; - - let (physical_device, queue_family_index) = instance - .enumerate_physical_devices() - .unwrap() - .filter(|p| p.supported_extensions().contains(&device_extensions)) - .filter_map(|p| { - p.queue_family_properties() - .iter() - .enumerate() - .position(|(i, q)| { - q.queue_flags.intersects(QueueFlags::GRAPHICS) - && p.surface_support(i as u32, surface).unwrap_or(false) - }) - .map(|i| (p, i as u32)) - }) - .min_by_key(|(p, _)| match p.properties().device_type { - PhysicalDeviceType::DiscreteGpu => 0, - PhysicalDeviceType::IntegratedGpu => 1, - PhysicalDeviceType::VirtualGpu => 2, - PhysicalDeviceType::Cpu => 3, - PhysicalDeviceType::Other => 4, - _ => 5, - }) - .expect("No suitable physical device found"); - - // Some little debug infos. - println!( - "Using device: {} (type: {:?})", - physical_device.properties().device_name, - physical_device.properties().device_type, - ); +mod application; +mod vertex; - let (device, mut queues) = Device::new( - physical_device, - DeviceCreateInfo { - enabled_extensions: device_extensions, - queue_create_infos: vec![QueueCreateInfo { - queue_family_index, - ..Default::default() - }], - - ..Default::default() - }, - ) - .unwrap(); - - let queue: Arc = queues.next().unwrap(); - - (device, queue) - } - - pub fn create_swapchain( - device: &Arc, - surface: &Arc, - ) -> (Arc, Vec>) { - let surface_capabilities = device - .physical_device() - .surface_capabilities(surface, Default::default()) - .unwrap(); - - let image_format = Some( - device - .physical_device() - .surface_formats(surface, Default::default()) - .unwrap()[0] - .0, - ); - - let window = surface.object().unwrap().downcast_ref::().unwrap(); - - Swapchain::new( - device.clone(), - surface.clone(), - SwapchainCreateInfo { - min_image_count: surface_capabilities.min_image_count, - image_format, - image_extent: window.inner_size().into(), - image_usage: ImageUsage::COLOR_ATTACHMENT, - composite_alpha: surface_capabilities - .supported_composite_alpha - .into_iter() - .next() - .unwrap(), - ..Default::default() - }, - ) - .unwrap() - } +fn main() { + use vertex::halvar::StandardVertex; - pub fn run(self) { - if Arc::strong_count(&self.instance) == 0 { - println!("Cannot run application without a vulkan instance"); - return; - } - if Arc::strong_count(&self.device) == 0 { - println!("Cannot run application without a vulkan device"); - return; - } - if Arc::strong_count(&self.queue) == 0 { - println!("Cannot run application without a vulkan queue"); - return; - } - if Arc::strong_count(&self.surface) == 0 { - println!("Cannot run application without a vulkan surface"); - return; - } - if Arc::strong_count(&self.swapchain) == 0 { - println!("Cannot run application without a vulkan swapchain"); - return; - } - if Vec::is_empty(&self.images) { - println!("Cannot run application without vulkan images"); - return; - } - self.event_loop - .run(move |event, _, control_flow| match event { - Event::WindowEvent { - event: WindowEvent::CloseRequested, - .. - } => control_flow.set_exit(), - Event::RedrawEventsCleared => { - let window = self - .surface - .object() - .unwrap() - .downcast_ref::() - .unwrap(); - let dimensions = window.inner_size(); - if dimensions.width == 0 || dimensions.height == 0 {} - } - _ => (), - }); - } - } -} + let app = application::halvar::Application::new(); -fn main() { - let app = halvar::Application::new(); + let _vertices = [ + StandardVertex { + position: [-0.5, -0.25], + }, + StandardVertex { + position: [0.0, 0.5], + }, + StandardVertex { + position: [0.25, -0.1], + }, + ]; app.run(); -} +} \ No newline at end of file diff --git a/src/vertex.rs b/src/vertex.rs new file mode 100644 index 0000000..e15bd99 --- /dev/null +++ b/src/vertex.rs @@ -0,0 +1,13 @@ +pub mod halvar { + use vulkano::{ + buffer::BufferContents, + pipeline::graphics::vertex_input::Vertex + }; + + #[derive(BufferContents, Vertex)] + #[repr(C)] + pub struct StandardVertex { + #[format(R32G32_SFLOAT)] + pub position: [f32; 2], + } +} \ No newline at end of file