use {
crate::{UniformValue, context::Context, state::State, types, value::StorageValue},
std::marker::PhantomData,
};
struct Data {
buf: wgpu::Buffer,
size: usize,
}
impl Data {
fn new(state: &State, contents: &[u8], usage: wgpu::BufferUsages) -> Self {
use wgpu::util::{self, DeviceExt};
let buf = {
let desc = util::BufferInitDescriptor {
label: None,
contents,
usage,
};
state.device().create_buffer_init(&desc)
};
let size = contents.len();
Self { buf, size }
}
fn update(&self, state: &State, contents: &[u8]) {
assert_eq!(
contents.len(),
self.size,
"cannot update buffer of size {} with value of size {}",
self.size,
contents.len(),
);
state.queue().write_buffer(&self.buf, 0, contents);
}
}
pub type RwStorage<V> = Storage<V, types::Mutable>;
pub struct Storage<V, M = types::Immutable>
where
V: ?Sized,
{
data: Data,
ty: PhantomData<V>,
mu: PhantomData<M>,
}
impl<V, M> Storage<V, M>
where
V: ?Sized,
{
#[inline]
pub(crate) fn new(cx: &Context, val: &V) -> Self
where
V: StorageValue,
{
let data = Data::new(
cx.state(),
val.storage_value(),
wgpu::BufferUsages::STORAGE
| wgpu::BufferUsages::COPY_SRC
| wgpu::BufferUsages::COPY_DST,
);
Self {
data,
ty: PhantomData,
mu: PhantomData,
}
}
#[inline]
pub fn update(&self, cx: &Context, val: &V)
where
V: StorageValue,
{
self.data.update(cx.state(), val.storage_value());
}
#[inline]
pub fn size(&self) -> usize {
self.data.size
}
pub(crate) fn buffer(&self) -> &wgpu::Buffer {
&self.data.buf
}
}
impl<V> Storage<V>
where
V: ?Sized,
{
pub fn rw(self) -> RwStorage<V> {
RwStorage {
data: self.data,
ty: PhantomData,
mu: PhantomData,
}
}
}
pub struct Uniform<V> {
data: Data,
ty: PhantomData<V>,
}
impl<V> Uniform<V> {
#[inline]
pub(crate) fn new(cx: &Context, val: &V) -> Self
where
V: UniformValue,
{
let data = Data::new(
cx.state(),
val.uniform_value(),
wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
);
Self {
data,
ty: PhantomData,
}
}
#[inline]
pub fn update(&self, cx: &Context, val: &V)
where
V: UniformValue,
{
self.data.update(cx.state(), val.uniform_value());
}
#[inline]
pub fn size(&self) -> usize {
self.data.size
}
pub(crate) fn buffer(&self) -> &wgpu::Buffer {
&self.data.buf
}
}