Add traits
This commit is contained in:
parent
5539381f46
commit
1a61aab218
9 changed files with 663 additions and 94 deletions
83
src/core/render/primitives/buffer.rs
Normal file
83
src/core/render/primitives/buffer.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use std::{error::Error, sync::Arc};
|
||||
|
||||
use vulkano::{
|
||||
Validated,
|
||||
buffer::{AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, Subbuffer},
|
||||
memory::allocator::{AllocationCreateInfo, StandardMemoryAllocator},
|
||||
};
|
||||
|
||||
pub trait AsBindableBuffer<T> {
|
||||
type BufferData: BufferContents + Clone;
|
||||
|
||||
fn buffer_create_info() -> BufferCreateInfo;
|
||||
|
||||
fn allocation_create_info() -> AllocationCreateInfo;
|
||||
|
||||
fn to_buffer_data(data: &T) -> Self::BufferData;
|
||||
|
||||
fn create_buffer(
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
data: &T,
|
||||
) -> Result<Subbuffer<[Self::BufferData]>, Validated<AllocateBufferError>> {
|
||||
let buffer_data = Self::to_buffer_data(data);
|
||||
Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
Self::buffer_create_info(),
|
||||
Self::allocation_create_info(),
|
||||
[buffer_data],
|
||||
)
|
||||
}
|
||||
|
||||
fn update_buffer(
|
||||
buffer: &Subbuffer<[Self::BufferData]>,
|
||||
data: &T,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let buffer_data = Self::to_buffer_data(data);
|
||||
let mut write_guard = buffer.write()?;
|
||||
write_guard[0] = buffer_data;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsUniformBuffer<T>: AsBindableBuffer<T> {
|
||||
fn create_uniform_buffer(
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
data: &T,
|
||||
) -> Result<Subbuffer<[Self::BufferData]>, Validated<AllocateBufferError>> {
|
||||
Self::create_buffer(memory_allocator, data)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsVertexBuffer<T>: AsBindableBuffer<T> {
|
||||
fn create_vertex_buffer(
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
vertices: &[T],
|
||||
) -> Result<Subbuffer<[Self::BufferData]>, Validated<AllocateBufferError>> {
|
||||
let buffer_data: Vec<Self::BufferData> =
|
||||
vertices.iter().map(|v| Self::to_buffer_data(v)).collect();
|
||||
|
||||
Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
Self::buffer_create_info(),
|
||||
Self::allocation_create_info(),
|
||||
buffer_data,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsIndexBuffer<T>: AsBindableBuffer<T> {
|
||||
fn create_index_buffer(
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
indices: &[T],
|
||||
) -> Result<Subbuffer<[Self::BufferData]>, Validated<AllocateBufferError>> {
|
||||
let buffer_data: Vec<Self::BufferData> =
|
||||
indices.iter().map(|i| Self::to_buffer_data(i)).collect();
|
||||
|
||||
Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
Self::buffer_create_info(),
|
||||
Self::allocation_create_info(),
|
||||
buffer_data,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ use vulkano::{
|
|||
|
||||
use crate::core::{input::InputManager, timer::Timer};
|
||||
|
||||
use super::mvp::Mvp;
|
||||
use super::{AsUniformBuffer, mvp::Mvp};
|
||||
|
||||
// See docs/OPENGL_VULKAN_DIFF.md
|
||||
const OPENGL_TO_VULKAN_Y_AXIS_FLIP: Mat4 = Mat4 {
|
||||
|
@ -112,11 +112,12 @@ impl Camera3D {
|
|||
Vec3::Y,
|
||||
);
|
||||
|
||||
Mvp {
|
||||
let mvp = Mvp {
|
||||
model: OPENGL_TO_VULKAN_Y_AXIS_FLIP.to_cols_array_2d(),
|
||||
view: view_matrix.to_cols_array_2d(),
|
||||
projection: self.projection.to_cols_array_2d(),
|
||||
}
|
||||
.into_buffer(memory_allocator)
|
||||
};
|
||||
|
||||
Mvp::create_uniform_buffer(memory_allocator, &mvp)
|
||||
}
|
||||
}
|
||||
|
|
110
src/core/render/primitives/command.rs
Normal file
110
src/core/render/primitives/command.rs
Normal file
|
@ -0,0 +1,110 @@
|
|||
use std::{error::Error, sync::Arc};
|
||||
|
||||
use vulkano::{
|
||||
command_buffer::{
|
||||
AutoCommandBufferBuilder, PrimaryAutoCommandBuffer, RenderPassBeginInfo, SubpassBeginInfo,
|
||||
SubpassEndInfo,
|
||||
},
|
||||
descriptor_set::DescriptorSet,
|
||||
pipeline::{GraphicsPipeline, Pipeline},
|
||||
render_pass::{Framebuffer, RenderPass},
|
||||
};
|
||||
|
||||
pub trait AsRecordable<T> {
|
||||
fn record_render_commands(
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
data: &T,
|
||||
pipeline: &Arc<GraphicsPipeline>,
|
||||
descriptor_sets: &[Arc<DescriptorSet>],
|
||||
) -> Result<(), Box<dyn Error>>;
|
||||
}
|
||||
|
||||
pub trait AsDrawable<T> {
|
||||
type VertexBuffer;
|
||||
type IndexBuffer;
|
||||
|
||||
fn vertex_buffer(data: &T) -> &Self::VertexBuffer;
|
||||
|
||||
fn index_buffer(_data: &T) -> Option<&Self::IndexBuffer> {
|
||||
None
|
||||
}
|
||||
|
||||
fn vertex_count(data: &T) -> u32;
|
||||
|
||||
fn index_count(_data: &T) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn instance_count(_data: &T) -> u32 {
|
||||
1
|
||||
}
|
||||
|
||||
fn first_vertex(_data: &T) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn first_index(_data: &T) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
fn first_instance(_data: &T) -> u32 {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsRenderPassRecordable<T> {
|
||||
fn begin_render_pass(
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
_render_pass: &Arc<RenderPass>,
|
||||
framebuffer: &Arc<Framebuffer>,
|
||||
clear_values: Vec<Option<vulkano::format::ClearValue>>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
builder.begin_render_pass(
|
||||
RenderPassBeginInfo {
|
||||
clear_values,
|
||||
..RenderPassBeginInfo::framebuffer(framebuffer.clone())
|
||||
},
|
||||
SubpassBeginInfo {
|
||||
contents: vulkano::command_buffer::SubpassContents::Inline,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn end_render_pass(
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
builder.end_render_pass(SubpassEndInfo::default())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn record_render_pass_commands(
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
data: &T,
|
||||
) -> Result<(), Box<dyn Error>>;
|
||||
}
|
||||
|
||||
pub trait AsRenderableObject<T>: AsRecordable<T> + AsDrawable<T> {
|
||||
fn record_complete_render(
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
data: &T,
|
||||
pipeline: &Arc<GraphicsPipeline>,
|
||||
descriptor_sets: &[Arc<DescriptorSet>],
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
builder.bind_pipeline_graphics(pipeline.clone())?;
|
||||
|
||||
if !descriptor_sets.is_empty() {
|
||||
builder.bind_descriptor_sets(
|
||||
vulkano::pipeline::PipelineBindPoint::Graphics,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
descriptor_sets.iter().cloned().collect::<Vec<_>>(),
|
||||
)?;
|
||||
}
|
||||
|
||||
Self::record_render_commands(builder, data, pipeline, descriptor_sets)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -14,6 +14,13 @@ pub mod mvp;
|
|||
pub mod transform;
|
||||
pub mod vertex;
|
||||
|
||||
pub mod buffer;
|
||||
pub mod command;
|
||||
pub mod resource;
|
||||
|
||||
pub use buffer::{AsBindableBuffer, AsIndexBuffer, AsUniformBuffer, AsVertexBuffer};
|
||||
pub use command::{AsDrawable, AsRecordable};
|
||||
|
||||
pub trait AsBindableDescriptorSet<T> {
|
||||
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding>;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeMap;
|
|||
use std::sync::Arc;
|
||||
|
||||
use vulkano::buffer::{
|
||||
AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
||||
AllocateBufferError, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
||||
};
|
||||
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
||||
use vulkano::descriptor_set::layout::{
|
||||
|
@ -13,7 +13,7 @@ use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, Standar
|
|||
use vulkano::shader::ShaderStages;
|
||||
use vulkano::{Validated, VulkanError};
|
||||
|
||||
use crate::core::render::primitives::AsBindableDescriptorSet;
|
||||
use crate::core::render::primitives::{AsBindableBuffer, AsBindableDescriptorSet, AsUniformBuffer};
|
||||
|
||||
#[derive(BufferContents, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
|
@ -28,22 +28,35 @@ impl Mvp {
|
|||
self,
|
||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
) -> Result<Subbuffer<[Mvp]>, Validated<AllocateBufferError>> {
|
||||
Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::UNIFORM_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
},
|
||||
[self],
|
||||
)
|
||||
Self::create_uniform_buffer(memory_allocator, &self)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsBindableBuffer<Mvp> for Mvp {
|
||||
type BufferData = Mvp;
|
||||
|
||||
fn buffer_create_info() -> BufferCreateInfo {
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::UNIFORM_BUFFER,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn allocation_create_info() -> AllocationCreateInfo {
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer_data(data: &Mvp) -> Self::BufferData {
|
||||
*data
|
||||
}
|
||||
}
|
||||
|
||||
impl AsUniformBuffer<Mvp> for Mvp {}
|
||||
|
||||
impl AsBindableDescriptorSet<Subbuffer<[Mvp]>> for Mvp {
|
||||
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding> {
|
||||
BTreeMap::<u32, DescriptorSetLayoutBinding>::from_iter([(
|
||||
|
|
208
src/core/render/primitives/resource.rs
Normal file
208
src/core/render/primitives/resource.rs
Normal file
|
@ -0,0 +1,208 @@
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
error::Error,
|
||||
fmt::{self, Debug, Display},
|
||||
hash::Hash,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ResourceLoadError {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl Display for ResourceLoadError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Resource load error: {}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ResourceLoadError {}
|
||||
|
||||
impl ResourceLoadError {
|
||||
pub fn new(message: impl Into<String>) -> Self {
|
||||
Self {
|
||||
message: message.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
/// Type d'erreur lors du chargement
|
||||
type LoadError: Error;
|
||||
|
||||
/// Charge une ressource avec l'handle donné
|
||||
fn load(&mut self, handle: THandle, resource: TResource) -> Result<(), Self::LoadError>;
|
||||
|
||||
/// Récupère une ressource par son handle
|
||||
fn get(&self, handle: &THandle) -> Option<&TResource>;
|
||||
|
||||
/// Récupère une ressource mutable par son handle
|
||||
fn get_mut(&mut self, handle: &THandle) -> Option<&mut TResource>;
|
||||
|
||||
/// Supprime une ressource
|
||||
fn unload(&mut self, handle: &THandle) -> Option<TResource>;
|
||||
|
||||
/// Vérifie si une ressource est chargée
|
||||
fn is_loaded(&self, handle: &THandle) -> bool;
|
||||
|
||||
/// Retourne tous les handles chargés
|
||||
fn loaded_handles(&self) -> Vec<THandle>;
|
||||
|
||||
/// Nettoie toutes les ressources
|
||||
fn clear(&mut self);
|
||||
}
|
||||
|
||||
/// Implémentation basique d'un gestionnaire de ressources
|
||||
pub struct BasicResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
resources: HashMap<THandle, TResource>,
|
||||
}
|
||||
|
||||
impl<THandle, TResource> BasicResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
resources: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
resources: HashMap::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<THandle, TResource> Default for BasicResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<THandle, TResource> AsResourceManager<THandle, TResource>
|
||||
for BasicResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
type LoadError = ResourceLoadError;
|
||||
|
||||
fn load(&mut self, handle: THandle, resource: TResource) -> Result<(), Self::LoadError> {
|
||||
self.resources.insert(handle, resource);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get(&self, handle: &THandle) -> Option<&TResource> {
|
||||
self.resources.get(handle)
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, handle: &THandle) -> Option<&mut TResource> {
|
||||
self.resources.get_mut(handle)
|
||||
}
|
||||
|
||||
fn unload(&mut self, handle: &THandle) -> Option<TResource> {
|
||||
self.resources.remove(handle)
|
||||
}
|
||||
|
||||
fn is_loaded(&self, handle: &THandle) -> bool {
|
||||
self.resources.contains_key(handle)
|
||||
}
|
||||
|
||||
fn loaded_handles(&self) -> Vec<THandle> {
|
||||
self.resources.keys().cloned().collect()
|
||||
}
|
||||
|
||||
fn clear(&mut self) {
|
||||
self.resources.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ThreadSafeResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
resources: Arc<std::sync::RwLock<HashMap<THandle, Arc<TResource>>>>,
|
||||
}
|
||||
|
||||
impl<THandle, TResource> ThreadSafeResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
resources: Arc::new(std::sync::RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(&self, handle: THandle, resource: TResource) -> Result<(), ResourceLoadError> {
|
||||
let mut resources = self
|
||||
.resources
|
||||
.write()
|
||||
.map_err(|_| ResourceLoadError::new("Failed to acquire write lock"))?;
|
||||
resources.insert(handle, Arc::new(resource));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get(&self, handle: &THandle) -> Option<Arc<TResource>> {
|
||||
let resources = self.resources.read().ok()?;
|
||||
resources.get(handle).cloned()
|
||||
}
|
||||
|
||||
pub fn unload(&self, handle: &THandle) -> Option<Arc<TResource>> {
|
||||
let mut resources = self.resources.write().ok()?;
|
||||
resources.remove(handle)
|
||||
}
|
||||
|
||||
pub fn is_loaded(&self, handle: &THandle) -> bool {
|
||||
if let Ok(resources) = self.resources.read() {
|
||||
resources.contains_key(handle)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn loaded_handles(&self) -> Vec<THandle> {
|
||||
if let Ok(resources) = self.resources.read() {
|
||||
resources.keys().cloned().collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
if let Ok(mut resources) = self.resources.write() {
|
||||
resources.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<THandle, TResource> Clone for ThreadSafeResourceManager<THandle, TResource>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
resources: Arc::clone(&self.resources),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AsAsyncLoadable<THandle>
|
||||
where
|
||||
THandle: Clone + Eq + Hash + Debug + Send + Sync,
|
||||
{
|
||||
type Resource: Send + Sync;
|
||||
type LoadError: Error + Send + Sync;
|
||||
|
||||
async fn load_async(handle: THandle) -> Result<Self::Resource, Self::LoadError>;
|
||||
}
|
|
@ -3,20 +3,20 @@ use std::sync::Arc;
|
|||
use glam::{Mat4, Quat, Vec3};
|
||||
use vulkano::{
|
||||
Validated,
|
||||
buffer::{
|
||||
AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
||||
},
|
||||
buffer::{AllocateBufferError, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer},
|
||||
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
||||
pipeline::graphics::vertex_input::Vertex,
|
||||
};
|
||||
|
||||
use crate::core::render::primitives::{AsBindableBuffer, AsVertexBuffer};
|
||||
|
||||
pub struct Transform {
|
||||
pub position: Vec3,
|
||||
pub rotation: Quat,
|
||||
pub scale: Vec3,
|
||||
}
|
||||
|
||||
#[derive(BufferContents, Vertex)]
|
||||
#[derive(BufferContents, Vertex, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct TransformRaw {
|
||||
#[format(R32G32B32A32_SFLOAT)]
|
||||
|
@ -59,23 +59,37 @@ impl Transform {
|
|||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||
transforms: &[Transform],
|
||||
) -> Result<Subbuffer<[TransformRaw]>, Validated<AllocateBufferError>> {
|
||||
let transform_raws: Vec<TransformRaw> =
|
||||
transforms.iter().map(|t| t.to_raw_tranform()).collect();
|
||||
|
||||
let buffer = Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::VERTEX_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
},
|
||||
transform_raws,
|
||||
)?;
|
||||
|
||||
Ok(buffer)
|
||||
TransformRaw::create_vertex_buffer(
|
||||
memory_allocator,
|
||||
&transforms
|
||||
.iter()
|
||||
.map(|t| t.to_raw_tranform())
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsBindableBuffer<TransformRaw> for TransformRaw {
|
||||
type BufferData = TransformRaw;
|
||||
|
||||
fn buffer_create_info() -> BufferCreateInfo {
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::VERTEX_BUFFER,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn allocation_create_info() -> AllocationCreateInfo {
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer_data(data: &TransformRaw) -> Self::BufferData {
|
||||
*data
|
||||
}
|
||||
}
|
||||
|
||||
impl AsVertexBuffer<TransformRaw> for TransformRaw {}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use vulkano::buffer::BufferContents;
|
||||
use vulkano::buffer::{BufferCreateInfo, BufferUsage};
|
||||
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter};
|
||||
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
||||
|
||||
#[derive(BufferContents, Vertex)]
|
||||
use crate::core::render::primitives::{AsBindableBuffer, AsIndexBuffer, AsVertexBuffer};
|
||||
|
||||
#[derive(BufferContents, Vertex, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Vertex2D {
|
||||
#[format(R32G32_SFLOAT)]
|
||||
|
@ -11,7 +15,7 @@ pub struct Vertex2D {
|
|||
pub uv: [f32; 2],
|
||||
}
|
||||
|
||||
#[derive(BufferContents, Vertex)]
|
||||
#[derive(BufferContents, Vertex, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct Vertex3D {
|
||||
#[format(R32G32B32_SFLOAT)]
|
||||
|
@ -20,3 +24,78 @@ pub struct Vertex3D {
|
|||
#[format(R32G32_SFLOAT)]
|
||||
pub uv: [f32; 2],
|
||||
}
|
||||
|
||||
impl AsBindableBuffer<Vertex2D> for Vertex2D {
|
||||
type BufferData = Vertex2D;
|
||||
|
||||
fn buffer_create_info() -> BufferCreateInfo {
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::VERTEX_BUFFER,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn allocation_create_info() -> AllocationCreateInfo {
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer_data(data: &Vertex2D) -> Self::BufferData {
|
||||
*data
|
||||
}
|
||||
}
|
||||
|
||||
impl AsVertexBuffer<Vertex2D> for Vertex2D {}
|
||||
|
||||
impl AsBindableBuffer<Vertex3D> for Vertex3D {
|
||||
type BufferData = Vertex3D;
|
||||
|
||||
fn buffer_create_info() -> BufferCreateInfo {
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::VERTEX_BUFFER,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn allocation_create_info() -> AllocationCreateInfo {
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer_data(data: &Vertex3D) -> Self::BufferData {
|
||||
*data
|
||||
}
|
||||
}
|
||||
|
||||
impl AsVertexBuffer<Vertex3D> for Vertex3D {}
|
||||
|
||||
impl AsBindableBuffer<u32> for u32 {
|
||||
type BufferData = u32;
|
||||
|
||||
fn buffer_create_info() -> BufferCreateInfo {
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::INDEX_BUFFER,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn allocation_create_info() -> AllocationCreateInfo {
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn to_buffer_data(data: &u32) -> Self::BufferData {
|
||||
*data
|
||||
}
|
||||
}
|
||||
|
||||
impl AsIndexBuffer<u32> for u32 {}
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
use std::{collections::BTreeMap, error::Error, sync::Arc};
|
||||
use std::{error::Error, sync::Arc};
|
||||
|
||||
use vulkano::{
|
||||
buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer},
|
||||
buffer::Subbuffer,
|
||||
command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer},
|
||||
descriptor_set::{
|
||||
DescriptorSet, WriteDescriptorSet,
|
||||
allocator::StandardDescriptorSetAllocator,
|
||||
layout::{DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType},
|
||||
DescriptorSet, allocator::StandardDescriptorSetAllocator,
|
||||
layout::DescriptorSetLayoutCreateInfo,
|
||||
},
|
||||
device::Device,
|
||||
format::Format,
|
||||
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
||||
memory::allocator::StandardMemoryAllocator,
|
||||
pipeline::{
|
||||
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
|
||||
PipelineShaderStageCreateInfo,
|
||||
|
@ -27,11 +26,13 @@ use vulkano::{
|
|||
},
|
||||
layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags},
|
||||
},
|
||||
shader::ShaderStages,
|
||||
};
|
||||
|
||||
use crate::core::render::{
|
||||
primitives::{AsBindableDescriptorSet, mvp::Mvp, transform::TransformRaw, vertex::Vertex3D},
|
||||
primitives::{
|
||||
AsBindableDescriptorSet, AsDrawable, AsIndexBuffer, AsRecordable, AsVertexBuffer, mvp::Mvp,
|
||||
transform::TransformRaw, vertex::Vertex3D,
|
||||
},
|
||||
texture::Texture,
|
||||
};
|
||||
|
||||
|
@ -80,6 +81,14 @@ pub struct Square {
|
|||
pipeline: Arc<GraphicsPipeline>,
|
||||
}
|
||||
|
||||
/// Structure pour encapsuler les données de rendu du Square
|
||||
pub struct SquareRenderData<'a> {
|
||||
pub square: &'a Square,
|
||||
pub mvp_uniform: &'a Subbuffer<[Mvp]>,
|
||||
pub transform_uniform: &'a Subbuffer<[TransformRaw]>,
|
||||
pub texture: &'a Texture,
|
||||
}
|
||||
|
||||
impl Square {
|
||||
pub fn new(
|
||||
device: &Arc<Device>,
|
||||
|
@ -87,32 +96,9 @@ impl Square {
|
|||
swapchain_format: Format,
|
||||
depth_format: Format,
|
||||
) -> Result<Self, Box<dyn Error>> {
|
||||
let vertex_buffer = Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::VERTEX_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
},
|
||||
Vec::from_iter(VERTICES),
|
||||
)?;
|
||||
let index_buffer = Buffer::from_iter(
|
||||
memory_allocator.clone(),
|
||||
BufferCreateInfo {
|
||||
usage: BufferUsage::INDEX_BUFFER,
|
||||
..Default::default()
|
||||
},
|
||||
AllocationCreateInfo {
|
||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
||||
..Default::default()
|
||||
},
|
||||
Vec::from_iter(INDICES),
|
||||
)?;
|
||||
let vertex_buffer = Vertex3D::create_vertex_buffer(memory_allocator, &VERTICES)?;
|
||||
|
||||
let index_buffer = u32::create_index_buffer(memory_allocator, &INDICES)?;
|
||||
|
||||
let vs = shaders::vs::load(device.clone())?
|
||||
.entry_point("main")
|
||||
|
@ -197,6 +183,13 @@ impl Square {
|
|||
transform_uniform: &Subbuffer<[TransformRaw]>,
|
||||
texture: &Texture,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let render_data = SquareRenderData {
|
||||
square: self,
|
||||
mvp_uniform,
|
||||
transform_uniform,
|
||||
texture,
|
||||
};
|
||||
|
||||
let layouts = self.pipeline.layout().set_layouts();
|
||||
|
||||
let uniform_descriptor_set =
|
||||
|
@ -205,25 +198,86 @@ impl Square {
|
|||
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(
|
||||
PipelineBindPoint::Graphics,
|
||||
self.pipeline.layout().clone(),
|
||||
0,
|
||||
vec![uniform_descriptor_set, texture_descriptor_set],
|
||||
// Utiliser les nouveaux traits pour le rendu
|
||||
Self::record_render_commands(
|
||||
command_buffer,
|
||||
&render_data,
|
||||
&self.pipeline,
|
||||
&[uniform_descriptor_set, texture_descriptor_set],
|
||||
)?;
|
||||
command_buffer
|
||||
.bind_vertex_buffers(0, (self.vertex_buffer.clone(), transform_uniform.clone()))?;
|
||||
command_buffer.bind_index_buffer(self.index_buffer.clone())?;
|
||||
|
||||
unsafe {
|
||||
command_buffer.draw_indexed(
|
||||
INDICES.len() as u32,
|
||||
transform_uniform.len() as u32,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Implémentation des nouveaux traits pour Square
|
||||
impl<'a> AsDrawable<SquareRenderData<'a>> for Square {
|
||||
type VertexBuffer = Subbuffer<[Vertex3D]>;
|
||||
type IndexBuffer = Subbuffer<[u32]>;
|
||||
|
||||
fn vertex_buffer(data: &SquareRenderData<'a>) -> &'a Self::VertexBuffer {
|
||||
&data.square.vertex_buffer
|
||||
}
|
||||
|
||||
fn index_buffer(data: &SquareRenderData<'a>) -> Option<&'a Self::IndexBuffer> {
|
||||
Some(&data.square.index_buffer)
|
||||
}
|
||||
|
||||
fn vertex_count(_data: &SquareRenderData<'a>) -> u32 {
|
||||
VERTICES.len() as u32
|
||||
}
|
||||
|
||||
fn index_count(_data: &SquareRenderData<'a>) -> u32 {
|
||||
INDICES.len() as u32
|
||||
}
|
||||
|
||||
fn instance_count(data: &SquareRenderData<'a>) -> u32 {
|
||||
data.transform_uniform.len() as u32
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> AsRecordable<SquareRenderData<'a>> for Square {
|
||||
fn record_render_commands(
|
||||
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
|
||||
data: &SquareRenderData<'a>,
|
||||
pipeline: &Arc<GraphicsPipeline>,
|
||||
descriptor_sets: &[Arc<DescriptorSet>],
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
// Bind pipeline
|
||||
builder.bind_pipeline_graphics(pipeline.clone())?;
|
||||
|
||||
// Bind descriptor sets
|
||||
builder.bind_descriptor_sets(
|
||||
PipelineBindPoint::Graphics,
|
||||
pipeline.layout().clone(),
|
||||
0,
|
||||
descriptor_sets.iter().cloned().collect::<Vec<_>>(),
|
||||
)?;
|
||||
|
||||
// Bind buffers
|
||||
builder.bind_vertex_buffers(
|
||||
0,
|
||||
(
|
||||
Self::vertex_buffer(data).clone(),
|
||||
data.transform_uniform.clone(),
|
||||
),
|
||||
)?;
|
||||
|
||||
if let Some(index_buffer) = Self::index_buffer(data) {
|
||||
builder.bind_index_buffer(index_buffer.clone())?;
|
||||
unsafe {
|
||||
builder.draw_indexed(
|
||||
Self::index_count(data),
|
||||
Self::instance_count(data),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
unsafe {
|
||||
builder.draw(Self::vertex_count(data), Self::instance_count(data), 0, 0)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue