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 crate::core::{input::InputManager, timer::Timer};
|
||||||
|
|
||||||
use super::mvp::Mvp;
|
use super::{AsUniformBuffer, mvp::Mvp};
|
||||||
|
|
||||||
// See docs/OPENGL_VULKAN_DIFF.md
|
// See docs/OPENGL_VULKAN_DIFF.md
|
||||||
const OPENGL_TO_VULKAN_Y_AXIS_FLIP: Mat4 = Mat4 {
|
const OPENGL_TO_VULKAN_Y_AXIS_FLIP: Mat4 = Mat4 {
|
||||||
|
@ -112,11 +112,12 @@ impl Camera3D {
|
||||||
Vec3::Y,
|
Vec3::Y,
|
||||||
);
|
);
|
||||||
|
|
||||||
Mvp {
|
let mvp = Mvp {
|
||||||
model: OPENGL_TO_VULKAN_Y_AXIS_FLIP.to_cols_array_2d(),
|
model: OPENGL_TO_VULKAN_Y_AXIS_FLIP.to_cols_array_2d(),
|
||||||
view: view_matrix.to_cols_array_2d(),
|
view: view_matrix.to_cols_array_2d(),
|
||||||
projection: self.projection.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 transform;
|
||||||
pub mod vertex;
|
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> {
|
pub trait AsBindableDescriptorSet<T> {
|
||||||
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding>;
|
fn as_descriptor_set_layout_bindings() -> BTreeMap<u32, DescriptorSetLayoutBinding>;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use vulkano::buffer::{
|
use vulkano::buffer::{
|
||||||
AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
AllocateBufferError, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
||||||
};
|
};
|
||||||
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
use vulkano::descriptor_set::allocator::StandardDescriptorSetAllocator;
|
||||||
use vulkano::descriptor_set::layout::{
|
use vulkano::descriptor_set::layout::{
|
||||||
|
@ -13,7 +13,7 @@ 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::AsBindableDescriptorSet;
|
use crate::core::render::primitives::{AsBindableBuffer, AsBindableDescriptorSet, AsUniformBuffer};
|
||||||
|
|
||||||
#[derive(BufferContents, Clone, Copy)]
|
#[derive(BufferContents, Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -28,22 +28,35 @@ impl Mvp {
|
||||||
self,
|
self,
|
||||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||||
) -> Result<Subbuffer<[Mvp]>, Validated<AllocateBufferError>> {
|
) -> Result<Subbuffer<[Mvp]>, Validated<AllocateBufferError>> {
|
||||||
Buffer::from_iter(
|
Self::create_uniform_buffer(memory_allocator, &self)
|
||||||
memory_allocator.clone(),
|
|
||||||
BufferCreateInfo {
|
|
||||||
usage: BufferUsage::UNIFORM_BUFFER,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
AllocationCreateInfo {
|
|
||||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
|
||||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
[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 {
|
impl AsBindableDescriptorSet<Subbuffer<[Mvp]>> 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([(
|
||||||
|
|
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 glam::{Mat4, Quat, Vec3};
|
||||||
use vulkano::{
|
use vulkano::{
|
||||||
Validated,
|
Validated,
|
||||||
buffer::{
|
buffer::{AllocateBufferError, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer},
|
||||||
AllocateBufferError, Buffer, BufferContents, BufferCreateInfo, BufferUsage, Subbuffer,
|
|
||||||
},
|
|
||||||
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
||||||
pipeline::graphics::vertex_input::Vertex,
|
pipeline::graphics::vertex_input::Vertex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::core::render::primitives::{AsBindableBuffer, AsVertexBuffer};
|
||||||
|
|
||||||
pub struct Transform {
|
pub struct Transform {
|
||||||
pub position: Vec3,
|
pub position: Vec3,
|
||||||
pub rotation: Quat,
|
pub rotation: Quat,
|
||||||
pub scale: Vec3,
|
pub scale: Vec3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BufferContents, Vertex)]
|
#[derive(BufferContents, Vertex, Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct TransformRaw {
|
pub struct TransformRaw {
|
||||||
#[format(R32G32B32A32_SFLOAT)]
|
#[format(R32G32B32A32_SFLOAT)]
|
||||||
|
@ -59,23 +59,37 @@ impl Transform {
|
||||||
memory_allocator: &Arc<StandardMemoryAllocator>,
|
memory_allocator: &Arc<StandardMemoryAllocator>,
|
||||||
transforms: &[Transform],
|
transforms: &[Transform],
|
||||||
) -> Result<Subbuffer<[TransformRaw]>, Validated<AllocateBufferError>> {
|
) -> Result<Subbuffer<[TransformRaw]>, Validated<AllocateBufferError>> {
|
||||||
let transform_raws: Vec<TransformRaw> =
|
TransformRaw::create_vertex_buffer(
|
||||||
transforms.iter().map(|t| t.to_raw_tranform()).collect();
|
memory_allocator,
|
||||||
|
&transforms
|
||||||
let buffer = Buffer::from_iter(
|
.iter()
|
||||||
memory_allocator.clone(),
|
.map(|t| t.to_raw_tranform())
|
||||||
BufferCreateInfo {
|
.collect::<Vec<_>>(),
|
||||||
usage: BufferUsage::VERTEX_BUFFER,
|
)
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
AllocationCreateInfo {
|
|
||||||
memory_type_filter: MemoryTypeFilter::PREFER_DEVICE
|
|
||||||
| MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
transform_raws,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(buffer)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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::BufferContents;
|
||||||
|
use vulkano::buffer::{BufferCreateInfo, BufferUsage};
|
||||||
|
use vulkano::memory::allocator::{AllocationCreateInfo, MemoryTypeFilter};
|
||||||
use vulkano::pipeline::graphics::vertex_input::Vertex;
|
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)]
|
#[repr(C)]
|
||||||
pub struct Vertex2D {
|
pub struct Vertex2D {
|
||||||
#[format(R32G32_SFLOAT)]
|
#[format(R32G32_SFLOAT)]
|
||||||
|
@ -11,7 +15,7 @@ pub struct Vertex2D {
|
||||||
pub uv: [f32; 2],
|
pub uv: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(BufferContents, Vertex)]
|
#[derive(BufferContents, Vertex, Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Vertex3D {
|
pub struct Vertex3D {
|
||||||
#[format(R32G32B32_SFLOAT)]
|
#[format(R32G32B32_SFLOAT)]
|
||||||
|
@ -20,3 +24,78 @@ pub struct Vertex3D {
|
||||||
#[format(R32G32_SFLOAT)]
|
#[format(R32G32_SFLOAT)]
|
||||||
pub uv: [f32; 2],
|
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::{
|
use vulkano::{
|
||||||
buffer::{Buffer, BufferCreateInfo, BufferUsage, Subbuffer},
|
buffer::Subbuffer,
|
||||||
command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer},
|
command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer},
|
||||||
descriptor_set::{
|
descriptor_set::{
|
||||||
DescriptorSet, WriteDescriptorSet,
|
DescriptorSet, allocator::StandardDescriptorSetAllocator,
|
||||||
allocator::StandardDescriptorSetAllocator,
|
layout::DescriptorSetLayoutCreateInfo,
|
||||||
layout::{DescriptorSetLayoutBinding, DescriptorSetLayoutCreateInfo, DescriptorType},
|
|
||||||
},
|
},
|
||||||
device::Device,
|
device::Device,
|
||||||
format::Format,
|
format::Format,
|
||||||
memory::allocator::{AllocationCreateInfo, MemoryTypeFilter, StandardMemoryAllocator},
|
memory::allocator::StandardMemoryAllocator,
|
||||||
pipeline::{
|
pipeline::{
|
||||||
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
|
DynamicState, GraphicsPipeline, Pipeline, PipelineBindPoint, PipelineLayout,
|
||||||
PipelineShaderStageCreateInfo,
|
PipelineShaderStageCreateInfo,
|
||||||
|
@ -27,11 +26,13 @@ use vulkano::{
|
||||||
},
|
},
|
||||||
layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags},
|
layout::{PipelineDescriptorSetLayoutCreateInfo, PipelineLayoutCreateFlags},
|
||||||
},
|
},
|
||||||
shader::ShaderStages,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::core::render::{
|
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,
|
texture::Texture,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -80,6 +81,14 @@ pub struct Square {
|
||||||
pipeline: Arc<GraphicsPipeline>,
|
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 {
|
impl Square {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
device: &Arc<Device>,
|
device: &Arc<Device>,
|
||||||
|
@ -87,32 +96,9 @@ impl Square {
|
||||||
swapchain_format: Format,
|
swapchain_format: Format,
|
||||||
depth_format: Format,
|
depth_format: Format,
|
||||||
) -> Result<Self, Box<dyn Error>> {
|
) -> Result<Self, Box<dyn Error>> {
|
||||||
let vertex_buffer = Buffer::from_iter(
|
let vertex_buffer = Vertex3D::create_vertex_buffer(memory_allocator, &VERTICES)?;
|
||||||
memory_allocator.clone(),
|
|
||||||
BufferCreateInfo {
|
let index_buffer = u32::create_index_buffer(memory_allocator, &INDICES)?;
|
||||||
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 vs = shaders::vs::load(device.clone())?
|
let vs = shaders::vs::load(device.clone())?
|
||||||
.entry_point("main")
|
.entry_point("main")
|
||||||
|
@ -197,6 +183,13 @@ impl Square {
|
||||||
transform_uniform: &Subbuffer<[TransformRaw]>,
|
transform_uniform: &Subbuffer<[TransformRaw]>,
|
||||||
texture: &Texture,
|
texture: &Texture,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
|
let render_data = SquareRenderData {
|
||||||
|
square: self,
|
||||||
|
mvp_uniform,
|
||||||
|
transform_uniform,
|
||||||
|
texture,
|
||||||
|
};
|
||||||
|
|
||||||
let layouts = self.pipeline.layout().set_layouts();
|
let layouts = self.pipeline.layout().set_layouts();
|
||||||
|
|
||||||
let uniform_descriptor_set =
|
let uniform_descriptor_set =
|
||||||
|
@ -205,25 +198,86 @@ impl Square {
|
||||||
let texture_descriptor_set =
|
let texture_descriptor_set =
|
||||||
Texture::as_descriptor_set(descriptor_set_allocator, &layouts[1], texture)?;
|
Texture::as_descriptor_set(descriptor_set_allocator, &layouts[1], texture)?;
|
||||||
|
|
||||||
command_buffer.bind_pipeline_graphics(self.pipeline.clone())?;
|
// Utiliser les nouveaux traits pour le rendu
|
||||||
command_buffer.bind_descriptor_sets(
|
Self::record_render_commands(
|
||||||
PipelineBindPoint::Graphics,
|
command_buffer,
|
||||||
self.pipeline.layout().clone(),
|
&render_data,
|
||||||
0,
|
&self.pipeline,
|
||||||
vec![uniform_descriptor_set, texture_descriptor_set],
|
&[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 {
|
Ok(())
|
||||||
command_buffer.draw_indexed(
|
}
|
||||||
INDICES.len() as u32,
|
}
|
||||||
transform_uniform.len() as u32,
|
|
||||||
0,
|
// Implémentation des nouveaux traits pour Square
|
||||||
0,
|
impl<'a> AsDrawable<SquareRenderData<'a>> for Square {
|
||||||
0,
|
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(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue