cyborg/src/mesh/group.rs

93 lines
2.8 KiB
Rust

//! Fixed-room pooling of mesh data.
use super::*;
use std::sync::Arc;
/// 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,
attr_store: Arc<AttrStore>,
pools: HashMap<AttrId, AttrPool>,
meshes: Slab<MeshAlloc>,
}
impl MeshGroup {
pub fn new(id: usize, attr_store: Arc<AttrStore>) -> Self {
Self {
id,
attr_store,
pools: Default::default(),
meshes: Default::default(),
}
}
/// 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 => {
match self.attr_store.get_info(&attr.id) {
Some(_) => {} // new pools of valid attrs can be made
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() {
let id = &attr.id;
let pool = match self.pools.get_mut(id) {
Some(pool) => pool,
None => {
let info = match self.attr_store.get_info(id) {
Some(info) => *info,
None => return Err(PoolError::AttrUnregistered),
};
let new_pool = AttrPool::new(self.id, *id, info)?;
self.pools.insert(*id, new_pool);
self.pools.get_mut(id).unwrap()
}
};
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))
}
/// Gets a [MeshHandle's][MeshHandle] [MeshAlloc].
pub fn get_alloc(&self, handle: &MeshHandle) -> Option<&MeshAlloc> {
if handle.group != self.id {
None
} else {
self.meshes.get(handle.sub)
}
}
}