encase/core/
buffers.rs

1use super::{
2    AlignmentValue, BufferMut, BufferRef, CreateFrom, ReadFrom, Reader, Result, ShaderType,
3    WriteInto, Writer,
4};
5
6/// Storage buffer wrapper facilitating RW operations
7pub struct StorageBuffer<B> {
8    inner: B,
9}
10
11impl<B> StorageBuffer<B> {
12    pub const fn new(buffer: B) -> Self {
13        Self { inner: buffer }
14    }
15
16    pub fn into_inner(self) -> B {
17        self.inner
18    }
19}
20
21impl<B> From<B> for StorageBuffer<B> {
22    fn from(buffer: B) -> Self {
23        Self::new(buffer)
24    }
25}
26
27impl<B> AsRef<B> for StorageBuffer<B> {
28    fn as_ref(&self) -> &B {
29        &self.inner
30    }
31}
32
33impl<B> AsMut<B> for StorageBuffer<B> {
34    fn as_mut(&mut self) -> &mut B {
35        &mut self.inner
36    }
37}
38
39impl<B: BufferMut> StorageBuffer<B> {
40    pub fn write<T>(&mut self, value: &T) -> Result<()>
41    where
42        T: ?Sized + ShaderType + WriteInto,
43    {
44        let mut writer = Writer::new(value, &mut self.inner, 0)?;
45        value.write_into(&mut writer);
46        Ok(())
47    }
48}
49
50impl<B: BufferRef> StorageBuffer<B> {
51    pub fn read<T>(&self, value: &mut T) -> Result<()>
52    where
53        T: ?Sized + ShaderType + ReadFrom,
54    {
55        let mut writer = Reader::new::<T>(&self.inner, 0)?;
56        value.read_from(&mut writer);
57        Ok(())
58    }
59
60    pub fn create<T>(&self) -> Result<T>
61    where
62        T: ShaderType + CreateFrom,
63    {
64        let mut writer = Reader::new::<T>(&self.inner, 0)?;
65        Ok(T::create_from(&mut writer))
66    }
67}
68
69/// Uniform buffer wrapper facilitating RW operations
70pub struct UniformBuffer<B> {
71    inner: StorageBuffer<B>,
72}
73
74impl<B> UniformBuffer<B> {
75    pub const fn new(buffer: B) -> Self {
76        Self {
77            inner: StorageBuffer::new(buffer),
78        }
79    }
80
81    pub fn into_inner(self) -> B {
82        self.inner.inner
83    }
84}
85
86impl<B> From<B> for UniformBuffer<B> {
87    fn from(buffer: B) -> Self {
88        Self::new(buffer)
89    }
90}
91
92impl<B> AsRef<B> for UniformBuffer<B> {
93    fn as_ref(&self) -> &B {
94        &self.inner.inner
95    }
96}
97
98impl<B> AsMut<B> for UniformBuffer<B> {
99    fn as_mut(&mut self) -> &mut B {
100        &mut self.inner.inner
101    }
102}
103
104impl<B: BufferMut> UniformBuffer<B> {
105    pub fn write<T>(&mut self, value: &T) -> Result<()>
106    where
107        T: ?Sized + ShaderType + WriteInto,
108    {
109        T::assert_uniform_compat();
110        self.inner.write(value)
111    }
112}
113
114impl<B: BufferRef> UniformBuffer<B> {
115    pub fn read<T>(&self, value: &mut T) -> Result<()>
116    where
117        T: ?Sized + ShaderType + ReadFrom,
118    {
119        T::assert_uniform_compat();
120        self.inner.read(value)
121    }
122
123    pub fn create<T>(&self) -> Result<T>
124    where
125        T: ShaderType + CreateFrom,
126    {
127        T::assert_uniform_compat();
128        self.inner.create()
129    }
130}
131
132/// Dynamic storage buffer wrapper facilitating RW operations
133pub struct DynamicStorageBuffer<B> {
134    inner: B,
135    alignment: AlignmentValue,
136    offset: usize,
137}
138
139impl<B> DynamicStorageBuffer<B> {
140    /// Creates a new dynamic storage buffer wrapper with an alignment of 256
141    /// (default alignment in the WebGPU spec).
142    pub const fn new(buffer: B) -> Self {
143        Self::new_with_alignment(buffer, 256)
144    }
145
146    /// Creates a new dynamic storage buffer wrapper with a given alignment.
147    /// # Panics
148    ///
149    /// - if `alignment` is not a power of two.
150    /// - if `alignment` is less than 32 (min alignment imposed by the WebGPU spec).
151    pub const fn new_with_alignment(buffer: B, alignment: u64) -> Self {
152        if alignment < 32 {
153            panic!("Alignment must be at least 32!");
154        }
155        Self {
156            inner: buffer,
157            alignment: AlignmentValue::new(alignment),
158            offset: 0,
159        }
160    }
161
162    pub fn set_offset(&mut self, offset: u64) {
163        if !self.alignment.is_aligned(offset) {
164            panic!(
165                "offset of {} bytes is not aligned to alignment of {} bytes",
166                offset,
167                self.alignment.get()
168            );
169        }
170
171        self.offset = offset as usize;
172    }
173
174    pub fn into_inner(self) -> B {
175        self.inner
176    }
177}
178
179impl<B> From<B> for DynamicStorageBuffer<B> {
180    fn from(buffer: B) -> Self {
181        Self::new(buffer)
182    }
183}
184
185impl<B> AsRef<B> for DynamicStorageBuffer<B> {
186    fn as_ref(&self) -> &B {
187        &self.inner
188    }
189}
190
191impl<B> AsMut<B> for DynamicStorageBuffer<B> {
192    fn as_mut(&mut self) -> &mut B {
193        &mut self.inner
194    }
195}
196
197impl<B: BufferMut> DynamicStorageBuffer<B> {
198    pub fn write<T>(&mut self, value: &T) -> Result<u64>
199    where
200        T: ?Sized + ShaderType + WriteInto,
201    {
202        let offset = self.offset;
203
204        let mut writer = Writer::new(value, &mut self.inner, offset)?;
205        value.write_into(&mut writer);
206
207        self.offset += self.alignment.round_up(value.size().get()) as usize;
208
209        Ok(offset as u64)
210    }
211}
212
213impl<B: BufferRef> DynamicStorageBuffer<B> {
214    pub fn read<T>(&mut self, value: &mut T) -> Result<()>
215    where
216        T: ?Sized + ShaderType + ReadFrom,
217    {
218        let mut writer = Reader::new::<T>(&self.inner, self.offset)?;
219        value.read_from(&mut writer);
220
221        self.offset += self.alignment.round_up(value.size().get()) as usize;
222
223        Ok(())
224    }
225
226    pub fn create<T>(&mut self) -> Result<T>
227    where
228        T: ShaderType + CreateFrom,
229    {
230        let mut writer = Reader::new::<T>(&self.inner, self.offset)?;
231        let value = T::create_from(&mut writer);
232
233        self.offset += self.alignment.round_up(value.size().get()) as usize;
234
235        Ok(value)
236    }
237}
238
239/// Dynamic uniform buffer wrapper facilitating RW operations
240pub struct DynamicUniformBuffer<B> {
241    inner: DynamicStorageBuffer<B>,
242}
243
244impl<B> DynamicUniformBuffer<B> {
245    /// Creates a new dynamic uniform buffer wrapper with an alignment of 256
246    /// (default alignment in the WebGPU spec).
247    pub const fn new(buffer: B) -> Self {
248        Self {
249            inner: DynamicStorageBuffer::new(buffer),
250        }
251    }
252
253    /// Creates a new dynamic uniform buffer wrapper with a given alignment.
254    /// # Panics
255    ///
256    /// - if `alignment` is not a power of two.
257    /// - if `alignment` is less than 32 (min alignment imposed by the WebGPU spec).
258    pub const fn new_with_alignment(buffer: B, alignment: u64) -> Self {
259        Self {
260            inner: DynamicStorageBuffer::new_with_alignment(buffer, alignment),
261        }
262    }
263
264    pub fn set_offset(&mut self, offset: u64) {
265        self.inner.set_offset(offset);
266    }
267
268    pub fn into_inner(self) -> B {
269        self.inner.inner
270    }
271}
272
273impl<B> From<B> for DynamicUniformBuffer<B> {
274    fn from(buffer: B) -> Self {
275        Self::new(buffer)
276    }
277}
278
279impl<B> AsRef<B> for DynamicUniformBuffer<B> {
280    fn as_ref(&self) -> &B {
281        &self.inner.inner
282    }
283}
284
285impl<B> AsMut<B> for DynamicUniformBuffer<B> {
286    fn as_mut(&mut self) -> &mut B {
287        &mut self.inner.inner
288    }
289}
290
291impl<B: BufferMut> DynamicUniformBuffer<B> {
292    pub fn write<T>(&mut self, value: &T) -> Result<u64>
293    where
294        T: ?Sized + ShaderType + WriteInto,
295    {
296        T::assert_uniform_compat();
297        self.inner.write(value)
298    }
299}
300
301impl<B: BufferRef> DynamicUniformBuffer<B> {
302    pub fn read<T>(&mut self, value: &mut T) -> Result<()>
303    where
304        T: ?Sized + ShaderType + ReadFrom,
305    {
306        T::assert_uniform_compat();
307        self.inner.read(value)
308    }
309
310    pub fn create<T>(&mut self) -> Result<T>
311    where
312        T: ShaderType + CreateFrom,
313    {
314        T::assert_uniform_compat();
315        self.inner.create()
316    }
317}