Reduce Generics in pipeline rendering

This commit is contained in:
Florian RICHER 2025-06-09 16:12:21 +02:00
parent 90a5b5d117
commit 0174aeb60e
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
8 changed files with 92 additions and 76 deletions

View file

@ -7,7 +7,9 @@ use vulkano::{
pipeline::GraphicsPipeline, pipeline::GraphicsPipeline,
}; };
pub trait AsRecordable<T, V, MI, I> use super::AsDescriptorSet;
pub trait AsRecordable<V, MI, I>
where where
MI: Into<IndexBuffer> + Clone, MI: Into<IndexBuffer> + Clone,
{ {
@ -17,7 +19,7 @@ where
pipeline: &Arc<GraphicsPipeline>, pipeline: &Arc<GraphicsPipeline>,
mesh: &impl AsRenderableMesh<V, MI>, mesh: &impl AsRenderableMesh<V, MI>,
instances: &impl AsRenderableMeshInstance<I>, instances: &impl AsRenderableMeshInstance<I>,
extra_data: &T, descriptor_sets: Vec<Arc<dyn AsDescriptorSet>>,
) -> Result<(), Box<dyn Error>>; ) -> Result<(), Box<dyn Error>>;
fn record_draw_commands( fn record_draw_commands(

View file

@ -0,0 +1,22 @@
use std::{collections::BTreeMap, sync::Arc};
use vulkano::{
Validated, VulkanError,
descriptor_set::{
DescriptorSet,
allocator::StandardDescriptorSetAllocator,
layout::{DescriptorSetLayout, DescriptorSetLayoutBinding},
},
};
pub trait AsDescriptorSetLayoutBindings {
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding>;
}
pub trait AsDescriptorSet {
fn as_descriptor_set(
&self,
descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>,
layout: &Arc<DescriptorSetLayout>,
) -> Result<Arc<DescriptorSet>, Validated<VulkanError>>;
}

View file

@ -1,16 +1,6 @@
use std::{collections::BTreeMap, sync::Arc};
use vulkano::{
Validated, VulkanError,
descriptor_set::{
DescriptorSet,
allocator::StandardDescriptorSetAllocator,
layout::{DescriptorSetLayout, DescriptorSetLayoutBinding},
},
};
mod buffer; mod buffer;
mod command; mod command;
mod descriptor_set;
pub mod camera; pub mod camera;
pub mod mvp; pub mod mvp;
@ -19,13 +9,4 @@ pub mod transform;
pub mod vertex; pub mod vertex;
pub use buffer::{AsBindableBuffer, AsIndexBuffer, AsUniformBuffer, AsVertexBuffer}; pub use buffer::{AsBindableBuffer, AsIndexBuffer, AsUniformBuffer, AsVertexBuffer};
pub use command::{AsRecordable, AsRenderableMesh, AsRenderableMeshInstance}; pub use command::{AsRecordable, AsRenderableMesh, AsRenderableMeshInstance};
pub use descriptor_set::{AsDescriptorSet, AsDescriptorSetLayoutBindings};
pub trait AsBindableDescriptorSet<T> {
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding>;
fn as_descriptor_set(
descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>,
layout: &Arc<DescriptorSetLayout>,
data: &T,
) -> Result<Arc<DescriptorSet>, Validated<VulkanError>>;
}

View file

@ -13,7 +13,9 @@ use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, Standar
use vulkano::shader::ShaderStages; use vulkano::shader::ShaderStages;
use vulkano::{Validated, VulkanError}; use vulkano::{Validated, VulkanError};
use crate::core::render::primitives::{AsBindableBuffer, AsBindableDescriptorSet, AsUniformBuffer}; use crate::core::render::primitives::{AsBindableBuffer, AsUniformBuffer};
use super::{AsDescriptorSet, AsDescriptorSetLayoutBindings};
#[derive(BufferContents, Clone, Copy)] #[derive(BufferContents, Clone, Copy)]
#[repr(C)] #[repr(C)]
@ -57,7 +59,7 @@ impl AsBindableBuffer<Mvp> for Mvp {
impl AsUniformBuffer<Mvp> for Mvp {} impl AsUniformBuffer<Mvp> for Mvp {}
impl AsBindableDescriptorSet<Subbuffer<[Mvp]>> for Mvp { impl AsDescriptorSetLayoutBindings for Mvp {
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding> { fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding> {
BTreeMap::<u32, DescriptorSetLayoutBinding>::from_iter([( BTreeMap::<u32, DescriptorSetLayoutBinding>::from_iter([(
0, 0,
@ -67,16 +69,18 @@ impl AsBindableDescriptorSet<Subbuffer<[Mvp]>> for Mvp {
}, },
)]) )])
} }
}
impl AsDescriptorSet for Subbuffer<[Mvp]> {
fn as_descriptor_set( fn as_descriptor_set(
&self,
descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>, descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>,
layout: &Arc<DescriptorSetLayout>, layout: &Arc<DescriptorSetLayout>,
data: &Subbuffer<[Mvp]>,
) -> Result<Arc<DescriptorSet>, Validated<VulkanError>> { ) -> Result<Arc<DescriptorSet>, Validated<VulkanError>> {
DescriptorSet::new( DescriptorSet::new(
descriptor_set_allocator.clone(), descriptor_set_allocator.clone(),
layout.clone(), layout.clone(),
[WriteDescriptorSet::buffer(0, data.clone())], [WriteDescriptorSet::buffer(0, self.clone())],
[], [],
) )
} }

View file

@ -27,7 +27,7 @@ pub struct TextureLoadInfo {
} }
pub struct TextureLoader { pub struct TextureLoader {
loaded_textures: HashMap<String, Texture>, loaded_textures: HashMap<String, Arc<Texture>>,
pending_textures: HashMap<String, TextureLoadInfo>, pending_textures: HashMap<String, TextureLoadInfo>,
device: Arc<Device>, device: Arc<Device>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>, command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
@ -102,7 +102,7 @@ impl TextureLoader {
)?, )?,
}; };
loading_textures.insert(name.clone(), texture); loading_textures.insert(name.clone(), Arc::new(texture));
tracing::trace!("Loaded texture: {}", name); tracing::trace!("Loaded texture: {}", name);
} }
@ -113,7 +113,7 @@ impl TextureLoader {
Ok(()) Ok(())
} }
pub fn get_texture(&self, name: &str) -> Option<&Texture> { pub fn get_texture(&self, name: &str) -> Option<&Arc<Texture>> {
self.loaded_textures.get(name) self.loaded_textures.get(name)
} }

View file

@ -17,7 +17,7 @@ use vulkano::{
shader::ShaderStages, shader::ShaderStages,
}; };
use crate::core::render::primitives::AsBindableDescriptorSet; use crate::core::render::primitives::{AsDescriptorSet, AsDescriptorSetLayoutBindings};
use super::TextureLoadInfo; use super::TextureLoadInfo;
@ -112,7 +112,7 @@ impl Texture {
} }
} }
impl AsBindableDescriptorSet<Texture> for Texture { impl AsDescriptorSetLayoutBindings for Texture {
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding> { fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding> {
BTreeMap::<u32, DescriptorSetLayoutBinding>::from_iter([ BTreeMap::<u32, DescriptorSetLayoutBinding>::from_iter([
( (
@ -131,18 +131,20 @@ impl AsBindableDescriptorSet<Texture> for Texture {
), ),
]) ])
} }
}
impl AsDescriptorSet for Texture {
fn as_descriptor_set( fn as_descriptor_set(
&self,
descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>, descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>,
layout: &Arc<DescriptorSetLayout>, layout: &Arc<DescriptorSetLayout>,
data: &Texture,
) -> Result<Arc<DescriptorSet>, Validated<VulkanError>> { ) -> Result<Arc<DescriptorSet>, Validated<VulkanError>> {
DescriptorSet::new( DescriptorSet::new(
descriptor_set_allocator.clone(), descriptor_set_allocator.clone(),
layout.clone(), layout.clone(),
[ [
WriteDescriptorSet::sampler(0, data.sampler.clone()), WriteDescriptorSet::sampler(0, self.sampler.clone()),
WriteDescriptorSet::image_view(1, data.texture.clone()), WriteDescriptorSet::image_view(1, self.texture.clone()),
], ],
[], [],
) )

View file

@ -1,4 +1,4 @@
use std::{error::Error, sync::Arc}; use std::{collections::HashMap, error::Error, sync::Arc};
use vulkano::{ use vulkano::{
buffer::Subbuffer, buffer::Subbuffer,
@ -28,17 +28,12 @@ use vulkano::{
use crate::core::render::{ use crate::core::render::{
primitives::{ primitives::{
AsBindableDescriptorSet, AsRecordable, AsRenderableMesh, AsRenderableMeshInstance, AsDescriptorSet, AsDescriptorSetLayoutBindings, AsRecordable, AsRenderableMesh,
mvp::Mvp, transform::TransformRaw, vertex::Vertex3D, AsRenderableMeshInstance, mvp::Mvp, transform::TransformRaw, vertex::Vertex3D,
}, },
resources::texture::Texture, resources::texture::Texture,
}; };
pub struct SimplePipelineRenderData<'a> {
pub mvp_uniform: &'a Subbuffer<[Mvp]>,
pub texture: &'a Texture,
}
pub struct SimplePipeline { pub struct SimplePipeline {
pipeline: Arc<GraphicsPipeline>, pipeline: Arc<GraphicsPipeline>,
} }
@ -125,33 +120,35 @@ impl SimplePipeline {
} }
} }
impl<'a> AsRecordable<SimplePipelineRenderData<'a>, Vertex3D, Subbuffer<[u32]>, TransformRaw> impl AsRecordable<Vertex3D, Subbuffer<[u32]>, TransformRaw> for SimplePipeline {
for SimplePipeline
{
fn record_bind_commands( fn record_bind_commands(
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>, builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>, descriptor_set_allocator: &Arc<StandardDescriptorSetAllocator>,
pipeline: &Arc<GraphicsPipeline>, pipeline: &Arc<GraphicsPipeline>,
mesh: &impl AsRenderableMesh<Vertex3D, Subbuffer<[u32]>>, mesh: &impl AsRenderableMesh<Vertex3D, Subbuffer<[u32]>>,
instances: &impl AsRenderableMeshInstance<TransformRaw>, instances: &impl AsRenderableMeshInstance<TransformRaw>,
data: &SimplePipelineRenderData<'a>, descriptor_sets: Vec<Arc<dyn AsDescriptorSet>>,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
let layouts = pipeline.layout().set_layouts();
let uniform_descriptor_set =
Mvp::as_descriptor_set(descriptor_set_allocator, &layouts[0], data.mvp_uniform)?;
let texture_descriptor_set =
Texture::as_descriptor_set(descriptor_set_allocator, &layouts[1], data.texture)?;
builder.bind_pipeline_graphics(pipeline.clone())?; builder.bind_pipeline_graphics(pipeline.clone())?;
builder.bind_descriptor_sets( if !descriptor_sets.is_empty() {
PipelineBindPoint::Graphics, let layouts = pipeline.layout().set_layouts();
pipeline.layout().clone(),
0, let descriptor_sets = descriptor_sets
vec![uniform_descriptor_set, texture_descriptor_set], .iter()
)?; .enumerate()
.map(|(layout_index, data)| {
data.as_descriptor_set(descriptor_set_allocator, &layouts[layout_index])
})
.collect::<Result<Vec<_>, _>>()?;
builder.bind_descriptor_sets(
PipelineBindPoint::Graphics,
pipeline.layout().clone(),
0,
descriptor_sets,
)?;
}
builder.bind_vertex_buffers( builder.bind_vertex_buffers(
0, 0,

View file

@ -1,19 +1,19 @@
use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::sync::Arc;
use super::settings_scene::SettingsScene; use super::settings_scene::SettingsScene;
use crate::core::app::DEPTH_IMAGE_ID; use crate::core::app::DEPTH_IMAGE_ID;
use crate::core::app::context::WindowContext; use crate::core::app::context::WindowContext;
use crate::core::app::user_event::UserEvent; use crate::core::app::user_event::UserEvent;
use crate::core::render::primitives::AsRecordable;
use crate::core::render::primitives::camera::Camera3D; use crate::core::render::primitives::camera::Camera3D;
use crate::core::render::primitives::transform::Transform; use crate::core::render::primitives::transform::Transform;
use crate::core::render::primitives::{AsDescriptorSet, AsRecordable};
use crate::core::render::render_pass_manager::{RenderPassConfig, RenderPassManager}; use crate::core::render::render_pass_manager::{RenderPassConfig, RenderPassManager};
use crate::core::render::resources::meshes::{ObjMesh, SquareMesh}; use crate::core::render::resources::meshes::{ObjMesh, SquareMesh};
use crate::core::render::resources::texture::{ use crate::core::render::resources::texture::{TextureLoadInfo, TextureLoader, TextureSourceKind};
Texture, TextureLoadInfo, TextureLoader, TextureSourceKind,
};
use crate::core::scene::Scene; use crate::core::scene::Scene;
use crate::game::assets::pipelines::simple::{SimplePipeline, SimplePipelineRenderData}; use crate::game::assets::pipelines::simple::SimplePipeline;
use egui_winit_vulkano::egui; use egui_winit_vulkano::egui;
use glam::EulerRot; use glam::EulerRot;
use glam::Quat; use glam::Quat;
@ -21,7 +21,7 @@ use glam::Vec3;
use vulkano::format::Format; use vulkano::format::Format;
use vulkano::image::sampler::{Filter, SamplerAddressMode, SamplerCreateInfo}; use vulkano::image::sampler::{Filter, SamplerAddressMode, SamplerCreateInfo};
use vulkano::{ use vulkano::{
command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract}, command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage},
sync::GpuFuture, sync::GpuFuture,
}; };
use winit::window::CursorGrabMode; use winit::window::CursorGrabMode;
@ -250,7 +250,7 @@ impl Scene for MainScene {
} }
// Create camera uniform using the actual camera // Create camera uniform using the actual camera
let camera_uniform = state.camera.create_buffer(&app_context.memory_allocator)?; let camera_uniform = Arc::new(state.camera.create_buffer(&app_context.memory_allocator)?);
let square_transform_uniform = let square_transform_uniform =
Transform::create_buffer(&app_context.memory_allocator, &state.square_instances)?; Transform::create_buffer(&app_context.memory_allocator, &state.square_instances)?;
let obj_transform_uniform = let obj_transform_uniform =
@ -262,10 +262,14 @@ impl Scene for MainScene {
state.simple_pipeline.pipeline(), state.simple_pipeline.pipeline(),
&state.square, &state.square,
&square_transform_uniform, &square_transform_uniform,
&SimplePipelineRenderData { vec![
mvp_uniform: &camera_uniform, camera_uniform.clone() as Arc<dyn AsDescriptorSet>,
texture: &state.texture_loader.get_texture("wooden-crate").unwrap(), state
}, .texture_loader
.get_texture("wooden-crate")
.unwrap()
.clone(),
],
)?; )?;
SimplePipeline::record_draw_commands( SimplePipeline::record_draw_commands(
&mut builder, &mut builder,
@ -279,10 +283,14 @@ impl Scene for MainScene {
state.simple_pipeline.pipeline(), state.simple_pipeline.pipeline(),
&state.obj, &state.obj,
&obj_transform_uniform, &obj_transform_uniform,
&SimplePipelineRenderData { vec![
mvp_uniform: &camera_uniform, camera_uniform.clone() as Arc<dyn AsDescriptorSet>,
texture: &state.texture_loader.get_texture("cube-diffuse").unwrap(), state
}, .texture_loader
.get_texture("cube-diffuse")
.unwrap()
.clone(),
],
)?; )?;
SimplePipeline::record_draw_commands(&mut builder, &state.obj, &obj_transform_uniform)?; SimplePipeline::record_draw_commands(&mut builder, &state.obj, &obj_transform_uniform)?;