From dd8a5a97ea5403e773da10d56e34c344b21494ae Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Sun, 24 Nov 2024 19:24:28 +0100 Subject: [PATCH] Update --- res/shaders/vertex.frag | 10 +++++++++ res/shaders/vertex.vert | 1 + src/vulkan/mod.rs | 1 + src/vulkan/vertex.rs | 33 ++++++++++++++++++++++++++++++ src/vulkan/vk_graphics_pipeline.rs | 3 --- src/vulkan/vk_render_context.rs | 28 +++++++++++++++++++++---- src/vulkan/vk_render_pass.rs | 2 -- src/vulkan/vk_surface.rs | 1 + src/vulkan/vk_swapchain.rs | 17 +++++++++++---- 9 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 res/shaders/vertex.frag create mode 100644 res/shaders/vertex.vert create mode 100644 src/vulkan/vertex.rs diff --git a/res/shaders/vertex.frag b/res/shaders/vertex.frag new file mode 100644 index 0000000..04f88bd --- /dev/null +++ b/res/shaders/vertex.frag @@ -0,0 +1,10 @@ +#version 450 +#extension GL_ARB_separate_shader_objects: enable + +layout (location = 0) in vec3 fragColor; + +layout (location = 0) out vec4 outColor; + +void main() { + outColor = vec4(fragColor, 1.0); +} \ No newline at end of file diff --git a/res/shaders/vertex.vert b/res/shaders/vertex.vert new file mode 100644 index 0000000..d7b1aac --- /dev/null +++ b/res/shaders/vertex.vert @@ -0,0 +1 @@ +#version 450 #extension GL_ARB_separate_shader_objects: enable // NOTE: names must match the `Vertex` struct in Rust layout (location = 0) in vec2 pos; layout (location = 1) in vec3 color; layout (location = 0) out vec3 fragColor; out gl_PerVertex { vec4 gl_Position; }; void main() { gl_Position = vec4(pos, 0.0, 1.0); fragColor = color; } \ No newline at end of file diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs index aff9b51..5043262 100644 --- a/src/vulkan/mod.rs +++ b/src/vulkan/mod.rs @@ -38,3 +38,4 @@ mod vk_fence; pub(self) use vk_fence::VkFence; mod utils; +mod vertex; diff --git a/src/vulkan/vertex.rs b/src/vulkan/vertex.rs new file mode 100644 index 0000000..fcbd4c5 --- /dev/null +++ b/src/vulkan/vertex.rs @@ -0,0 +1,33 @@ +use ash::vk; +use std::mem::offset_of; + +#[derive(Default)] +pub struct Vertex { + pub position: [f32; 2], + pub color: [f32; 3], +} + +impl Vertex { + pub fn get_binding_description() -> vk::VertexInputBindingDescription { + vk::VertexInputBindingDescription::default() + .binding(0) + .stride(size_of::() as u32) + .input_rate(vk::VertexInputRate::VERTEX) + } + + pub fn get_attribute_descriptions() -> [vk::VertexInputAttributeDescription; 2] { + let position_attribute = vk::VertexInputAttributeDescription::default() + .binding(0) + .location(0) + .format(vk::Format::R32G32_SFLOAT) + .offset(offset_of!(Vertex, position) as u32); + + let color_attribute = vk::VertexInputAttributeDescription::default() + .binding(0) + .location(1) + .format(vk::Format::R32G32B32_SFLOAT) + .offset(offset_of!(Vertex, color) as u32); + + [position_attribute, color_attribute] + } +} \ No newline at end of file diff --git a/src/vulkan/vk_graphics_pipeline.rs b/src/vulkan/vk_graphics_pipeline.rs index bcc3805..9e7d0ed 100644 --- a/src/vulkan/vk_graphics_pipeline.rs +++ b/src/vulkan/vk_graphics_pipeline.rs @@ -6,7 +6,6 @@ use std::sync::Arc; pub struct VkGraphicsPipeline { device: Arc, - swapchain: Arc, render_pass: Arc, pub(super) pipeline_layout: vk::PipelineLayout, @@ -18,7 +17,6 @@ pub struct VkGraphicsPipeline { impl VkGraphicsPipeline { pub fn new( device: &Arc, - swapchain: &Arc, render_pass: &Arc, ) -> anyhow::Result { let shader_entry_name = CStr::from_bytes_with_nul(b"main\0")?; @@ -99,7 +97,6 @@ impl VkGraphicsPipeline { Ok(Self { device: device.clone(), - swapchain: swapchain.clone(), render_pass: render_pass.clone(), pipeline_layout, pipeline, diff --git a/src/vulkan/vk_render_context.rs b/src/vulkan/vk_render_context.rs index 214996f..e4a22f5 100644 --- a/src/vulkan/vk_render_context.rs +++ b/src/vulkan/vk_render_context.rs @@ -62,7 +62,7 @@ impl VkRenderContext { .create_framebuffers(&render_pass) .ok_or_else(|| anyhow::anyhow!("Failed to get framebuffers"))?; - let pipeline = Arc::new(VkGraphicsPipeline::new(&device, &swapchain, &render_pass)?); + let pipeline = Arc::new(VkGraphicsPipeline::new(&device, &render_pass)?); let command_pool = VkCommandPool::new(&device)?; @@ -109,6 +109,10 @@ impl VkRenderContext { .swapchain .acquire_next_image(&self.image_available_semaphore)?; + // if self.swapchain.is_dirty() { + // self.update_swapchain()? + // } + let command_buffer = self.command_buffers[index as usize]; unsafe { self.device.handle.reset_command_buffer(command_buffer, vk::CommandBufferResetFlags::default())? }; @@ -152,7 +156,7 @@ impl VkRenderContext { unsafe { self.device.handle.cmd_set_viewport(command_buffer, 0, &[viewport]) } - let scissor = vk::Rect2D::default().extent(self.swapchain.surface_resolution); + let scissor = self.swapchain.surface_resolution.into(); unsafe { self.device.handle.cmd_set_scissor(command_buffer, 0, &[scissor]) } @@ -196,8 +200,9 @@ impl VkRenderContext { } pub fn update_resolution(&mut self, width: u32, height: u32) -> anyhow::Result<()> { - if let Some(swapchain) = Arc::get_mut(&mut self.swapchain) { - swapchain.update_resolution(width, height)?; + match Arc::get_mut(&mut self.swapchain) { + Some(swapchain) => swapchain.update_resolution(width, height)?, + None => log::warn!("Impossible to get mutable swapchain"), } Ok(()) @@ -206,4 +211,19 @@ impl VkRenderContext { pub fn exit(&self) { unsafe { self.device.handle.device_wait_idle().unwrap() } } + + fn update_swapchain(&mut self) -> anyhow::Result<()> { + match Arc::get_mut(&mut self.swapchain) { + Some(swapchain) => { + swapchain.create_swapchain()?; + + self.framebuffers = self.swapchain + .create_framebuffers(&self.render_pass) + .ok_or_else(|| anyhow::anyhow!("Failed to get framebuffers"))?; + } + None => log::warn!("Impossible to get mutable swapchain"), + } + + Ok(()) + } } diff --git a/src/vulkan/vk_render_pass.rs b/src/vulkan/vk_render_pass.rs index c9fcb7c..b450865 100644 --- a/src/vulkan/vk_render_pass.rs +++ b/src/vulkan/vk_render_pass.rs @@ -5,7 +5,6 @@ use std::sync::Arc; pub struct VkRenderPass { device: Arc, - swapchain: Arc, pub(super) handle: vk::RenderPass, } @@ -42,7 +41,6 @@ impl VkRenderPass { Ok(Self { device: device.clone(), - swapchain: swapchain.clone(), handle: render_pass, }) } diff --git a/src/vulkan/vk_surface.rs b/src/vulkan/vk_surface.rs index dd288f5..4a5a9bc 100644 --- a/src/vulkan/vk_surface.rs +++ b/src/vulkan/vk_surface.rs @@ -12,6 +12,7 @@ pub struct SwapchainSupportDetails( pub struct VkSurface { instance: Arc, + pub(super) surface: vk::SurfaceKHR, } diff --git a/src/vulkan/vk_swapchain.rs b/src/vulkan/vk_swapchain.rs index dc32d99..b60f1ed 100644 --- a/src/vulkan/vk_swapchain.rs +++ b/src/vulkan/vk_swapchain.rs @@ -17,6 +17,7 @@ pub struct VkSwapchain { pub(super) desired_image_count: u32, pub(super) surface_format: vk::SurfaceFormatKHR, pub(super) surface_resolution: vk::Extent2D, + pub(super) new_requested_surface_resolution: Option, pub(super) present_mode: vk::PresentModeKHR, pub(super) pre_transform: vk::SurfaceTransformFlagsKHR, @@ -64,6 +65,7 @@ impl VkSwapchain { device: device.clone(), swapchain: None, + new_requested_surface_resolution: None, swapchain_support_details, desired_image_count, surface_format, @@ -80,6 +82,11 @@ impl VkSwapchain { } pub(super) fn create_swapchain(&mut self) -> VkResult<()> { + if let Some(new_requested_surface_resolution) = self.new_requested_surface_resolution { + self.surface_resolution = new_requested_surface_resolution; + self.new_requested_surface_resolution = None; + } + let mut swapchain_create_info = self.create_swapchain_info(&self.surface); if let Some(old_swapchain) = self.swapchain { @@ -154,14 +161,12 @@ impl VkSwapchain { if chosen_extent.width != self.surface_resolution.width || chosen_extent.height != self.surface_resolution.height { - self.surface_resolution = chosen_extent; + self.new_requested_surface_resolution = Some(chosen_extent); log::debug!( - "New resolution applied ({}x{})", + "New resolution submitted ({}x{})", chosen_extent.width, chosen_extent.height ); - - self.create_swapchain()?; } else { log::debug!("New resolution skipped ({width}x{height}) : Same resolution"); } @@ -180,6 +185,10 @@ impl VkSwapchain { } } + pub(super) fn is_dirty(&self) -> bool { + self.new_requested_surface_resolution.is_some() + } + fn create_swapchain_info(&self, surface: &VkSurface) -> vk::SwapchainCreateInfoKHR { vk::SwapchainCreateInfoKHR::default() .surface(surface.surface)