87 lines
2.5 KiB
Rust
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))
|
|
}
|
|
}
|