use std::borrow::Borrow;
use std::mem::MaybeUninit;
use web_glitz::buffer::UsageHint;
use web_glitz::pipeline::graphics::{IndexBuffer, IndexBufferView, IndexFormat};
use web_glitz::runtime::RenderingContext;
use crate::util::new_capacity_amortized;
pub struct IndexBufferVec<Rc, T> {
context: Rc,
len: usize,
buffer: IndexBuffer<MaybeUninit<T>>,
}
impl<Rc, T> IndexBufferVec<Rc, T>
where
Rc: RenderingContext,
T: IndexFormat + 'static,
{
pub fn new(context: Rc, usage: UsageHint) -> Self {
let buffer = context.create_index_buffer_uninit(0, usage);
IndexBufferVec {
context,
len: 0,
buffer,
}
}
pub fn with_capacity(context: Rc, usage: UsageHint, capacity: usize) -> Self {
let buffer = context.create_index_buffer_uninit(capacity, usage);
IndexBufferVec {
context,
len: 0,
buffer,
}
}
pub fn update<D>(&mut self, data: D) -> bool
where
D: Borrow<[T]> + Send + Sync + 'static,
{
let IndexBufferVec {
context,
len,
buffer,
} = self;
*len = data.borrow().len();
let current_capacity = buffer.len();
let reallocated = if let Some(new_capacity) = new_capacity_amortized(current_capacity, *len) {
*buffer = context
.create_index_buffer_uninit(new_capacity, buffer.usage_hint())
.into();
true
} else {
false
};
let view = buffer.get(0..*len).unwrap();
let upload_task = unsafe {
view.assume_init().upload_command(data)
};
context.submit(upload_task);
reallocated
}
pub fn capacity(&self) -> usize {
self.buffer.len()
}
pub fn as_buffer_view(&self) -> IndexBufferView<T>
where
T: Copy + 'static,
{
let IndexBufferVec { len, buffer, .. } = self;
unsafe { buffer.get(0..*len).unwrap().assume_init() }
}
}