diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs index 48a5d6b..11bfe11 100644 --- a/src/vulkan/mod.rs +++ b/src/vulkan/mod.rs @@ -29,7 +29,9 @@ mod vk_semaphore; pub(self) use vk_semaphore::VkSemaphore; mod vk_command_pool; +pub(self) use vk_command_pool::VkCommandPool; mod vk_framebuffer; +pub(self) use vk_framebuffer::VkFramebuffer; mod utils; diff --git a/src/vulkan/vk_command_pool.rs b/src/vulkan/vk_command_pool.rs index 14ff0d1..fe79391 100644 --- a/src/vulkan/vk_command_pool.rs +++ b/src/vulkan/vk_command_pool.rs @@ -10,14 +10,18 @@ pub struct VkCommandPool { } impl VkCommandPool { - pub fn new(device: Arc) -> VkResult { - let command_pool_info = vk::CommandPoolCreateInfo::default() - .queue_family_index(device.queue_family_index); - let command_pool = unsafe { device.handle.create_command_pool(&command_pool_info, None)? }; + pub fn new(device: &Arc) -> VkResult { + let command_pool_info = + vk::CommandPoolCreateInfo::default().queue_family_index(device.queue_family_index); + let command_pool = unsafe { + device + .handle + .create_command_pool(&command_pool_info, None)? + }; log::debug!("Command pool created ({command_pool:?})"); Ok(Self { - device, + device: device.clone(), handle: command_pool, }) } @@ -28,4 +32,4 @@ impl Drop for VkCommandPool { unsafe { self.device.handle.destroy_command_pool(self.handle, None) }; log::debug!("Command pool destroyed ({:?})", self.handle); } -} \ No newline at end of file +} diff --git a/src/vulkan/vk_device.rs b/src/vulkan/vk_device.rs index 4fb1986..fd79033 100644 --- a/src/vulkan/vk_device.rs +++ b/src/vulkan/vk_device.rs @@ -16,7 +16,7 @@ pub struct VkDevice { impl VkDevice { pub(super) fn new_graphics_device( - instance: Arc, + instance: &Arc, physical_device: &VkPhysicalDevice, queue_family_index: u32, ) -> anyhow::Result { @@ -56,7 +56,7 @@ impl VkDevice { let swapchain_loader = ash::khr::swapchain::Device::new(&instance.handle, &device); Ok(Self { - instance, + instance: instance.clone(), handle: device, swapchain_loader, queue_family_index, diff --git a/src/vulkan/vk_framebuffer.rs b/src/vulkan/vk_framebuffer.rs index 44252a9..c4dedb6 100644 --- a/src/vulkan/vk_framebuffer.rs +++ b/src/vulkan/vk_framebuffer.rs @@ -1,30 +1,24 @@ use crate::vulkan::vk_render_pass::VkRenderPass; use crate::vulkan::{VkDevice, VkSwapchain}; -use ash::prelude::VkResult; use ash::vk; use std::sync::Arc; -pub struct VkSwapchainFramebuffer { +pub struct VkFramebuffer { device: Arc, - swapchain: Arc, + image_view: Arc, render_pass: Arc, - image_view_index: usize, pub(super) handle: vk::Framebuffer, } -impl VkSwapchainFramebuffer { - pub fn new( - device: Arc, - swapchain: Arc, - render_pass: Arc, - image_view_index: usize, - ) -> VkResult { - let present_image_view = swapchain - .present_image_views - .as_ref() - .unwrap()[image_view_index]; - let attachments = [present_image_view]; +impl VkFramebuffer { + pub fn from_swapchain_image_view( + device: &Arc, + render_pass: &Arc, + image_view: &Arc, + swapchain: &VkSwapchain, + ) -> anyhow::Result { + let attachments = [*image_view.as_ref()]; let framebuffer_info = vk::FramebufferCreateInfo::default() .render_pass(render_pass.handle) .width(swapchain.surface_resolution.width) @@ -35,18 +29,17 @@ impl VkSwapchainFramebuffer { let framebuffer = unsafe { device.handle.create_framebuffer(&framebuffer_info, None)? }; Ok(Self { - device, - swapchain, - render_pass, - image_view_index, + device: device.clone(), + render_pass: render_pass.clone(), + image_view: image_view.clone(), handle: framebuffer, }) } } -impl Drop for VkSwapchainFramebuffer { +impl Drop for VkFramebuffer { fn drop(&mut self) { unsafe { self.device.handle.destroy_framebuffer(self.handle, None) }; } -} \ No newline at end of file +} diff --git a/src/vulkan/vk_graphics_pipeline.rs b/src/vulkan/vk_graphics_pipeline.rs index e306557..51bd628 100644 --- a/src/vulkan/vk_graphics_pipeline.rs +++ b/src/vulkan/vk_graphics_pipeline.rs @@ -17,9 +17,9 @@ pub struct VkGraphicsPipeline { impl VkGraphicsPipeline { pub fn new( - device: Arc, - swapchain: Arc, - render_pass: Arc, + device: &Arc, + swapchain: &Arc, + render_pass: &Arc, ) -> anyhow::Result { let shader_entry_name = CStr::from_bytes_with_nul(b"main\0")?; @@ -107,9 +107,9 @@ impl VkGraphicsPipeline { log::debug!("Pipeline created ({pipeline_layout:?})"); Ok(Self { - device, - swapchain, - render_pass, + device: device.clone(), + swapchain: swapchain.clone(), + render_pass: render_pass.clone(), pipeline_layout, pipeline, vertex_shader: vert_shader_module, @@ -124,8 +124,10 @@ impl Drop for VkGraphicsPipeline { self.device.handle.destroy_pipeline(self.pipeline, None); log::debug!("Pipeline destroyed ({:?})", self.pipeline); - self.device.handle.destroy_pipeline_layout(self.pipeline_layout, None); + self.device + .handle + .destroy_pipeline_layout(self.pipeline_layout, None); log::debug!("Pipeline layout destroyed ({:?})", self.pipeline_layout); } } -} \ No newline at end of file +} diff --git a/src/vulkan/vk_render_context.rs b/src/vulkan/vk_render_context.rs index c8800be..755d2c4 100644 --- a/src/vulkan/vk_render_context.rs +++ b/src/vulkan/vk_render_context.rs @@ -1,7 +1,8 @@ -use crate::vulkan::vk_command_pool::VkCommandPool; -use crate::vulkan::{VkDevice, VkGraphicsPipeline, VkInstance, VkPhysicalDevice, VkRenderPass, VkSemaphore, VkSurface, VkSwapchain}; +use crate::vulkan::{ + VkCommandPool, VkDevice, VkFramebuffer, VkGraphicsPipeline, VkInstance, VkPhysicalDevice, + VkRenderPass, VkSemaphore, VkSurface, VkSwapchain, +}; use ash::vk; -use std::mem::swap; use std::sync::Arc; pub struct VkRenderContext { @@ -11,6 +12,7 @@ pub struct VkRenderContext { swapchain: Arc, render_pass: Arc, + framebuffers: Vec>, pipeline: Arc, command_pool: VkCommandPool, command_buffers: Vec, @@ -34,66 +36,81 @@ impl VkRenderContext { Some(vk::QueueFlags::GRAPHICS), Some(&surface), ) - .ok_or_else(|| anyhow::anyhow!("Unable to find physical device"))?; + .ok_or_else(|| anyhow::anyhow!("Unable to find physical device"))?; log::debug!( "Selected queue {properties:#?} for physical device {:?}", physical_device.properties.device_name_as_c_str() ); let device = Arc::new(VkDevice::new_graphics_device( - instance.clone(), + &instance, &physical_device, queue_family_index, )?); let swapchain = Arc::new(VkSwapchain::new( &window, - surface.clone(), - device.clone(), + &surface, + &device, &physical_device, )?); - let render_pass = Arc::new(VkRenderPass::new( - device.clone(), - swapchain.clone(), - )?); + let render_pass = Arc::new(VkRenderPass::new(&device, &swapchain)?); - let framebuffers = swapchain.create_framebuffers(render_pass.clone()) + let framebuffers = swapchain + .create_framebuffers(&render_pass) .ok_or_else(|| anyhow::anyhow!("Failed to get framebuffers"))?; - let pipeline = Arc::new(VkGraphicsPipeline::new( - device.clone(), - swapchain.clone(), - render_pass.clone(), - )?); + let pipeline = Arc::new(VkGraphicsPipeline::new(&device, &swapchain, &render_pass)?); - let command_pool = VkCommandPool::new(device.clone())?; + let command_pool = VkCommandPool::new(&device)?; let command_buffer_info = vk::CommandBufferAllocateInfo::default() .command_pool(command_pool.handle) .level(vk::CommandBufferLevel::PRIMARY) - .command_buffer_count(framebuffers.as_ref().unwrap().len() as u32); + .command_buffer_count(framebuffers.len() as u32); // Destroyed with command pool - let command_buffers = unsafe { device.handle.allocate_command_buffers(&command_buffer_info)? }; + let command_buffers = unsafe { + device + .handle + .allocate_command_buffers(&command_buffer_info)? + }; // Same in VkGraphicsPipeline (TODO: Refactor this) let render_area = vk::Rect2D::default().extent(swapchain.surface_resolution); let clear_value = vk::ClearValue::default(); for (index, command_buffer) in command_buffers.iter().enumerate() { let command_buffer_begin_info = vk::CommandBufferBeginInfo::default(); - unsafe { device.handle.begin_command_buffer(*command_buffer, &command_buffer_begin_info)? }; + unsafe { + device + .handle + .begin_command_buffer(*command_buffer, &command_buffer_begin_info)? + }; let clear_values = [clear_value]; + let framebuffer = framebuffers[index].as_ref(); let render_pass_begin_info = vk::RenderPassBeginInfo::default() .render_pass(render_pass.handle) - .framebuffer(framebuffers[index]) + .framebuffer(framebuffer.handle) .render_area(render_area) .clear_values(&clear_values); - unsafe { device.handle.cmd_begin_render_pass(*command_buffer, &render_pass_begin_info, vk::SubpassContents::INLINE); }; + unsafe { + device.handle.cmd_begin_render_pass( + *command_buffer, + &render_pass_begin_info, + vk::SubpassContents::INLINE, + ); + }; - unsafe { device.handle.cmd_bind_pipeline(*command_buffer, vk::PipelineBindPoint::GRAPHICS, pipeline.pipeline) }; + unsafe { + device.handle.cmd_bind_pipeline( + *command_buffer, + vk::PipelineBindPoint::GRAPHICS, + pipeline.pipeline, + ) + }; unsafe { device.handle.cmd_draw(*command_buffer, 3, 1, 0, 0) }; @@ -112,6 +129,7 @@ impl VkRenderContext { swapchain, render_pass, + framebuffers, pipeline, command_pool, @@ -123,10 +141,14 @@ impl VkRenderContext { } pub fn render(&mut self) -> anyhow::Result<()> { - let queue = self.device.get_device_queue(0) + let queue = self + .device + .get_device_queue(0) .ok_or_else(|| anyhow::anyhow!("Failed to get a queue"))?; - let (index, _) = self.swapchain.acquire_next_image(&self.image_available_semaphore)?; + let (index, _) = self + .swapchain + .acquire_next_image(&self.image_available_semaphore)?; let wait_semaphores = [self.image_available_semaphore.handle]; let signal_semaphores = [self.render_finished_semaphore.handle]; @@ -138,7 +160,11 @@ impl VkRenderContext { .command_buffers(&command_buffers_to_submit) .signal_semaphores(&signal_semaphores); - unsafe { self.device.handle.queue_submit(*queue, &[submit_info], vk::Fence::null())? }; + unsafe { + self.device + .handle + .queue_submit(*queue, &[submit_info], vk::Fence::null())? + }; Ok(()) } diff --git a/src/vulkan/vk_render_pass.rs b/src/vulkan/vk_render_pass.rs index ff6ac9e..fafe50e 100644 --- a/src/vulkan/vk_render_pass.rs +++ b/src/vulkan/vk_render_pass.rs @@ -11,10 +11,7 @@ pub struct VkRenderPass { } impl VkRenderPass { - pub fn new( - device: Arc, - swapchain: Arc, - ) -> VkResult { + pub fn new(device: &Arc, swapchain: &Arc) -> VkResult { let color_attachment = vk::AttachmentDescription::default() .format(swapchain.surface_format.format) .samples(vk::SampleCountFlags::TYPE_1) @@ -40,14 +37,12 @@ impl VkRenderPass { .attachments(&attachments) .subpasses(&subpasses); - let render_pass = unsafe { - device.handle.create_render_pass(&render_pass_info, None)? - }; + let render_pass = unsafe { device.handle.create_render_pass(&render_pass_info, None)? }; log::debug!("Render pass created ({render_pass:?})"); Ok(Self { - device, - swapchain, + device: device.clone(), + swapchain: swapchain.clone(), handle: render_pass, }) } @@ -60,4 +55,4 @@ impl Drop for VkRenderPass { log::debug!("Render pass destroyed ({:?})", self.handle); } } -} \ No newline at end of file +} diff --git a/src/vulkan/vk_swapchain.rs b/src/vulkan/vk_swapchain.rs index 12e556f..3aa4274 100644 --- a/src/vulkan/vk_swapchain.rs +++ b/src/vulkan/vk_swapchain.rs @@ -1,9 +1,8 @@ use crate::display::Window; -use crate::vulkan::vk_framebuffer::VkSwapchainFramebuffer; use crate::vulkan::vk_render_pass::VkRenderPass; use crate::vulkan::vk_semaphore::VkSemaphore; use crate::vulkan::vk_surface::SwapchainSupportDetails; -use crate::vulkan::{VkDevice, VkPhysicalDevice, VkSurface}; +use crate::vulkan::{VkDevice, VkFramebuffer, VkPhysicalDevice, VkSurface}; use ash::prelude::VkResult; use ash::vk; use std::sync::Arc; @@ -22,14 +21,14 @@ pub struct VkSwapchain { pub(super) pre_transform: vk::SurfaceTransformFlagsKHR, pub(super) present_images: Option>, - pub(super) present_image_views: Option>, + pub(super) present_image_views: Option>>, } impl VkSwapchain { pub(super) fn new( window: &Window, - surface: Arc, - device: Arc, + surface: &Arc, + device: &Arc, physical_device: &VkPhysicalDevice, ) -> anyhow::Result { log::debug!("Creating swapchain"); @@ -61,8 +60,8 @@ impl VkSwapchain { let present_mode = Self::choose_present_mode(present_modes); let mut swapchain = Self { - surface, - device, + surface: surface.clone(), + device: device.clone(), swapchain: None, swapchain_support_details, @@ -104,6 +103,7 @@ impl VkSwapchain { self.create_present_image_view(*i) .expect("Failed to create image view") }) + .map(|i| Arc::new(i)) .collect::>(); if log::log_enabled!(log::Level::Debug) { @@ -121,14 +121,27 @@ impl VkSwapchain { Ok(()) } - pub(super) fn create_framebuffers(&self, render_pass: Arc) -> Option> { + pub(super) fn create_framebuffers( + &self, + render_pass: &Arc, + ) -> Option>> { let present_image_views = self.present_image_views.as_ref()?; - present_image_views.iter().enumerate() - .map(|present_image_view| { - VkSwapchainFramebuffer::new() - }) - .collect::>() + Some( + present_image_views + .iter() + .map(|image_view| { + VkFramebuffer::from_swapchain_image_view( + &self.device, + &render_pass, + &image_view, + &self, + ) + .unwrap() + }) + .map(|framebuffer| Arc::new(framebuffer)) + .collect::>(), + ) } pub(super) fn update_resolution(&mut self, width: u32, height: u32) -> VkResult<()> {