use crate::backend::{BackendBuffer, BackendBufferOps};
use crate::error::Result;
#[allow(private_interfaces)]
pub trait GpuBuf {
#[doc(hidden)]
fn raw(&self) -> &BackendBuffer;
}
pub struct Buffer<T: bytemuck::Pod> {
pub(crate) inner: BackendBuffer,
pub(crate) len: usize,
pub(crate) _marker: std::marker::PhantomData<T>,
}
impl<T: bytemuck::Pod> Buffer<T> {
pub const fn len(&self) -> usize {
self.len
}
pub const fn is_empty(&self) -> bool {
self.len == 0
}
pub const fn byte_size(&self) -> u64 {
match self.len.checked_mul(std::mem::size_of::<T>()) {
Some(s) => s as u64,
None => u64::MAX,
}
}
pub fn download(&self) -> Result<Vec<T>> {
let bytes = self.inner.read_back()?;
let elements = bytemuck::cast_slice(&bytes).to_vec();
Ok(elements)
}
}
#[allow(private_interfaces)]
impl<T: bytemuck::Pod> GpuBuf for Buffer<T> {
fn raw(&self) -> &BackendBuffer {
&self.inner
}
}
impl<T: bytemuck::Pod> std::fmt::Debug for Buffer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Buffer")
.field("len", &self.len)
.field("byte_size", &self.byte_size())
.field("type", &std::any::type_name::<T>())
.finish_non_exhaustive()
}
}