Refactorisation de la gestion des pipelines

This commit is contained in:
Florian RICHER 2024-12-11 20:16:38 +01:00
parent f65f45fc9a
commit 1169c76b41
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
5 changed files with 155 additions and 143 deletions

View file

@ -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<Image>]) -> Vec<Arc<ImageView>> {
images

View file

@ -0,0 +1,2 @@
mod triangle_pipeline;
pub use triangle_pipeline::create_triangle_pipeline;

View file

@ -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<Device>, swapchain: &Arc<Swapchain>) -> Arc<GraphicsPipeline> {
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()
}

View file

@ -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<GraphicsPipeline>,
vertex_buffer: Subbuffer<[MyVertex]>,
vertex_buffer: Subbuffer<[Vertex2D]>,
}
impl Scene {
pub fn initialize(device: &Arc<Device>, swapchain: &Arc<Swapchain>, memory_allocator: &Arc<StandardMemoryAllocator>) -> 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<StandardMemoryAllocator>,
) -> 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<Device>,
swapchain: &Arc<Swapchain>,
memory_allocator: &Arc<StandardMemoryAllocator>,
) -> 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<PrimaryAutoCommandBuffer>) {
builder.bind_pipeline_graphics(self.pipeline.clone())
builder
.bind_pipeline_graphics(self.pipeline.clone())
.unwrap()
.bind_vertex_buffers(0, self.vertex_buffer.clone())
.unwrap();

18
src/renderer/vertex.rs Normal file
View file

@ -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 }
}
}