From f7ada5471d1f6beae39d24f7bafe9aa7efc30be3 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Wed, 12 Apr 2023 13:23:19 -0400 Subject: [PATCH] Minor refactoring, extract create_buffer method --- src/app.rs | 168 +++++++++++++++++++++++++----------------------- src/app/data.rs | 154 ++++++++++++++++++++++++++------------------ src/lib.rs | 4 +- 3 files changed, 181 insertions(+), 145 deletions(-) diff --git a/src/app.rs b/src/app.rs index b3c0d3e..15004b2 100644 --- a/src/app.rs +++ b/src/app.rs @@ -47,35 +47,37 @@ impl App { /// /// # Safety /// Here be Dragons - pub unsafe fn create(window: &Window) -> Result { - let loader = LibloadingLoader::new(LIBRARY)?; - let entry = Entry::new(loader).map_err(|b| anyhow!("{}", b))?; + pub fn create(window: &Window) -> Result { + unsafe { + let loader = LibloadingLoader::new(LIBRARY)?; + let entry = Entry::new(loader).map_err(|b| anyhow!("{}", b))?; - let mut data = AppData::default(); - let instance = data.create_instance(window, &entry)?; - data.surface = vk_window::create_surface(&instance, window)?; + let mut data = AppData::default(); + let instance = data.create_instance(window, &entry)?; + data.surface = vk_window::create_surface(&instance, window)?; - data.pick_physical_device(&instance)?; - let device = data.create_logical_device(&instance)?; + data.pick_physical_device(&instance)?; + let device = data.create_logical_device(&instance)?; - data.create_swapchain(window, &instance, &device)?; - data.create_swapchain_image_views(&device)?; - data.create_render_pass(&instance, &device)?; - data.create_pipeline(&device)?; - data.create_framebuffers(&device)?; - data.create_command_pool(&instance, &device)?; - data.create_vertex_buffer(&instance, &device)?; - data.create_command_buffers(&device)?; - data.create_sync_objects(&device)?; + data.create_swapchain(window, &instance, &device)?; + data.create_swapchain_image_views(&device)?; + data.create_render_pass(&instance, &device)?; + data.create_pipeline(&device)?; + data.create_framebuffers(&device)?; + data.create_command_pool(&instance, &device)?; + data.create_vertex_buffer(&instance, &device)?; + data.create_command_buffers(&device)?; + data.create_sync_objects(&device)?; - Ok(Self { - _entry: entry, - instance, - data, - device, - frame: 0, - resized: false, - }) + Ok(Self { + _entry: entry, + instance, + data, + device, + frame: 0, + resized: false, + }) + } } /// Destroys our Vulkan app, in reverse order of creation @@ -139,67 +141,69 @@ impl App { /// /// # Safety /// Here be Dragons - pub unsafe fn render(&mut self, window: &Window) -> Result<()> { - let in_flight_fence = self.data.in_flight_fences[self.frame]; + pub fn render(&mut self, window: &Window) -> Result<()> { + unsafe { + let in_flight_fence = self.data.in_flight_fences[self.frame]; - self.device - .wait_for_fences(&[in_flight_fence], true, u64::max_value())?; - let result = self.device.acquire_next_image_khr( - self.data.swapchain, - u64::max_value(), - self.data.image_available_semaphores[self.frame], - vk::Fence::null(), - ); - let image_index = match result { - Ok((image_index, _)) => image_index as usize, - Err(vk::ErrorCode::OUT_OF_DATE_KHR) => return self.recreate_swapchain(window), - Err(e) => return Err(anyhow!(e)), - }; - - let image_in_flight = self.data.images_in_flight[image_index]; - if !image_in_flight.is_null() { self.device - .wait_for_fences(&[image_in_flight], true, u64::max_value())?; + .wait_for_fences(&[in_flight_fence], true, u64::max_value())?; + let result = self.device.acquire_next_image_khr( + self.data.swapchain, + u64::max_value(), + self.data.image_available_semaphores[self.frame], + vk::Fence::null(), + ); + let image_index = match result { + Ok((image_index, _)) => image_index as usize, + Err(vk::ErrorCode::OUT_OF_DATE_KHR) => return self.recreate_swapchain(window), + Err(e) => return Err(anyhow!(e)), + }; + + let image_in_flight = self.data.images_in_flight[image_index]; + if !image_in_flight.is_null() { + self.device + .wait_for_fences(&[image_in_flight], true, u64::max_value())?; + } + + self.data.images_in_flight[image_index] = in_flight_fence; + + let wait_semaphores = &[self.data.image_available_semaphores[self.frame]]; + let wait_stages = &[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; + let command_buffers = &[self.data.command_buffers[image_index]]; + let signal_semaphores = &[self.data.render_finished_semaphores[self.frame]]; + let submit_info = vk::SubmitInfo::builder() + .wait_semaphores(wait_semaphores) + .wait_dst_stage_mask(wait_stages) + .command_buffers(command_buffers) + .signal_semaphores(signal_semaphores); + + self.device.reset_fences(&[in_flight_fence])?; + + self.device + .queue_submit(self.data.graphics_queue, &[submit_info], in_flight_fence)?; + + let swapchains = &[self.data.swapchain]; + let image_indices = &[image_index as u32]; + let present_info = vk::PresentInfoKHR::builder() + .wait_semaphores(signal_semaphores) + .swapchains(swapchains) + .image_indices(image_indices); + + let result = self + .device + .queue_present_khr(self.data.present_queue, &present_info); + + let changed = result == Ok(vk::SuccessCode::SUBOPTIMAL_KHR) + || result == Err(vk::ErrorCode::OUT_OF_DATE_KHR); + if self.resized || changed { + self.recreate_swapchain(window)?; + } else if let Err(e) = result { + return Err(anyhow!(e)); + } + + self.frame = (self.frame + 1) % MAX_FRAMES_IN_FLIGHT; } - self.data.images_in_flight[image_index] = in_flight_fence; - - let wait_semaphores = &[self.data.image_available_semaphores[self.frame]]; - let wait_stages = &[vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; - let command_buffers = &[self.data.command_buffers[image_index]]; - let signal_semaphores = &[self.data.render_finished_semaphores[self.frame]]; - let submit_info = vk::SubmitInfo::builder() - .wait_semaphores(wait_semaphores) - .wait_dst_stage_mask(wait_stages) - .command_buffers(command_buffers) - .signal_semaphores(signal_semaphores); - - self.device.reset_fences(&[in_flight_fence])?; - - self.device - .queue_submit(self.data.graphics_queue, &[submit_info], in_flight_fence)?; - - let swapchains = &[self.data.swapchain]; - let image_indices = &[image_index as u32]; - let present_info = vk::PresentInfoKHR::builder() - .wait_semaphores(signal_semaphores) - .swapchains(swapchains) - .image_indices(image_indices); - - let result = self - .device - .queue_present_khr(self.data.present_queue, &present_info); - - let changed = result == Ok(vk::SuccessCode::SUBOPTIMAL_KHR) - || result == Err(vk::ErrorCode::OUT_OF_DATE_KHR); - if self.resized || changed { - self.recreate_swapchain(window)?; - } else if let Err(e) = result { - return Err(anyhow!(e)); - } - - self.frame = (self.frame + 1) % MAX_FRAMES_IN_FLIGHT; - Ok(()) } diff --git a/src/app/data.rs b/src/app/data.rs index e2d138c..52ee848 100644 --- a/src/app/data.rs +++ b/src/app/data.rs @@ -37,43 +37,47 @@ extern "system" fn debug_callback( /// The Vulkan handles and associated properties used by our Vulkan app. #[derive(Clone, Debug, Default)] -pub struct AppData { +pub(super) struct AppData { // Debug - pub(crate) messenger: vk::DebugUtilsMessengerEXT, + pub(super) messenger: vk::DebugUtilsMessengerEXT, // Surface - pub(crate) surface: vk::SurfaceKHR, + pub(super) surface: vk::SurfaceKHR, // Physical Device / Logical Device - pub(crate) physical_device: vk::PhysicalDevice, - pub(crate) graphics_queue: vk::Queue, - pub(crate) present_queue: vk::Queue, + pub(super) physical_device: vk::PhysicalDevice, + pub(super) graphics_queue: vk::Queue, + pub(super) present_queue: vk::Queue, // Swapchain - pub(crate) swapchain_format: vk::Format, - pub(crate) swapchain_extent: vk::Extent2D, - pub(crate) swapchain: vk::SwapchainKHR, - pub(crate) swapchain_images: Vec, - pub(crate) swapchain_image_views: Vec, + pub(super) swapchain_format: vk::Format, + pub(super) swapchain_extent: vk::Extent2D, + pub(super) swapchain: vk::SwapchainKHR, + pub(super) swapchain_images: Vec, + pub(super) swapchain_image_views: Vec, // Pipeline - pub(crate) render_pass: vk::RenderPass, - pub(crate) pipeline_layout: vk::PipelineLayout, - pub(crate) pipeline: vk::Pipeline, + pub(super) render_pass: vk::RenderPass, + pub(super) pipeline_layout: vk::PipelineLayout, + pub(super) pipeline: vk::Pipeline, // Framebuffers - pub(crate) framebuffers: Vec, + pub(super) framebuffers: Vec, // Command Pool - pub(crate) command_pool: vk::CommandPool, + pub(super) command_pool: vk::CommandPool, // Buffers - pub(crate) vertex_buffer: vk::Buffer, - pub(crate) vertex_buffer_memory: vk::DeviceMemory, + pub(super) vertex_buffer: vk::Buffer, + pub(super) vertex_buffer_memory: vk::DeviceMemory, // Command Buffers - pub(crate) command_buffers: Vec, + pub(super) command_buffers: Vec, // Sync Objects - pub(crate) image_available_semaphores: Vec, - pub(crate) render_finished_semaphores: Vec, - pub(crate) in_flight_fences: Vec, - pub(crate) images_in_flight: Vec, + pub(super) image_available_semaphores: Vec, + pub(super) render_finished_semaphores: Vec, + pub(super) in_flight_fences: Vec, + pub(super) images_in_flight: Vec, } impl AppData { - pub unsafe fn create_instance(&mut self, window: &Window, entry: &Entry) -> Result { + pub(super) unsafe fn create_instance( + &mut self, + window: &Window, + entry: &Entry, + ) -> Result { // Application Info let application_info = vk::ApplicationInfo::builder() .application_name(b"Vulkan Tutorial\0") @@ -534,6 +538,64 @@ impl AppData { Ok(()) } + //================================================ + // Buffers + //================================================ + + pub(super) unsafe fn create_buffer( + &self, + instance: &Instance, + device: &Device, + size: vk::DeviceSize, + usage: vk::BufferUsageFlags, + properties: vk::MemoryPropertyFlags, + ) -> Result<(vk::Buffer, vk::DeviceMemory)> { + let buffer_info = vk::BufferCreateInfo::builder() + .size(size) + .usage(usage) + .sharing_mode(vk::SharingMode::EXCLUSIVE); + + let buffer = device.create_buffer(&buffer_info, None)?; + + let requirements = device.get_buffer_memory_requirements(buffer); + + let memory_info = vk::MemoryAllocateInfo::builder() + .allocation_size(requirements.size) + .memory_type_index(self.get_memory_type_index(instance, properties, requirements)?); + + let buffer_memory = device.allocate_memory(&memory_info, None)?; + + device.bind_buffer_memory(buffer, buffer_memory, 0)?; + + Ok((buffer, buffer_memory)) + } + + pub(super) unsafe fn create_vertex_buffer( + &mut self, + instance: &Instance, + device: &Device, + ) -> Result<()> { + let size = (size_of::() * VERTICES.len()) as u64; + let (vertex_buffer, vertex_buffer_memory) = self.create_buffer( + instance, + device, + size, + vk::BufferUsageFlags::VERTEX_BUFFER, + vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE, + )?; + + self.vertex_buffer = vertex_buffer; + self.vertex_buffer_memory = vertex_buffer_memory; + + let memory = + device.map_memory(vertex_buffer_memory, 0, size, vk::MemoryMapFlags::empty())?; + + memcpy(VERTICES.as_ptr(), memory.cast(), VERTICES.len()); + device.unmap_memory(vertex_buffer_memory); + + Ok(()) + } + //================================================ // Command Buffers //================================================ @@ -590,6 +652,10 @@ impl AppData { Ok(()) } + //================================================ + // Sync Objects + //================================================ + pub(super) unsafe fn create_sync_objects(&mut self, device: &Device) -> Result<()> { let semaphore_info = vk::SemaphoreCreateInfo::builder(); let fence_info = vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED); @@ -613,43 +679,9 @@ impl AppData { Ok(()) } - pub(super) unsafe fn create_vertex_buffer( - &mut self, - instance: &Instance, - device: &Device, - ) -> Result<()> { - let buffer_info = vk::BufferCreateInfo::builder() - .size((size_of::() * VERTICES.len()) as u64) - .usage(vk::BufferUsageFlags::VERTEX_BUFFER) - .sharing_mode(vk::SharingMode::EXCLUSIVE); - - self.vertex_buffer = device.create_buffer(&buffer_info, None)?; - - let requirements = device.get_buffer_memory_requirements(self.vertex_buffer); - let memory_info = vk::MemoryAllocateInfo::builder() - .allocation_size(requirements.size) - .memory_type_index(self.get_memory_type_index( - instance, - vk::MemoryPropertyFlags::HOST_COHERENT | vk::MemoryPropertyFlags::HOST_VISIBLE, - requirements, - )?); - - self.vertex_buffer_memory = device.allocate_memory(&memory_info, None)?; - - device.bind_buffer_memory(self.vertex_buffer, self.vertex_buffer_memory, 0)?; - - let memory = device.map_memory( - self.vertex_buffer_memory, - 0, - buffer_info.size, - vk::MemoryMapFlags::empty(), - )?; - - memcpy(VERTICES.as_ptr(), memory.cast(), VERTICES.len()); - device.unmap_memory(self.vertex_buffer_memory); - - Ok(()) - } + //================================================ + // Shared (Other) + //================================================ unsafe fn get_memory_type_index( &self, diff --git a/src/lib.rs b/src/lib.rs index b728bbe..93eea26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ pub fn run() -> Result<()> { .build(&event_loop)?; // App - let mut app = unsafe { App::create(&window)? }; + let mut app = App::create(&window)?; let mut destroying = false; let mut minimized = false; event_loop.run(move |event, _, control_flow| { @@ -27,7 +27,7 @@ pub fn run() -> Result<()> { match event { // Render a frame if our Vulkan app is not being destroyed Event::MainEventsCleared if !destroying && !minimized => { - unsafe { app.render(&window) }.unwrap() + app.render(&window).unwrap() } // Let the app know it has been resized Event::WindowEvent {