cyborg/src/mesh/group.rs

87 lines
2.5 KiB
Rust

//! Fixed-room pooling of mesh data.
use super::*;
/// A mesh that has been allocated in a [MeshGroup].
pub struct MeshAlloc {
pub attributes: SmallVec<[(usize, AttrId); MAX_MESH_INLINE_ATTRIBUTES]>,
}
/// A set of GPU-side vertex attribute pools and index pools.
pub struct MeshGroup {
id: usize,
pools: HashMap<AttrId, AttrPool>,
meshes: Slab<MeshAlloc>,
}
impl MeshGroup {
pub fn new(id: usize) -> Self {
Self {
id,
pools: Default::default(),
meshes: Default::default(),
}
}
/// Registers an [AttrId], and creates the [AttrPool] for it.
///
/// Fails if the [AttrId] has already been registered.
///
/// `pool_size` defines the size of the new pool. Once an attribute pool
/// has been created, it cannot be resized, so if it runs out of room for
/// new attributes, a new [MeshGroup] must be created.
pub fn add_attribute(
&mut self,
id: AttrId,
layout: AttrLayout,
pool_size: usize,
) -> Result<(), PoolError> {
if self.pools.contains_key(&id) {
return Err(PoolError::AttrTaken);
}
let pool = AttrPool::new(self.id, id, layout, pool_size)?;
self.pools.insert(id, pool);
Ok(())
}
/// Checks to see if a mesh can be loaded within this group.
pub fn can_load(&self, buf: &MeshBuffer) -> Result<(), PoolError> {
for attr in buf.attributes.iter() {
match self.pools.get(&attr.id) {
None => return Err(PoolError::AttrUnregistered),
Some(pool) => pool.can_load(attr)?,
};
}
Ok(())
}
/// Tries to load a [MeshBuffer] into this pool. Returns a [MeshHandle].
pub fn load(&mut self, buf: &MeshBuffer) -> Result<(MeshHandle, Vec<CopyInfo>), PoolError> {
self.can_load(&buf)?;
let mut allocs = SmallVec::with_capacity(buf.attributes.len());
let mut copies = Vec::new();
for attr in buf.attributes.iter() {
match self.pools.get_mut(&attr.id) {
None => unreachable!(),
Some(pool) => {
let (alloc, copy) = pool.load(attr)?;
allocs.push((alloc, attr.id));
copies.push(copy);
}
}
}
let mesh = MeshAlloc { attributes: allocs };
let sub = self.meshes.insert(mesh);
let group = self.id;
let handle = MeshHandle { group, sub };
Ok((handle, copies))
}
}