From 5539381f4688b5608c5f6da0c2efdb44add7d401 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Thu, 5 Jun 2025 13:30:55 +0200 Subject: [PATCH] render: Add AsBindableDescriptorSet --- src/core/render/primitives/mod.rs | 21 ++++++++++++ src/core/render/primitives/mvp.rs | 36 ++++++++++++++++++- src/core/render/texture.rs | 57 +++++++++++++++++++++++++++---- src/game/assets/square.rs | 48 +++++--------------------- 4 files changed, 115 insertions(+), 47 deletions(-) diff --git a/src/core/render/primitives/mod.rs b/src/core/render/primitives/mod.rs index 606c12d..5ab8266 100644 --- a/src/core/render/primitives/mod.rs +++ b/src/core/render/primitives/mod.rs @@ -1,4 +1,25 @@ +use std::{collections::BTreeMap, sync::Arc}; + +use vulkano::{ + Validated, VulkanError, + descriptor_set::{ + DescriptorSet, + allocator::StandardDescriptorSetAllocator, + layout::{DescriptorSetLayout, DescriptorSetLayoutBinding}, + }, +}; + pub mod camera; pub mod mvp; pub mod transform; pub mod vertex; + +pub trait AsBindableDescriptorSet { + fn as_descriptor_set_layout_bindings() -> BTreeMap; + + fn as_descriptor_set( + descriptor_set_allocator: &Arc, + layout: &Arc, + data: &T, + ) -> Result, Validated>; +} diff --git a/src/core/render/primitives/mvp.rs b/src/core/render/primitives/mvp.rs index 192c67b..d05307e 100644 --- a/src/core/render/primitives/mvp.rs +++ b/src/core/render/primitives/mvp.rs @@ -1,10 +1,19 @@ +use std::collections::BTreeMap; use std::sync::Arc; -use vulkano::Validated; use vulkano::buffer::{ AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer, }; +use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator; +use vulkano::descriptor_set::layout::{ + DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType, +}; +use vulkano::descriptor_set::{DescriptorSet, WriteDescriptorSet}; use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}; +use vulkano::shader::ShaderStages; +use vulkano::{Validated, VulkanError}; + +use crate::core::render::primitives::AsBindableDescriptorSet; #[derive(BufferContents, Clone, Copy)] #[repr(C)] @@ -34,3 +43,28 @@ impl Mvp { ) } } + +impl AsBindableDescriptorSet> for Mvp { + fn as_descriptor_set_layout_bindings() -> BTreeMap { + BTreeMap::::from_iter([( + 0, + DescriptorSetLayoutBinding { + stages: ShaderStages::VERTEX, + ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer) + }, + )]) + } + + fn as_descriptor_set( + descriptor_set_allocator: &Arc, + layout: &Arc, + data: &Subbuffer<[Mvp]>, + ) -> Result, Validated> { + DescriptorSet::new( + descriptor_set_allocator.clone(), + layout.clone(), + [WriteDescriptorSet::buffer(0, data.clone())], + [], + ) + } +} diff --git a/src/core/render/texture.rs b/src/core/render/texture.rs index 8b7f63c..db0bcc5 100644 --- a/src/core/render/texture.rs +++ b/src/core/render/texture.rs @@ -1,10 +1,15 @@ -use std::{path::Path, sync::Arc}; +use std::{collections::BTreeMap, error::Error, sync::Arc}; -use anyhow::Error; -use image::{DynamicImage, EncodableLayout}; +use image::DynamicImage; use vulkano::{ + Validated, VulkanError, buffer::{Buffer, BufferCreateInfo, BufferUsage}, command_buffer::{AutoCommandBufferBuilder, CopyBufferToImageInfo, PrimaryAutoCommandBuffer}, + descriptor_set::{ + DescriptorSet, WriteDescriptorSet, + allocator::StandardDescriptorSetAllocator, + layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorType}, + }, device::Device, format::Format, image::{ @@ -13,8 +18,11 @@ use vulkano::{ view::ImageView, }, memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator}, + shader::ShaderStages, }; +use crate::core::render::primitives::AsBindableDescriptorSet; + pub struct Texture { texture: Arc, sampler: Arc, @@ -30,7 +38,7 @@ impl Texture { memory_allocator: &Arc, builder: &mut AutoCommandBufferBuilder, path: &str, - ) -> Result { + ) -> Result> { let _span = tracing::info_span!("texture_load_from_file", path = path); let bytes = std::fs::read(path)?; @@ -42,7 +50,7 @@ impl Texture { memory_allocator: &Arc, builder: &mut AutoCommandBufferBuilder, bytes: &[u8], - ) -> Result { + ) -> Result> { let image = image::load_from_memory(bytes)?; Self::from_dynamic_image(device, memory_allocator, builder, image) } @@ -52,7 +60,7 @@ impl Texture { memory_allocator: &Arc, builder: &mut AutoCommandBufferBuilder, image: DynamicImage, - ) -> Result { + ) -> Result> { let _span = tracing::info_span!("texture_from_dynamic_image"); let image_data = image.to_rgba8(); @@ -121,3 +129,40 @@ impl Texture { &self.sampler } } + +impl AsBindableDescriptorSet for Texture { + fn as_descriptor_set_layout_bindings() -> BTreeMap { + BTreeMap::::from_iter([ + ( + 0, + DescriptorSetLayoutBinding { + stages: ShaderStages::FRAGMENT, + ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::Sampler) + }, + ), + ( + 1, + DescriptorSetLayoutBinding { + stages: ShaderStages::FRAGMENT, + ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::SampledImage) + }, + ), + ]) + } + + fn as_descriptor_set( + descriptor_set_allocator: &Arc, + layout: &Arc, + data: &Texture, + ) -> Result, Validated> { + DescriptorSet::new( + descriptor_set_allocator.clone(), + layout.clone(), + [ + WriteDescriptorSet::sampler(0, data.sampler.clone()), + WriteDescriptorSet::image_view(1, data.texture.clone()), + ], + [], + ) + } +} diff --git a/src/game/assets/square.rs b/src/game/assets/square.rs index 7219157..c4a33ad 100644 --- a/src/game/assets/square.rs +++ b/src/game/assets/square.rs @@ -31,7 +31,7 @@ use vulkano::{ }; use crate::core::render::{ - primitives::{mvp::Mvp, transform::TransformRaw, vertex::Vertex3D}, + primitives::{AsBindableDescriptorSet, mvp::Mvp, transform::TransformRaw, vertex::Vertex3D}, texture::Texture, }; @@ -130,29 +130,8 @@ impl Square { PipelineShaderStageCreateInfo::new(fs), ]; - let vertex_bindings = BTreeMap::::from_iter([( - 0, - DescriptorSetLayoutBinding { - stages: ShaderStages::VERTEX, - ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::UniformBuffer) - }, - )]); - let fragment_bindings = BTreeMap::::from_iter([ - ( - 0, - DescriptorSetLayoutBinding { - stages: ShaderStages::FRAGMENT, - ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::Sampler) - }, - ), - ( - 1, - DescriptorSetLayoutBinding { - stages: ShaderStages::FRAGMENT, - ..DescriptorSetLayoutBinding::descriptor_type(DescriptorType::SampledImage) - }, - ), - ]); + let vertex_bindings = Mvp::as_descriptor_set_layout_bindings(); + let texture_bindings = Texture::as_descriptor_set_layout_bindings(); let vertex_descriptor_set_layout = DescriptorSetLayoutCreateInfo { bindings: vertex_bindings, @@ -160,7 +139,7 @@ impl Square { }; let fragment_descriptor_set_layout = DescriptorSetLayoutCreateInfo { - bindings: fragment_bindings, + bindings: texture_bindings, ..Default::default() }; @@ -220,22 +199,11 @@ impl Square { ) -> Result<(), Box> { let layouts = self.pipeline.layout().set_layouts(); - let uniform_descriptor_set = DescriptorSet::new( - descriptor_set_allocator.clone(), - layouts[0].clone(), - [WriteDescriptorSet::buffer(0, mvp_uniform.clone())], - [], - )?; + let uniform_descriptor_set = + Mvp::as_descriptor_set(descriptor_set_allocator, &layouts[0], mvp_uniform)?; - let texture_descriptor_set = DescriptorSet::new( - descriptor_set_allocator.clone(), - layouts[1].clone(), - [ - WriteDescriptorSet::sampler(0, texture.get_sampler().clone()), - WriteDescriptorSet::image_view(1, texture.get_texture().clone()), - ], - [], - )?; + let texture_descriptor_set = + Texture::as_descriptor_set(descriptor_set_allocator, &layouts[1], texture)?; command_buffer.bind_pipeline_graphics(self.pipeline.clone())?; command_buffer.bind_descriptor_sets(