Skip to main content

hexga_wgpu/
gpu_buffer.rs

1use super::*;
2
3pub type GpuBufferAddress = wgpu::BufferAddress;
4// Todo: impl the range operator ?
5
6pub trait GpuBufferNew<T>
7{
8    fn new(value: &[T], desc: GpuBufferDesc) -> Self;
9    fn with_capacity(capacity: usize, desc: GpuBufferDesc) -> Self;
10}
11pub trait GpuBufferByte
12{
13    fn bytes_len(&self) -> usize { self.wgpu_bytes_len() as _ }
14    fn wgpu_bytes_len(&self) -> GpuBufferAddress;
15
16    fn bytes_capacity(&self) -> usize { self.wgpu_bytes_capacity() as _ }
17    fn wgpu_bytes_capacity(&self) -> GpuBufferAddress { self.wgpu_bytes_len() }
18}
19
20pub trait GpuBufferAsWgpuSlice
21{
22    fn as_wgpu_slice(&self) -> wgpu::BufferSlice<'_>;
23}
24
25pub trait GpuAsUntypedSlice
26{
27    fn untyped_slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuUntypedSlice<'_>;
28
29    fn untyped_update<T>(&mut self, values: &[T])
30    where
31        T: BitAllUsed,
32    {
33        self.try_untyped_update(values)
34            .expect("failed to update the gpu buffer")
35    }
36    fn try_untyped_update<T>(&mut self, values: &[T]) -> Result<(), ()>
37    where
38        T: BitAllUsed,
39    {
40        self.untyped_slice(..).update(values)
41    }
42}
43
44pub trait GpuBufferRead<T>: GpuBufferByte
45{
46    fn len(&self) -> usize { self.wgpu_len() as _ }
47    fn wgpu_len(&self) -> GpuBufferAddress
48    {
49        self.wgpu_bytes_len() / std::mem::size_of::<T>() as GpuBufferAddress
50    }
51
52    fn capacity(&self) -> usize { self.wgpu_capacity() as _ }
53    fn wgpu_capacity(&self) -> GpuBufferAddress
54    {
55        self.wgpu_bytes_capacity() / std::mem::size_of::<T>() as GpuBufferAddress
56    }
57
58    fn read(&self) -> GpuResult<Vec<T>>
59    where
60        T: BitZero + BitPattern,
61    {
62        let mut v = Vec::new();
63        self.read_in(&mut v)?;
64        Ok(v)
65    }
66    fn read_in(&self, vec: &mut Vec<T>) -> GpuResult
67    where
68        T: BitZero + BitPattern;
69
70    fn slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuSlice<'_, T>;
71
72    fn update(&mut self, values: &[T])
73    where
74        T: BitAllUsed,
75    {
76        self.try_update(values)
77            .expect("failed to update the gpu buffer")
78    }
79    fn try_update(&mut self, values: &[T]) -> Result<(), ()>
80    where
81        T: BitAllUsed,
82    {
83        self.slice(..).update(values)
84    }
85}
86
87impl<T> GpuBufferNew<T> for wgpu::Buffer
88where
89    T: BitAllUsed,
90{
91    fn new(value: &[T], desc: GpuBufferDesc) -> Self
92    {
93        Gpu.wgpu
94            .device
95            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
96                label: None,
97                contents: bit::transmute_slice(value),
98                usage: desc.usages.into(),
99            })
100    }
101
102    fn with_capacity(capacity: usize, desc: GpuBufferDesc) -> Self
103    {
104        Gpu.wgpu.device.create_buffer(&wgpu::BufferDescriptor {
105            label: None,
106            usage: desc.usages.into(),
107            size: (capacity * std::mem::size_of::<T>()) as _,
108            mapped_at_creation: false,
109        })
110    }
111}
112impl GpuBufferByte for wgpu::Buffer
113{
114    fn wgpu_bytes_len(&self) -> GpuBufferAddress { self.size() }
115}
116impl GpuAsUntypedSlice for wgpu::Buffer
117{
118    fn untyped_slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuUntypedSlice<'_>
119    {
120        let bytes_len = self.size();
121
122        let start = match bounds.start_bound()
123        {
124            Bound::Included(&v) => v as GpuBufferAddress,
125            Bound::Excluded(&v) => (v + 1) as GpuBufferAddress,
126            Bound::Unbounded => 0,
127        }
128        .min(bytes_len);
129
130        let end = match bounds.end_bound()
131        {
132            Bound::Included(&v) => (v + 1) as GpuBufferAddress,
133            Bound::Excluded(&v) => v as GpuBufferAddress,
134            Bound::Unbounded => bytes_len,
135        }
136        .min(bytes_len);
137
138        assert!(
139            start <= end,
140            "GpuUntypedSlice::untyped_slice: invalid range"
141        );
142
143        GpuUntypedSlice {
144            buffer: self,
145            offset: start,
146            size: end - start,
147        }
148    }
149}
150
151fn create_staging_and_copy_slice(slice: &wgpu::BufferSlice) -> wgpu::Buffer
152{
153    let size = slice.size().get();
154
155    let staging = Gpu.wgpu.device.create_buffer(&wgpu::BufferDescriptor {
156        label: Some("staging buffer"),
157        size,
158        usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
159        mapped_at_creation: false,
160    });
161
162    let mut encoder = Gpu
163        .wgpu
164        .device
165        .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
166
167    encoder.copy_buffer_to_buffer(slice.buffer(), slice.offset(), &staging, 0, size);
168
169    Gpu.wgpu.queue.submit(Some(encoder.finish()));
170    staging
171}
172
173impl<'a> GpuBufferByte for wgpu::BufferSlice<'a>
174{
175    fn wgpu_bytes_len(&self) -> GpuBufferAddress { self.size().get() }
176}
177
178impl<'a, T> GpuBufferRead<T> for wgpu::BufferSlice<'a>
179{
180    fn read_in(&self, vec: &mut Vec<T>) -> GpuResult
181    where
182        T: BitZero + BitPattern,
183    {
184        let byte_len = self.size().get() as GpuBufferAddress as usize;
185        let elem_count = byte_len / std::mem::size_of::<T>();
186
187        if vec.len() < elem_count
188        {
189            vec.resize(elem_count, T::zeroed());
190        }
191
192        let staging = create_staging_and_copy_slice(self);
193        let slice = staging.slice(..);
194
195        let status = std::sync::Arc::new(std::sync::Mutex::new(None));
196        let status_clone = status.clone();
197
198        slice.map_async(wgpu::MapMode::Read, move |res| {
199            *status_clone.lock().unwrap() = Some(res);
200        });
201
202        while status.lock().unwrap().is_none()
203        {
204            Gpu.wgpu.device.poll(wgpu::PollType::Wait);
205        }
206
207        match status.lock().unwrap().take().unwrap()
208        {
209            Ok(()) =>
210            {
211                let data = slice.get_mapped_range();
212                let typed = bit::transmute_slice(&data);
213                vec[..typed.len()].copy_from_slice(typed);
214                drop(data);
215                staging.unmap();
216                Ok(())
217            }
218            Err(e) => Err(e.into()),
219        }
220    }
221
222    fn slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuSlice<'_, T> { todo!() }
223}
224
225/*
226fn get_range<S: RangeBounds<usize>,T>(bounds: S, bytes_len: usize) -> std::ops::Range<u64>
227{
228    let elem_size = std::mem::size_of::<T>()
229        .max(1); // To handle Zero Sized Type
230    let bytes_len = (bytes_len / elem_size * elem_size) as GpuBufferAddress;
231    let size = std::mem::size_of::<T>() as GpuBufferAddress;
232
233    let start = match bounds.start_bound() {
234        Bound::Included(&v) => v as GpuBufferAddress * size,
235        Bound::Excluded(&v) => (v + 1) as GpuBufferAddress * size,
236        Bound::Unbounded => 0,
237    }.min(bytes_len);
238
239    let end = match bounds.end_bound() {
240        Bound::Included(&v) => (v + 1) as GpuBufferAddress * size,
241        Bound::Excluded(&v) => v as GpuBufferAddress * size,
242        Bound::Unbounded => bytes_len,
243    }.min(bytes_len);
244
245    start..end
246}
247    */
248
249impl<T> GpuBufferRead<T> for wgpu::Buffer
250{
251    fn read_in(&self, mut vec: &mut Vec<T>) -> GpuResult
252    where
253        T: BitZero + BitPattern,
254    {
255        self.slice(..).read_in(vec)
256    }
257
258    fn slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuSlice<'_, T>
259    {
260        let untyped_slice = GpuUntypedSlice {
261            buffer: self,
262            offset: 0,
263            size: self.size(),
264        };
265        let slice: GpuSlice<'_, T> = untyped_slice.slice(bounds);
266        unsafe { GpuSlice::from_raw_parts(self, slice.offset, slice.size) }
267    }
268}
269
270#[derive(Copy, Clone, Debug, PartialEq)]
271pub struct GpuSlice<'a, T>
272{
273    buffer: &'a wgpu::Buffer,
274    offset: GpuBufferAddress,
275    size: GpuBufferAddress,
276    phantom: PhantomData<T>,
277}
278impl<'a, T> From<GpuSlice<'a, T>> for GpuUntypedSlice<'a>
279{
280    fn from(value: GpuSlice<'a, T>) -> Self
281    {
282        let size = std::mem::size_of::<T>() as GpuBufferAddress;
283        unsafe {
284            GpuUntypedSlice::from_raw_parts(value.buffer, value.offset * size, value.size * size)
285        }
286    }
287}
288impl<'a, T> GpuSlice<'a, T>
289{
290    pub unsafe fn from_raw_parts(
291        buffer: &'a wgpu::Buffer,
292        offset: GpuBufferAddress,
293        size: GpuBufferAddress,
294    ) -> Self
295    {
296        Self {
297            buffer,
298            offset,
299            size,
300            phantom: PhantomData,
301        }
302    }
303
304    pub unsafe fn from_untyped_slice_unchecked(slice: GpuUntypedSlice<'a>) -> Self
305    {
306        let size = std::mem::size_of::<T>().max(1) as GpuBufferAddress;
307        unsafe { Self::from_raw_parts(slice.buffer, slice.offset / size, slice.size / size) }
308    }
309
310    fn update(&self, values: &[T]) -> Result<(), ()>
311    where
312        T: BitAllUsed,
313    {
314        let untyped: GpuUntypedSlice<'_> = (*self).into();
315
316        let elem_size = std::mem::size_of::<T>();
317        if (values.len() as GpuBufferAddress) > self.size
318        {
319            return Err(()); // overflow
320        }
321        untyped.update(values)
322    }
323}
324impl<'a, T> GpuBufferAsWgpuSlice for GpuSlice<'a, T>
325{
326    fn as_wgpu_slice(&self) -> wgpu::BufferSlice<'a>
327    {
328        let size = std::mem::size_of::<T>() as GpuBufferAddress;
329        self.buffer
330            .slice((self.offset * size)..((self.offset + self.size) * size))
331    }
332}
333
334// TODO: impl TryFrom... same for the rest of the code in this file
335impl<'a, T> From<&'a wgpu::Buffer> for GpuSlice<'a, T>
336where
337    T: BitAnyPattern,
338{
339    fn from(buffer: &'a wgpu::Buffer) -> Self
340    {
341        assert_eq!(
342            buffer.bytes_len() % std::mem::size_of::<T>(),
343            0,
344            "wrong size"
345        );
346        unsafe { Self::from_untyped_slice_unchecked(GpuUntypedSlice::from(buffer)) }
347    }
348}
349
350#[derive(Copy, Clone, Debug, PartialEq)]
351pub struct GpuUntypedSlice<'a>
352{
353    buffer: &'a wgpu::Buffer,
354    offset: GpuBufferAddress,
355    size: GpuBufferAddress,
356}
357impl<'a> GpuUntypedSlice<'a>
358{
359    pub unsafe fn from_raw_parts(
360        buffer: &'a wgpu::Buffer,
361        offset: GpuBufferAddress,
362        size: GpuBufferAddress,
363    ) -> Self
364    {
365        Self {
366            buffer,
367            offset,
368            size,
369        }
370    }
371
372    fn update<T>(&self, values: &[T]) -> Result<(), ()>
373    where
374        T: BitAllUsed,
375    {
376        let value_bytes = values.len() * size_of::<T>();
377        if value_bytes as GpuBufferAddress > self.size
378        {
379            return Err(()); // overflow: values won't fit
380        }
381
382        let staging = Gpu
383            .wgpu
384            .device
385            .create_buffer_init(&wgpu::util::BufferInitDescriptor {
386                label: Some("update_bytes staging"),
387                contents: bit::try_transmute_slice(values).map_err(|_| ())?,
388                usage: wgpu::BufferUsages::COPY_SRC,
389            });
390
391        let mut encoder = Gpu
392            .wgpu
393            .device
394            .create_command_encoder(&wgpu::CommandEncoderDescriptor {
395                label: Some("update_bytes encoder"),
396            });
397
398        encoder.copy_buffer_to_buffer(
399            &staging,
400            0,
401            self.buffer,
402            self.offset,
403            value_bytes as GpuBufferAddress,
404        );
405
406        Gpu.wgpu.queue.submit(Some(encoder.finish()));
407
408        Ok(())
409    }
410}
411impl<'a> GpuBufferAsWgpuSlice for GpuUntypedSlice<'a>
412{
413    fn as_wgpu_slice(&self) -> wgpu::BufferSlice<'a>
414    {
415        self.buffer.slice(self.offset..self.offset + self.size)
416    }
417}
418
419impl<'a> From<&'a wgpu::Buffer> for GpuUntypedSlice<'a>
420{
421    fn from(buffer: &'a wgpu::Buffer) -> Self
422    {
423        Self {
424            buffer,
425            offset: 0,
426            size: buffer.size(),
427        }
428    }
429}
430impl<'a> GpuBufferByte for GpuUntypedSlice<'a>
431{
432    fn wgpu_bytes_len(&self) -> GpuBufferAddress { self.size }
433}
434impl<'a> GpuAsUntypedSlice for GpuUntypedSlice<'a>
435{
436    fn untyped_slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuUntypedSlice<'_>
437    {
438        let start = match bounds.start_bound()
439        {
440            Bound::Included(&v) => v as GpuBufferAddress,
441            Bound::Excluded(&v) => (v + 1) as GpuBufferAddress,
442            Bound::Unbounded => 0,
443        };
444
445        let end = match bounds.end_bound()
446        {
447            Bound::Included(&v) => (v + 1) as GpuBufferAddress,
448            Bound::Excluded(&v) => v as GpuBufferAddress,
449            Bound::Unbounded => self.size,
450        };
451
452        assert!(
453            start <= end && end <= self.size,
454            "GpuUntypedSlice::untyped_slice out of bounds"
455        );
456
457        GpuUntypedSlice {
458            buffer: self.buffer,
459            offset: self.offset + start,
460            size: end - start,
461        }
462    }
463}
464impl<'a, T> GpuBufferRead<T> for GpuUntypedSlice<'a>
465{
466    fn read_in(&self, vec: &mut Vec<T>) -> GpuResult
467    where
468        T: BitZero + BitPattern,
469    {
470        let elem_size = std::mem::size_of::<T>().max(1);
471        let elem_count = (self.size / elem_size as GpuBufferAddress) as usize;
472        if vec.len() < elem_count
473        {
474            vec.resize(elem_count, T::zeroed());
475        }
476
477        let staging = create_staging_and_copy_slice(&self.as_wgpu_slice());
478
479        let slice = staging.slice(..);
480        let status = std::sync::Arc::new(std::sync::Mutex::new(None));
481        let status_clone = status.clone();
482
483        slice.map_async(wgpu::MapMode::Read, move |res| {
484            *status_clone.lock().unwrap() = Some(res);
485        });
486
487        while status.lock().unwrap().is_none()
488        {
489            Gpu.wgpu.device.poll(wgpu::PollType::Wait);
490        }
491
492        match status.lock().unwrap().take().unwrap()
493        {
494            Ok(()) =>
495            {
496                let data = slice.get_mapped_range();
497                let typed = bit::transmute_slice(&data);
498                vec[..typed.len()].copy_from_slice(typed);
499                drop(data);
500                staging.unmap();
501                Ok(())
502            }
503            Err(e) => Err(e.into()),
504        }
505    }
506
507    fn slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuSlice<'_, T>
508    {
509        let elem_size = std::mem::size_of::<T>().max(1) as GpuBufferAddress;
510        let bytes_len = self.size;
511
512        let start = match bounds.start_bound()
513        {
514            std::ops::Bound::Included(&v) => (v as GpuBufferAddress) * elem_size,
515            std::ops::Bound::Excluded(&v) => ((v + 1) as GpuBufferAddress) * elem_size,
516            std::ops::Bound::Unbounded => 0,
517        }
518        .min(bytes_len);
519
520        let end = match bounds.end_bound()
521        {
522            std::ops::Bound::Included(&v) => ((v + 1) as GpuBufferAddress) * elem_size,
523            std::ops::Bound::Excluded(&v) => (v as GpuBufferAddress) * elem_size,
524            std::ops::Bound::Unbounded => bytes_len,
525        }
526        .min(bytes_len);
527
528        let size = end - start;
529
530        assert!(
531            start <= end && size % elem_size == 0,
532            "GpuSlice<T>::slice: requested range not aligned with element size"
533        );
534
535        let untyped = GpuUntypedSlice {
536            buffer: self.buffer,
537            offset: self.offset + start,
538            size,
539        };
540
541        unsafe { GpuSlice::from_untyped_slice_unchecked(untyped) }
542    }
543}
544
545#[repr(transparent)]
546#[derive(Clone, Debug, PartialEq, Hash)]
547pub struct GpuUntypedBuffer
548{
549    pub(crate) wgpu: wgpu::Buffer,
550    private_constructor: (),
551}
552impl Handle for GpuUntypedBuffer {}
553
554impl<T> GpuBufferNew<T> for GpuUntypedBuffer
555where
556    T: BitAllUsed,
557{
558    fn new(value: &[T], desc: GpuBufferDesc) -> Self
559    {
560        Self {
561            wgpu: wgpu::Buffer::new(value, desc),
562            private_constructor: (),
563        }
564    }
565
566    fn with_capacity(capacity: usize, desc: GpuBufferDesc) -> Self
567    {
568        Self {
569            wgpu: <wgpu::Buffer as GpuBufferNew<T>>::with_capacity(capacity, desc),
570            private_constructor: (),
571        }
572    }
573}
574
575impl From<wgpu::Buffer> for GpuUntypedBuffer
576{
577    fn from(buffer: wgpu::Buffer) -> Self
578    {
579        Self {
580            wgpu: buffer,
581            private_constructor: (),
582        }
583    }
584}
585impl From<GpuUntypedBuffer> for wgpu::Buffer
586{
587    fn from(value: GpuUntypedBuffer) -> Self { value.wgpu }
588}
589impl GpuBufferByte for GpuUntypedBuffer
590{
591    fn wgpu_bytes_len(&self) -> GpuBufferAddress { self.wgpu.wgpu_bytes_len() }
592}
593impl GpuAsUntypedSlice for GpuUntypedBuffer
594{
595    fn untyped_slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuUntypedSlice<'_>
596    {
597        self.wgpu.untyped_slice(bounds)
598    }
599}
600impl<T> GpuBufferRead<T> for GpuUntypedBuffer
601where
602    wgpu::Buffer: GpuBufferRead<T>,
603{
604    fn read_in(&self, vec: &mut Vec<T>) -> GpuResult
605    where
606        T: BitZero + BitPattern,
607    {
608        self.wgpu.read_in(vec)
609    }
610    fn slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuSlice<'_, T>
611    {
612        GpuBufferRead::<T>::slice(&self.wgpu, bounds)
613    }
614}
615
616#[repr(transparent)]
617#[derive(Clone, Debug, PartialEq, Hash)]
618pub struct GpuBuffer<T>
619{
620    pub(crate) wgpu: wgpu::Buffer,
621    phantom: PhantomData<T>,
622}
623impl<T> Handle for GpuBuffer<T> where T: BitAllUsed {}
624
625impl<T> GpuBufferNew<T> for GpuBuffer<T>
626where
627    T: BitAllUsed,
628{
629    fn new(value: &[T], desc: GpuBufferDesc) -> Self
630    {
631        Self {
632            wgpu: wgpu::Buffer::new(value, desc),
633            phantom: PhantomData,
634        }
635    }
636
637    fn with_capacity(capacity: usize, desc: GpuBufferDesc) -> Self
638    {
639        Self {
640            wgpu: <wgpu::Buffer as GpuBufferNew<T>>::with_capacity(capacity, desc),
641            phantom: PhantomData,
642        }
643    }
644}
645
646impl<T> From<wgpu::Buffer> for GpuBuffer<T>
647where
648    T: BitAnyPattern,
649{
650    fn from(buffer: wgpu::Buffer) -> Self
651    {
652        assert_eq!(
653            buffer.bytes_len() % std::mem::size_of::<T>(),
654            0,
655            "wrong gpu buffer size"
656        );
657        Self {
658            wgpu: buffer,
659            phantom: PhantomData,
660        }
661    }
662}
663impl<T> From<GpuUntypedBuffer> for GpuBuffer<T>
664where
665    T: BitAnyPattern,
666{
667    fn from(buffer: GpuUntypedBuffer) -> Self { Self::from(buffer.wgpu) }
668}
669impl<T> From<GpuBuffer<T>> for wgpu::Buffer
670{
671    fn from(value: GpuBuffer<T>) -> Self { value.wgpu }
672}
673impl<T> From<GpuBuffer<T>> for GpuUntypedBuffer
674{
675    fn from(value: GpuBuffer<T>) -> Self { GpuUntypedBuffer::from(value.wgpu) }
676}
677
678impl<T> GpuBufferByte for GpuBuffer<T>
679{
680    fn wgpu_bytes_len(&self) -> GpuBufferAddress { self.wgpu.wgpu_bytes_len() }
681}
682impl<T> GpuAsUntypedSlice for GpuBuffer<T>
683{
684    fn untyped_slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuUntypedSlice<'_>
685    {
686        self.wgpu.untyped_slice(bounds)
687    }
688    fn try_untyped_update<T2>(&mut self, values: &[T2]) -> Result<(), ()>
689    where
690        T2: BitAllUsed,
691    {
692        if std::mem::size_of::<T>() != std::mem::size_of::<T2>()
693        {
694            return Err(());
695        }
696        self.untyped_slice(..).update(values)
697    }
698}
699impl<T> GpuBufferRead<T> for GpuBuffer<T>
700where
701    wgpu::Buffer: GpuBufferRead<T>,
702{
703    fn read_in(&self, vec: &mut Vec<T>) -> GpuResult
704    where
705        T: BitZero + BitPattern,
706    {
707        self.wgpu.read_in(vec)
708    }
709    fn slice<S: RangeBounds<usize>>(&self, bounds: S) -> GpuSlice<'_, T>
710    {
711        GpuBufferRead::<T>::slice(&self.wgpu, bounds)
712    }
713}
714
715/// Different ways that you can use a buffer.
716///
717/// The usages determine what kind of memory the buffer is allocated from and what
718/// actions the buffer can partake in.
719///
720/// Corresponds to [WebGPU `GPUBufferUsageFlags`](
721/// https://gpuweb.github.io/gpuweb/#typedefdef-gpubufferusageflags).
722#[bit_index]
723#[repr(u32)]
724pub enum BufferUsage
725{
726    /// Allow a buffer to be mapped for reading using [`Buffer::map_async`] + [`Buffer::get_mapped_range`].
727    /// This does not include creating a buffer with [`BufferDescriptor::mapped_at_creation`] set.
728    ///
729    /// If [`Features::MAPPABLE_PRIMARY_BUFFERS`] isn't enabled, the only other usage a buffer
730    /// may have is COPY_DST.
731    MapReap = 0,
732    /// Allow a buffer to be mapped for writing using [`Buffer::map_async`] + [`Buffer::get_mapped_range_mut`].
733    /// This does not include creating a buffer with `mapped_at_creation` set.
734    ///
735    /// If [`Features::MAPPABLE_PRIMARY_BUFFERS`] feature isn't enabled, the only other usage a buffer
736    /// may have is COPY_SRC.
737    MapWrite = 1,
738    /// Allow a buffer to be the source buffer for a [`CommandEncoder::copy_buffer_to_buffer`] or [`CommandEncoder::copy_buffer_to_texture`]
739    /// operation.
740    CopySrc = 2,
741    /// Allow a buffer to be the destination buffer for a [`CommandEncoder::copy_buffer_to_buffer`], [`CommandEncoder::copy_texture_to_buffer`],
742    /// [`CommandEncoder::clear_buffer`] or [`Queue::write_buffer`] operation.
743    CopyDst = 3,
744    /// Allow a buffer to be the index buffer in a draw operation.
745    Index = 4,
746    /// Allow a buffer to be the vertex buffer in a draw operation.
747    Vertex = 5,
748    /// Allow a buffer to be a [`BufferBindingType::Uniform`] inside a bind group.
749    Uniform = 6,
750    /// Allow a buffer to be a [`BufferBindingType::Storage`] inside a bind group.
751    Storage = 7,
752    /// Allow a buffer to be the indirect buffer in an indirect draw call.
753    Indirect = 8,
754    /// Allow a buffer to be the destination buffer for a [`CommandEncoder::resolve_query_set`] operation.
755    QueryResolve = 9,
756    /// Allows a buffer to be used as input for a bottom level acceleration structure build
757    BlasInput = 10,
758    /// Allows a buffer to be used as input for a top level acceleration structure build
759    TlasInput = 11,
760}
761impl BufferUsageFlags
762{
763    pub const fn from_wgpu(value: wgpu::BufferUsages) -> Self
764    {
765        unsafe { Self::from_bits_unchecked(value.bits()) }
766    }
767}
768impl From<wgpu::BufferUsages> for BufferUsageFlags
769{
770    #[inline(always)]
771    fn from(value: wgpu::BufferUsages) -> Self { Self::from_wgpu(value) }
772}
773impl From<BufferUsageFlags> for wgpu::BufferUsages
774{
775    fn from(value: BufferUsageFlags) -> Self { Self::from_bits(value.bits()).expect("") }
776}
777
778#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
779pub struct GpuBufferDesc
780{
781    pub usages: BufferUsageFlags,
782    pub name: Option<&'static str>,
783}
784impl Default for GpuBufferDesc
785{
786    fn default() -> Self { Self::new() }
787}
788impl GpuBufferDesc
789{
790    pub const fn new() -> Self
791    {
792        Self {
793            usages: BufferUsageFlags::CopyDst.union(BufferUsageFlags::CopySrc),
794            name: None,
795        }
796    }
797
798    pub const fn add_usage(mut self, usage: BufferUsageFlags) -> Self
799    {
800        self.usages = self.usages.union(usage);
801        self
802    }
803    pub const fn with_usages(mut self, usages: BufferUsageFlags) -> Self
804    {
805        self.usages = usages;
806        self
807    }
808    pub const fn with_label(mut self, label: Option<&'static str>) -> Self
809    {
810        self.name = label;
811        self
812    }
813
814    pub const VERTEX: Self = Self::new().add_usage(BufferUsageFlags::Vertex);
815    pub const INDEX: Self = Self::new().add_usage(BufferUsageFlags::Index);
816}
817
818pub trait ToGpuBuffer<T>
819where
820    T: BitAllUsed,
821{
822    fn to_gpu_buffer(self, desc: GpuBufferDesc) -> GpuBuffer<T>;
823}
824impl<T> ToGpuBuffer<T> for &[T]
825where
826    T: BitAllUsed,
827{
828    fn to_gpu_buffer(self, desc: GpuBufferDesc) -> GpuBuffer<T> { GpuBuffer::new(self, desc) }
829}