From 1169c76b41698a9cba263700f784fcb8b16302ba Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Wed, 11 Dec 2024 20:16:38 +0100 Subject: [PATCH] Refactorisation de la gestion des pipelines --- src/renderer/mod.rs | 5 +- src/renderer/pipelines/mod.rs | 2 + src/renderer/pipelines/triangle_pipeline.rs | 85 +++++++++ src/renderer/scene.rs | 188 +++++--------------- src/renderer/vertex.rs | 18 ++ 5 files changed, 155 insertions(+), 143 deletions(-) create mode 100644 src/renderer/pipelines/mod.rs create mode 100644 src/renderer/pipelines/triangle_pipeline.rs create mode 100644 src/renderer/vertex.rs diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index e72d412..d056eb7 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,15 +1,18 @@ mod render_context; mod app; +mod vertex; +mod pipelines; pub use app::App; +pub use pipelines::create_triangle_pipeline; mod scene; pub use scene::Scene; +pub use vertex::Vertex2D; use std::sync::Arc; use vulkano::image::Image; use vulkano::image::view::ImageView; - /// This function is called once during initialization, then again whenever the window is resized. fn window_size_dependent_setup(images: &[Arc]) -> Vec> { images diff --git a/src/renderer/pipelines/mod.rs b/src/renderer/pipelines/mod.rs new file mode 100644 index 0000000..db588d1 --- /dev/null +++ b/src/renderer/pipelines/mod.rs @@ -0,0 +1,2 @@ +mod triangle_pipeline; +pub use triangle_pipeline::create_triangle_pipeline; \ No newline at end of file diff --git a/src/renderer/pipelines/triangle_pipeline.rs b/src/renderer/pipelines/triangle_pipeline.rs new file mode 100644 index 0000000..e9de828 --- /dev/null +++ b/src/renderer/pipelines/triangle_pipeline.rs @@ -0,0 +1,85 @@ +use std::sync::Arc; +use vulkano::device::Device; +use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition}; +use vulkano::pipeline::{DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo}; +use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState}; +use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo; +use vulkano::pipeline::graphics::input_assembly::InputAssemblyState; +use vulkano::pipeline::graphics::multisample::MultisampleState; +use vulkano::pipeline::graphics::rasterization::RasterizationState; +use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo; +use vulkano::pipeline::graphics::viewport::ViewportState; +use vulkano::pipeline::layout::PipelineDescriptorSetLayoutCreateInfo; +use vulkano::swapchain::Swapchain; + +use crate::renderer::Vertex2D; + +mod shaders { + pub mod vs { + vulkano_shaders::shader! { + ty: "vertex", + path: r"res/shaders/vertex.vert", + } + } + + pub mod fs { + vulkano_shaders::shader! { + ty: "fragment", + path: r"res/shaders/vertex.frag", + } + } +} + +pub fn create_triangle_pipeline(device: &Arc, swapchain: &Arc) -> Arc { + let vs = shaders::vs::load(device.clone()) + .unwrap() + .entry_point("main") + .unwrap(); + let fs = shaders::fs::load(device.clone()) + .unwrap() + .entry_point("main") + .unwrap(); + + let vertex_input_state = Vertex2D::per_vertex() + .definition(&vs) + .unwrap(); + + let stages = [ + PipelineShaderStageCreateInfo::new(vs), + PipelineShaderStageCreateInfo::new(fs), + ]; + + let layout = PipelineLayout::new( + device.clone(), + PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages) + .into_pipeline_layout_create_info(device.clone()) + .unwrap(), + ) + .unwrap(); + + let subpass = PipelineRenderingCreateInfo { + color_attachment_formats: vec![Some(swapchain.image_format())], + ..Default::default() + }; + + GraphicsPipeline::new( + device.clone(), + None, + GraphicsPipelineCreateInfo { + stages: stages.into_iter().collect(), + vertex_input_state: Some(vertex_input_state), + input_assembly_state: Some(InputAssemblyState::default()), + viewport_state: Some(ViewportState::default()), + rasterization_state: Some(RasterizationState::default()), + multisample_state: Some(MultisampleState::default()), + color_blend_state: Some(ColorBlendState::with_attachment_states( + subpass.color_attachment_formats.len() as u32, + ColorBlendAttachmentState::default(), + )), + dynamic_state: [DynamicState::Viewport].into_iter().collect(), + subpass: Some(subpass.into()), + ..GraphicsPipelineCreateInfo::layout(layout) + }, + ) + .unwrap() +} diff --git a/src/renderer/scene.rs b/src/renderer/scene.rs index 5b76973..f8fe8aa 100644 --- a/src/renderer/scene.rs +++ b/src/renderer/scene.rs @@ -1,163 +1,57 @@ use std::sync::Arc; -use vulkano::buffer::{Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer}; +use vulkano::buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer}; use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer}; use vulkano::device::Device; use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}; -use vulkano::pipeline::graphics::vertex_input::{Vertex, VertexDefinition}; -use vulkano::pipeline::{DynamicState, GraphicsPipeline, PipelineLayout, PipelineShaderStageCreateInfo}; -use vulkano::pipeline::graphics::color_blend::{ColorBlendAttachmentState, ColorBlendState}; -use vulkano::pipeline::graphics::GraphicsPipelineCreateInfo; -use vulkano::pipeline::graphics::input_assembly::InputAssemblyState; -use vulkano::pipeline::graphics::multisample::MultisampleState; -use vulkano::pipeline::graphics::rasterization::RasterizationState; -use vulkano::pipeline::graphics::subpass::PipelineRenderingCreateInfo; -use vulkano::pipeline::graphics::viewport::ViewportState; -use vulkano::pipeline::layout::PipelineDescriptorSetLayoutCreateInfo; +use vulkano::pipeline::GraphicsPipeline; use vulkano::swapchain::Swapchain; -// We use `#[repr(C)]` here to force rustc to use a defined layout for our data, as the default -// representation has *no guarantees*. -#[derive(BufferContents, Vertex)] -#[repr(C)] -struct MyVertex { - #[format(R32G32_SFLOAT)] - position: [f32; 2], - - #[format(R32G32B32_SFLOAT)] - color: [f32; 3], -} +use crate::renderer::{Vertex2D, create_triangle_pipeline}; pub struct Scene { pipeline: Arc, - vertex_buffer: Subbuffer<[MyVertex]>, + vertex_buffer: Subbuffer<[Vertex2D]>, } impl Scene { - pub fn initialize(device: &Arc, swapchain: &Arc, memory_allocator: &Arc) -> Scene { - mod vs { - vulkano_shaders::shader! { - ty: "vertex", - path: r"res/shaders/vertex.vert", - } - } - - mod fs { - vulkano_shaders::shader! { - ty: "fragment", - path: r"res/shaders/vertex.frag", - } - } - - let pipeline = { - let vs = vs::load(device.clone()) - .unwrap() - .entry_point("main") - .unwrap(); - let fs = fs::load(device.clone()) - .unwrap() - .entry_point("main") - .unwrap(); - - let vertex_input_state = MyVertex::per_vertex().definition(&vs).unwrap(); - - let stages = [ - PipelineShaderStageCreateInfo::new(vs), - PipelineShaderStageCreateInfo::new(fs), - ]; - - let layout = PipelineLayout::new( - device.clone(), - PipelineDescriptorSetLayoutCreateInfo::from_stages(&stages) - .into_pipeline_layout_create_info(device.clone()) - .unwrap(), - ) - .unwrap(); - - let subpass = PipelineRenderingCreateInfo { - color_attachment_formats: vec![Some(swapchain.image_format())], - ..Default::default() - }; - - GraphicsPipeline::new( - device.clone(), - None, - GraphicsPipelineCreateInfo { - stages: stages.into_iter().collect(), - vertex_input_state: Some(vertex_input_state), - input_assembly_state: Some(InputAssemblyState::default()), - viewport_state: Some(ViewportState::default()), - rasterization_state: Some(RasterizationState::default()), - multisample_state: Some(MultisampleState::default()), - color_blend_state: Some(ColorBlendState::with_attachment_states( - subpass.color_attachment_formats.len() as u32, - ColorBlendAttachmentState::default(), - )), - dynamic_state: [DynamicState::Viewport].into_iter().collect(), - subpass: Some(subpass.into()), - ..GraphicsPipelineCreateInfo::layout(layout) - }, - ) - .unwrap() - }; - + fn create_vertex_buffer( + memory_allocator: &Arc, + ) -> Subbuffer<[Vertex2D]> { let vertices = [ // Triangle en haut à gauche - MyVertex { - position: [-0.5, -0.75], // Coin supérieur gauche - color: [1.0, 0.0, 0.0], // Couleur rouge - }, - MyVertex { - position: [-0.75, -0.25], // Coin supérieur - color: [0.0, 1.0, 0.0], // Couleur verte - }, - MyVertex { - position: [-0.25, -0.25], // Coin supérieur droit - color: [0.0, 0.0, 1.0], // Couleur bleue - }, + Vertex2D::new([-0.5, -0.75], // Coin supérieur gauche + [1.0, 0.0, 0.0]), // Couleur rouge + Vertex2D::new([-0.75, -0.25], // Coin supérieur + [0.0, 1.0, 0.0]), // Couleur verte + Vertex2D::new([-0.25, -0.25], // Coin supérieur droit + [0.0, 0.0, 1.0]), // Couleur bleue // Triangle en bas à gauche - MyVertex { - position: [-0.5, 0.25], // Coin inférieur gauche - color: [0.5, 0.5, 0.5], // Couleur gris - }, - MyVertex { - position: [-0.75, 0.75], // Coin inférieur - color: [0.2, 0.8, 0.2], // Couleur vert clair - }, - MyVertex { - position: [-0.25, 0.75], // Coin inférieur droit - color: [0.8, 0.2, 0.2], // Couleur rouge clair - }, + Vertex2D::new([-0.5, 0.25], // Coin inférieur gauche + [0.5, 0.5, 0.5]), // Couleur gris + Vertex2D::new([-0.75, 0.75], // Coin inférieur + [0.2, 0.8, 0.2]), // Couleur vert clair + Vertex2D::new([-0.25, 0.75], // Coin inférieur droit + [0.8, 0.2, 0.2]), // Couleur rouge clair // Triangle en haut à droite - MyVertex { - position: [0.5, -0.75], // Coin gauche supérieur - color: [1.0, 1.0, 0.0], // Couleur jaune - }, - MyVertex { - position: [0.25, -0.25], // Coin gauche - color: [0.0, 1.0, 1.0], // Couleur cyan - }, - MyVertex { - position: [0.75, -0.25], // Coin gauche inférieur - color: [1.0, 0.0, 1.0], // Couleur magenta - }, + Vertex2D::new([0.5, -0.75], // Coin gauche supérieur + [1.0, 1.0, 0.0]), // Couleur jaune + Vertex2D::new([0.25, -0.25], // Coin gauche + [0.0, 1.0, 1.0]), // Couleur cyan + Vertex2D::new([0.75, -0.25], // Coin gauche inférieur + [1.0, 0.0, 1.0]), // Couleur magenta // Triangle en bas à droite - MyVertex { - position: [0.5, 0.25], // Coin droit supérieur - color: [0.1, 0.5, 0.8], // Couleur bleu clair - }, - MyVertex { - position: [0.25, 0.75], // Coin droit - color: [0.8, 0.6, 0.1], // Couleur or - }, - MyVertex { - position: [0.75, 0.75], // Coin droit inférieur - color: [0.3, 0.4, 0.6], // Couleur bleu foncé - }, + Vertex2D::new([0.5, 0.25], // Coin droit supérieur + [0.1, 0.5, 0.8]), // Couleur bleu clair + Vertex2D::new([0.25, 0.75], // Coin droit + [0.8, 0.6, 0.1]), // Couleur or + Vertex2D::new([0.75, 0.75], // Coin droit inférieur + [0.3, 0.4, 0.6]), // Couleur bleu foncé ]; - let vertex_buffer = Buffer::from_iter( + + Buffer::from_iter( memory_allocator.clone(), BufferCreateInfo { usage: BufferUsage::VERTEX_BUFFER, @@ -170,16 +64,26 @@ impl Scene { }, vertices, ) - .unwrap(); + .unwrap() + } - Self { + pub fn initialize( + device: &Arc, + swapchain: &Arc, + memory_allocator: &Arc, + ) -> Scene { + let pipeline = create_triangle_pipeline(device, swapchain); + let vertex_buffer = Self::create_vertex_buffer(memory_allocator); + + Scene { pipeline, vertex_buffer, } } pub fn render(&self, builder: &mut AutoCommandBufferBuilder) { - builder.bind_pipeline_graphics(self.pipeline.clone()) + builder + .bind_pipeline_graphics(self.pipeline.clone()) .unwrap() .bind_vertex_buffers(0, self.vertex_buffer.clone()) .unwrap(); diff --git a/src/renderer/vertex.rs b/src/renderer/vertex.rs new file mode 100644 index 0000000..8eb4ff5 --- /dev/null +++ b/src/renderer/vertex.rs @@ -0,0 +1,18 @@ +use vulkano::buffer::BufferContents; +use vulkano::pipeline::graphics::vertex_input::Vertex; + +#[derive(BufferContents, Vertex)] +#[repr(C)] +pub struct Vertex2D { + #[format(R32G32_SFLOAT)] + pub position: [f32; 2], + + #[format(R32G32B32_SFLOAT)] + pub color: [f32; 3], +} + +impl Vertex2D { + pub fn new(position: [f32; 2], color: [f32; 3]) -> Self { + Self { position, color } + } +}