Skip to main content

bevy_render/render_resource/
buffer_vec.rs

1use core::{iter, marker::PhantomData, ops::Range, slice};
2
3use crate::{
4    render_resource::{AtomicPod, Buffer},
5    renderer::{RenderDevice, RenderQueue},
6};
7use bytemuck::{must_cast_slice, NoUninit};
8use encase::{
9    internal::{WriteInto, Writer},
10    ShaderType,
11};
12use thiserror::Error;
13use wgpu::{BindingResource, BufferAddress, BufferUsages};
14
15use super::GpuArrayBufferable;
16
17/// A structure for storing raw bytes that have already been properly formatted
18/// for use by the GPU.
19///
20/// "Properly formatted" means that item data already meets the alignment and padding
21/// requirements for how it will be used on the GPU. The item type must implement [`NoUninit`]
22/// for its data representation to be directly copyable.
23///
24/// Index, vertex, and instance-rate vertex buffers have no alignment nor padding requirements and
25/// so this helper type is a good choice for them.
26///
27/// The contained data is stored in system RAM. Calling [`reserve`](RawBufferVec::reserve)
28/// allocates VRAM from the [`RenderDevice`].
29/// [`write_buffer`](RawBufferVec::write_buffer) queues copying of the data
30/// from system RAM to VRAM.
31///
32/// Other options for storing GPU-accessible data are:
33/// * [`BufferVec`]
34/// * [`DynamicStorageBuffer`](crate::render_resource::DynamicStorageBuffer)
35/// * [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
36/// * [`GpuArrayBuffer`](crate::render_resource::GpuArrayBuffer)
37/// * [`StorageBuffer`](crate::render_resource::StorageBuffer)
38/// * [`Texture`](crate::render_resource::Texture)
39/// * [`UniformBuffer`](crate::render_resource::UniformBuffer)
40pub struct RawBufferVec<T: NoUninit> {
41    values: Vec<T>,
42    buffer: Option<Buffer>,
43    capacity: usize,
44    item_size: usize,
45    buffer_usage: BufferUsages,
46    label: Option<String>,
47    changed: bool,
48}
49
50impl<T: NoUninit> RawBufferVec<T> {
51    /// Creates a new [`RawBufferVec`] with the given [`BufferUsages`].
52    pub const fn new(buffer_usage: BufferUsages) -> Self {
53        Self {
54            values: Vec::new(),
55            buffer: None,
56            capacity: 0,
57            item_size: size_of::<T>(),
58            buffer_usage,
59            label: None,
60            changed: false,
61        }
62    }
63
64    /// Returns a handle to the buffer, if the data has been uploaded.
65    #[inline]
66    pub fn buffer(&self) -> Option<&Buffer> {
67        self.buffer.as_ref()
68    }
69
70    /// Returns the binding for the buffer if the data has been uploaded.
71    #[inline]
72    pub fn binding(&self) -> Option<BindingResource<'_>> {
73        Some(BindingResource::Buffer(
74            self.buffer()?.as_entire_buffer_binding(),
75        ))
76    }
77
78    /// Returns the amount of space that the GPU will use before reallocating.
79    #[inline]
80    pub fn capacity(&self) -> usize {
81        self.capacity
82    }
83
84    /// Returns the number of items that have been pushed to this buffer.
85    #[inline]
86    pub fn len(&self) -> usize {
87        self.values.len()
88    }
89
90    /// Returns true if the buffer is empty.
91    #[inline]
92    pub fn is_empty(&self) -> bool {
93        self.values.is_empty()
94    }
95
96    /// Adds a new value and returns its index.
97    pub fn push(&mut self, value: T) -> usize {
98        let index = self.values.len();
99        self.values.push(value);
100        index
101    }
102
103    pub fn append(&mut self, other: &mut RawBufferVec<T>) {
104        self.values.append(&mut other.values);
105    }
106
107    /// Returns the value at the given index.
108    pub fn get(&self, index: u32) -> Option<&T> {
109        self.values.get(index as usize)
110    }
111
112    /// Sets the value at the given index.
113    ///
114    /// The index must be less than [`RawBufferVec::len`].
115    pub fn set(&mut self, index: u32, value: T) {
116        self.values[index as usize] = value;
117    }
118
119    /// Preallocates space for `count` elements in the internal CPU-side buffer.
120    ///
121    /// Unlike [`RawBufferVec::reserve`], this doesn't have any effect on the GPU buffer.
122    pub fn reserve_internal(&mut self, count: usize) {
123        self.values.reserve(count);
124    }
125
126    /// Changes the debugging label of the buffer.
127    ///
128    /// The next time the buffer is updated (via [`reserve`](Self::reserve)), Bevy will inform
129    /// the driver of the new label.
130    pub fn set_label(&mut self, label: Option<&str>) {
131        let label = label.map(str::to_string);
132
133        if label != self.label {
134            self.changed = true;
135        }
136
137        self.label = label;
138    }
139
140    /// Returns the label
141    pub fn get_label(&self) -> Option<&str> {
142        self.label.as_deref()
143    }
144
145    /// Creates a [`Buffer`] on the [`RenderDevice`] with size
146    /// at least `size_of::<T>() * capacity`, unless a such a buffer already exists.
147    ///
148    /// If a [`Buffer`] exists, but is too small, references to it will be discarded,
149    /// and a new [`Buffer`] will be created. Any previously created [`Buffer`]s
150    /// that are no longer referenced will be deleted by the [`RenderDevice`]
151    /// once it is done using them (typically 1-2 frames).
152    ///
153    /// In addition to any [`BufferUsages`] provided when
154    /// the `RawBufferVec` was created, the buffer on the [`RenderDevice`]
155    /// is marked as [`BufferUsages::COPY_DST`](BufferUsages).
156    pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
157        let size = self.item_size * capacity;
158        if capacity > self.capacity || (self.changed && size > 0) {
159            self.capacity = capacity;
160            self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
161                label: make_buffer_label::<Self>(&self.label),
162                size: size as BufferAddress,
163                usage: BufferUsages::COPY_DST | self.buffer_usage,
164                mapped_at_creation: false,
165            }));
166            self.changed = false;
167        }
168    }
169
170    /// Queues writing of data from system RAM to VRAM using the [`RenderDevice`]
171    /// and the provided [`RenderQueue`].
172    ///
173    /// Before queuing the write, a [`reserve`](RawBufferVec::reserve) operation
174    /// is executed.
175    pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
176        if self.values.is_empty() {
177            return;
178        }
179        self.reserve(self.values.len(), device);
180        if let Some(buffer) = &self.buffer {
181            let range = 0..self.item_size * self.values.len();
182            let bytes: &[u8] = must_cast_slice(&self.values);
183            queue.write_buffer(buffer, 0, &bytes[range]);
184        }
185    }
186
187    /// Queues writing of data from system RAM to VRAM using the [`RenderDevice`]
188    /// and the provided [`RenderQueue`].
189    ///
190    /// If the buffer is not initialized on the GPU or the range is bigger than the capacity it will
191    /// return an error. You'll need to either reserve a new buffer which will lose data on the GPU
192    /// or create a new buffer and copy the old data to it.
193    ///
194    /// This will only write the data contained in the given range. It is useful if you only want
195    /// to update a part of the buffer.
196    pub fn write_buffer_range(
197        &mut self,
198        render_queue: &RenderQueue,
199        range: Range<usize>,
200    ) -> Result<(), WriteBufferRangeError> {
201        if self.values.is_empty() {
202            return Err(WriteBufferRangeError::NoValuesToUpload);
203        }
204        if range.end > self.item_size * self.capacity {
205            return Err(WriteBufferRangeError::RangeBiggerThanBuffer);
206        }
207        if let Some(buffer) = &self.buffer {
208            // Cast only the bytes we need to write
209            let bytes: &[u8] = must_cast_slice(&self.values[range.start..range.end]);
210            render_queue.write_buffer(buffer, (range.start * self.item_size) as u64, bytes);
211            Ok(())
212        } else {
213            Err(WriteBufferRangeError::BufferNotInitialized)
214        }
215    }
216
217    /// Reduces the length of the buffer.
218    pub fn truncate(&mut self, len: usize) {
219        self.values.truncate(len);
220    }
221
222    /// Removes all elements from the buffer.
223    pub fn clear(&mut self) {
224        self.values.clear();
225    }
226
227    /// Removes and returns the last element in the buffer.
228    pub fn pop(&mut self) -> Option<T> {
229        self.values.pop()
230    }
231
232    pub fn swap_remove(&mut self, index: usize) -> T {
233        self.values.swap_remove(index)
234    }
235
236    pub fn values(&self) -> &Vec<T> {
237        &self.values
238    }
239
240    pub fn values_mut(&mut self) -> &mut Vec<T> {
241        &mut self.values
242    }
243}
244
245impl<T> RawBufferVec<T>
246where
247    T: NoUninit + Default,
248{
249    pub fn grow_set(&mut self, index: u32, value: T) {
250        self.values.reserve(index as usize + 1);
251        while index as usize + 1 > self.len() {
252            self.values.push(T::default());
253        }
254        self.values[index as usize] = value;
255    }
256}
257
258impl<T: NoUninit> Extend<T> for RawBufferVec<T> {
259    #[inline]
260    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
261        self.values.extend(iter);
262    }
263}
264
265/// A [`RawBufferVec`] that holds data that implements [`AtomicPod`].
266///
267/// This allows multiple threads to update the buffer to be sent to the GPU
268/// simultaneously. Note that they may only update *existing* data; pushing
269/// *new* data still requires exclusive access.
270pub struct AtomicRawBufferVec<T>
271where
272    T: AtomicPod,
273{
274    /// The underlying values.
275    ///
276    /// These are stored as their blob representation to allow for thread-safe
277    /// update.
278    values: Vec<T::Blob>,
279    /// The GPU buffer, if allocated.
280    buffer: Option<Buffer>,
281    /// The capacity of the GPU buffer.
282    capacity: usize,
283    /// The allowed `wgpu` buffer usages for the GPU buffer.
284    buffer_usage: BufferUsages,
285    /// An optional debug label to identify this buffer.
286    label: Option<String>,
287    /// Whether the buffer has been mutated on the CPU since the last time it
288    /// was uploaded to the GPU.
289    changed: bool,
290    phantom: PhantomData<T>,
291}
292
293impl<T> AtomicRawBufferVec<T>
294where
295    T: AtomicPod,
296{
297    /// Creates a new [`AtomicRawBufferVec`].
298    ///
299    /// The `buffer_usage` parameter tells `wgpu` which usages are allowed for
300    /// the backing buffer.
301    pub const fn new(buffer_usage: BufferUsages) -> Self {
302        Self {
303            values: Vec::new(),
304            buffer: None,
305            capacity: 0,
306            buffer_usage,
307            label: None,
308            changed: false,
309            phantom: PhantomData,
310        }
311    }
312
313    /// Creates a new [`AtomicRawBufferVec`] with a custom label.
314    ///
315    /// The `buffer_usage` parameter tells `wgpu` which usages are allowed for
316    /// the backing buffer.
317    pub fn with_label(buffer_usage: BufferUsages, label: &str) -> Self {
318        Self {
319            values: Vec::new(),
320            buffer: None,
321            capacity: 0,
322            buffer_usage,
323            label: Some(label.to_string()),
324            changed: false,
325            phantom: PhantomData,
326        }
327    }
328
329    /// Removes all elements from the buffer.
330    pub fn clear(&mut self) {
331        self.values.clear();
332    }
333
334    /// Returns the number of elements in the buffer.
335    pub fn len(&self) -> u32 {
336        self.values.len() as u32
337    }
338
339    /// Returns true if the vector is empty.
340    pub fn is_empty(&self) -> bool {
341        self.len() == 0
342    }
343
344    /// Adds a new value to the buffer, and returns its index.
345    ///
346    /// Internally, the value is converted to its blob representation.
347    pub fn push(&mut self, value: T) -> u32 {
348        let index = self.values.len();
349        self.values.push(T::Blob::default());
350        value.write_to_blob(&self.values[index]);
351        index as u32
352    }
353
354    /// Copies a value out of the buffer.
355    pub fn get(&self, index: u32) -> T {
356        T::read_from_blob(&self.values[index as usize])
357    }
358
359    /// Sets the value at the given index.
360    ///
361    /// If the index isn't in range of the buffer, this method panics.
362    ///
363    /// Internally, the value is converted to its blob representation.
364    ///
365    /// Note that this method is thread-safe and doesn't require `&mut self`.
366    /// It's your responsibility, however, to ensure synchronization; though
367    /// this method is memory-safe, it's possible for other threads to observe
368    /// partially-overwritten values if [`Self::get`] or similar methods are
369    /// called while the write operation is occurring.
370    pub fn set(&self, index: u32, value: T) {
371        value.write_to_blob(&self.values[index as usize]);
372    }
373
374    /// Creates a [`Buffer`] on the [`RenderDevice`] with size
375    /// at least `size_of::<T>() * capacity`, unless a such a buffer already exists.
376    ///
377    /// If a [`Buffer`] exists, but is too small, references to it will be discarded,
378    /// and a new [`Buffer`] will be created. Any previously created [`Buffer`]s
379    /// that are no longer referenced will be deleted by the [`RenderDevice`]
380    /// once it is done using them (typically 1-2 frames).
381    ///
382    /// In addition to any [`BufferUsages`] provided when
383    /// the `AtomicRawBufferVec` was created, the buffer on the [`RenderDevice`]
384    /// is marked as [`BufferUsages::COPY_DST`](BufferUsages).
385    pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
386        let size = size_of::<T::Blob>() * capacity;
387        if capacity > self.capacity || (self.changed && size > 0) {
388            self.capacity = capacity;
389            self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
390                label: make_buffer_label::<Self>(&self.label),
391                size: size as BufferAddress,
392                usage: BufferUsages::COPY_DST | self.buffer_usage,
393                mapped_at_creation: false,
394            }));
395            self.changed = false;
396        }
397    }
398
399    /// Queues writing of data from system RAM to VRAM using the
400    /// [`RenderDevice`] and the provided [`RenderQueue`].
401    ///
402    /// Before queuing the write, a [`reserve`](AtomicRawBufferVec::reserve)
403    /// operation is executed.
404    pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
405        self.write_buffer_range(0..self.values.len(), device, queue);
406    }
407
408    /// Queues writing of data from system RAM to VRAM using the
409    /// [`RenderDevice`] and the provided [`RenderQueue`].
410    ///
411    /// Before queuing the write, a [`reserve`](AtomicRawBufferVec::reserve)
412    /// operation is executed.
413    pub fn write_buffer_range(
414        &mut self,
415        range: Range<usize>,
416        device: &RenderDevice,
417        queue: &RenderQueue,
418    ) {
419        assert!(
420            range.start <= range.end
421                && range.start <= self.values.len()
422                && range.end <= self.values.len()
423        );
424        if range.start == range.end {
425            return;
426        }
427        self.reserve(range.end, device);
428
429        let Some(buffer) = &self.buffer else { return };
430
431        // SAFETY: We checked the range above to make sure it's in bounds.
432        // We have `&mut self`, so there are no other references to our
433        // buffer, and the `Blob` type must implement `AtomicPodBlob`, which
434        // guarantees that it be bit-equivalent to an array of `AtomicU32`s
435        // (i.e. POD except that they're atomic).
436        unsafe {
437            let bytes: &[u8] = slice::from_raw_parts(
438                self.values.as_ptr().add(range.start).cast::<u8>(),
439                (range.end - range.start) * size_of::<T::Blob>(),
440            );
441            let start_offset = range.start as u64 * size_of::<T::Blob>() as u64;
442            queue.write_buffer(buffer, start_offset, bytes);
443        }
444    }
445
446    /// Returns a handle to the buffer, if the data has been uploaded.
447    #[inline]
448    pub fn buffer(&self) -> Option<&Buffer> {
449        self.buffer.as_ref()
450    }
451
452    /// Grows the buffer by adding default values so that it's at least the
453    /// given size.
454    ///
455    /// If the buffer is already large enough, this method does nothing.
456    pub fn grow(&mut self, new_len: u32) {
457        if self.len() < new_len {
458            self.values.resize_with(new_len as usize, T::Blob::default);
459        }
460    }
461
462    /// Truncates the buffer to the given length.
463    ///
464    /// If the buffer is already shorter, this method does nothing.
465    pub fn truncate(&mut self, len: u32) {
466        self.values.truncate(len as usize);
467    }
468}
469
470/// Like [`RawBufferVec`], but doesn't require that the data type `T` be
471/// [`NoUninit`].
472///
473/// This is a high-performance data structure that you should use whenever
474/// possible if your data is more complex than is suitable for [`RawBufferVec`].
475/// The [`ShaderType`] trait from the `encase` library is used to ensure that
476/// the data is correctly aligned for use by the GPU.
477///
478/// For performance reasons, unlike [`RawBufferVec`], this type doesn't allow
479/// CPU access to the data after it's been added via [`BufferVec::push`]. If you
480/// need CPU access to the data, consider another type, such as
481/// [`StorageBuffer`][super::StorageBuffer].
482///
483/// Other options for storing GPU-accessible data are:
484/// * [`DynamicStorageBuffer`](crate::render_resource::DynamicStorageBuffer)
485/// * [`DynamicUniformBuffer`](crate::render_resource::DynamicUniformBuffer)
486/// * [`GpuArrayBuffer`](crate::render_resource::GpuArrayBuffer)
487/// * [`RawBufferVec`]
488/// * [`StorageBuffer`](crate::render_resource::StorageBuffer)
489/// * [`Texture`](crate::render_resource::Texture)
490/// * [`UniformBuffer`](crate::render_resource::UniformBuffer)
491pub struct BufferVec<T>
492where
493    T: ShaderType + WriteInto,
494{
495    data: Vec<u8>,
496    buffer: Option<Buffer>,
497    capacity: usize,
498    buffer_usage: BufferUsages,
499    label: Option<String>,
500    label_changed: bool,
501    phantom: PhantomData<T>,
502}
503
504impl<T> BufferVec<T>
505where
506    T: ShaderType + WriteInto,
507{
508    /// Creates a new [`BufferVec`] with the given [`BufferUsages`].
509    pub const fn new(buffer_usage: BufferUsages) -> Self {
510        Self {
511            data: vec![],
512            buffer: None,
513            capacity: 0,
514            buffer_usage,
515            label: None,
516            label_changed: false,
517            phantom: PhantomData,
518        }
519    }
520
521    /// Returns a handle to the buffer, if the data has been uploaded.
522    #[inline]
523    pub fn buffer(&self) -> Option<&Buffer> {
524        self.buffer.as_ref()
525    }
526
527    /// Returns the binding for the buffer if the data has been uploaded.
528    #[inline]
529    pub fn binding(&self) -> Option<BindingResource<'_>> {
530        Some(BindingResource::Buffer(
531            self.buffer()?.as_entire_buffer_binding(),
532        ))
533    }
534
535    /// Returns the amount of space that the GPU will use before reallocating.
536    #[inline]
537    pub fn capacity(&self) -> usize {
538        self.capacity
539    }
540
541    /// Returns the number of items that have been pushed to this buffer.
542    #[inline]
543    pub fn len(&self) -> usize {
544        self.data.len() / u64::from(T::min_size()) as usize
545    }
546
547    /// Returns true if the buffer is empty.
548    #[inline]
549    pub fn is_empty(&self) -> bool {
550        self.data.is_empty()
551    }
552
553    /// Adds a new value and returns its index.
554    pub fn push(&mut self, value: T) -> usize {
555        let element_size = u64::from(T::min_size()) as usize;
556        let offset = self.data.len();
557
558        // We can't optimize and push uninitialized data here (using e.g. spare_capacity_mut())
559        // because write_into() does not initialize inner padding bytes in T's expansion
560        self.data.extend(iter::repeat_n(0, element_size));
561
562        // Take a slice of the new data for `write_into` to use. This is
563        // important: it hoists the bounds check up here so that the compiler
564        // can eliminate all the bounds checks that `write_into` will emit.
565        let mut dest = &mut self.data[offset..(offset + element_size)];
566        value.write_into(&mut Writer::new(&value, &mut dest, 0).unwrap());
567
568        offset / u64::from(T::min_size()) as usize
569    }
570
571    /// Changes the debugging label of the buffer.
572    ///
573    /// The next time the buffer is updated (via [`Self::reserve`]), Bevy will inform
574    /// the driver of the new label.
575    pub fn set_label(&mut self, label: Option<&str>) {
576        let label = label.map(str::to_string);
577
578        if label != self.label {
579            self.label_changed = true;
580        }
581
582        self.label = label;
583    }
584
585    /// Returns the label
586    pub fn get_label(&self) -> Option<&str> {
587        self.label.as_deref()
588    }
589
590    /// Preallocates space for `count` elements in the internal CPU-side buffer.
591    ///
592    /// Unlike [`Self::reserve`], this doesn't have any effect on the GPU buffer.
593    pub fn reserve_internal(&mut self, count: usize) {
594        self.data.reserve(count * u64::from(T::min_size()) as usize);
595    }
596
597    /// Creates a [`Buffer`] on the [`RenderDevice`] with size
598    /// at least `size_of::<T>() * capacity`, unless such a buffer already exists.
599    ///
600    /// If a [`Buffer`] exists, but is too small, references to it will be discarded,
601    /// and a new [`Buffer`] will be created. Any previously created [`Buffer`]s
602    /// that are no longer referenced will be deleted by the [`RenderDevice`]
603    /// once it is done using them (typically 1-2 frames).
604    ///
605    /// In addition to any [`BufferUsages`] provided when
606    /// the `BufferVec` was created, the buffer on the [`RenderDevice`]
607    /// is marked as [`BufferUsages::COPY_DST`](BufferUsages).
608    pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
609        if capacity <= self.capacity && !self.label_changed {
610            return;
611        }
612
613        self.capacity = capacity;
614        let size = u64::from(T::min_size()) as usize * capacity;
615        self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
616            label: make_buffer_label::<Self>(&self.label),
617            size: size as BufferAddress,
618            usage: BufferUsages::COPY_DST | self.buffer_usage,
619            mapped_at_creation: false,
620        }));
621        self.label_changed = false;
622    }
623
624    /// Queues writing of data from system RAM to VRAM using the [`RenderDevice`]
625    /// and the provided [`RenderQueue`].
626    ///
627    /// Before queuing the write, a [`reserve`](BufferVec::reserve) operation is
628    /// executed.
629    pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
630        if self.data.is_empty() {
631            return;
632        }
633
634        self.reserve(self.data.len() / u64::from(T::min_size()) as usize, device);
635
636        let Some(buffer) = &self.buffer else { return };
637        queue.write_buffer(buffer, 0, &self.data);
638    }
639
640    /// Queues writing of data from system RAM to VRAM using the [`RenderDevice`]
641    /// and the provided [`RenderQueue`].
642    ///
643    /// If the buffer is not initialized on the GPU or the range is bigger than the capacity it will
644    /// return an error. You'll need to either reserve a new buffer which will lose data on the GPU
645    /// or create a new buffer and copy the old data to it.
646    ///
647    /// This will only write the data contained in the given range. It is useful if you only want
648    /// to update a part of the buffer.
649    pub fn write_buffer_range(
650        &mut self,
651        render_queue: &RenderQueue,
652        range: Range<usize>,
653    ) -> Result<(), WriteBufferRangeError> {
654        if self.data.is_empty() {
655            return Err(WriteBufferRangeError::NoValuesToUpload);
656        }
657        let item_size = u64::from(T::min_size()) as usize;
658        if range.end > item_size * self.capacity {
659            return Err(WriteBufferRangeError::RangeBiggerThanBuffer);
660        }
661        if let Some(buffer) = &self.buffer {
662            let bytes = &self.data[range.start..range.end];
663            render_queue.write_buffer(buffer, (range.start * item_size) as u64, bytes);
664            Ok(())
665        } else {
666            Err(WriteBufferRangeError::BufferNotInitialized)
667        }
668    }
669
670    /// Reduces the length of the buffer.
671    pub fn truncate(&mut self, len: usize) {
672        self.data.truncate(u64::from(T::min_size()) as usize * len);
673    }
674
675    /// Removes all elements from the buffer.
676    pub fn clear(&mut self) {
677        self.data.clear();
678    }
679}
680
681/// Like a [`BufferVec`], but only reserves space on the GPU for elements
682/// instead of initializing them CPU-side.
683///
684/// This type is useful when you're accumulating "output slots" for a GPU
685/// compute shader to write into.
686///
687/// The type `T` need not be [`NoUninit`], unlike [`RawBufferVec`]; it only has to
688/// be [`GpuArrayBufferable`].
689pub struct UninitBufferVec<T>
690where
691    T: GpuArrayBufferable,
692{
693    buffer: Option<Buffer>,
694    len: usize,
695    capacity: usize,
696    item_size: usize,
697    buffer_usage: BufferUsages,
698    label: Option<String>,
699    label_changed: bool,
700    phantom: PhantomData<T>,
701}
702
703impl<T> UninitBufferVec<T>
704where
705    T: GpuArrayBufferable,
706{
707    /// Creates a new [`UninitBufferVec`] with the given [`BufferUsages`].
708    pub const fn new(buffer_usage: BufferUsages) -> Self {
709        Self {
710            len: 0,
711            buffer: None,
712            capacity: 0,
713            item_size: size_of::<T>(),
714            buffer_usage,
715            label: None,
716            label_changed: false,
717            phantom: PhantomData,
718        }
719    }
720
721    /// Returns the buffer, if allocated.
722    #[inline]
723    pub fn buffer(&self) -> Option<&Buffer> {
724        self.buffer.as_ref()
725    }
726
727    /// Returns the binding for the buffer if the data has been uploaded.
728    #[inline]
729    pub fn binding(&self) -> Option<BindingResource<'_>> {
730        Some(BindingResource::Buffer(
731            self.buffer()?.as_entire_buffer_binding(),
732        ))
733    }
734
735    /// Reserves space for one more element in the buffer and returns its index.
736    pub fn add(&mut self) -> usize {
737        self.add_multiple(1)
738    }
739
740    /// Reserves space for the given number of elements in the buffer and
741    /// returns the index of the first one.
742    pub fn add_multiple(&mut self, count: usize) -> usize {
743        let index = self.len;
744        self.len += count;
745        index
746    }
747
748    /// Returns true if no elements have been added to this [`UninitBufferVec`].
749    pub fn is_empty(&self) -> bool {
750        self.len == 0
751    }
752
753    /// Removes all elements from the buffer.
754    pub fn clear(&mut self) {
755        self.len = 0;
756    }
757
758    /// Returns the length of the buffer.
759    pub fn len(&self) -> usize {
760        self.len
761    }
762
763    /// Returns the amount of space that the GPU will use before reallocating.
764    #[inline]
765    pub fn capacity(&self) -> usize {
766        self.capacity
767    }
768
769    /// Changes the debugging label of the buffer.
770    ///
771    /// The next time the buffer is updated (via [`Self::reserve`]), Bevy will inform
772    /// the driver of the new label.
773    pub fn set_label(&mut self, label: Option<&str>) {
774        let label = label.map(str::to_string);
775
776        if label != self.label {
777            self.label_changed = true;
778        }
779
780        self.label = label;
781    }
782
783    /// Returns the label
784    pub fn get_label(&self) -> Option<&str> {
785        self.label.as_deref()
786    }
787
788    /// Materializes the buffer on the GPU with space for `capacity` elements.
789    ///
790    /// If the buffer is already big enough, this function doesn't reallocate
791    /// the buffer.
792    pub fn reserve(&mut self, capacity: usize, device: &RenderDevice) {
793        if capacity <= self.capacity && !self.label_changed {
794            return;
795        }
796
797        self.capacity = capacity;
798        let size = self.item_size * capacity;
799        self.buffer = Some(device.create_buffer(&wgpu::BufferDescriptor {
800            label: make_buffer_label::<Self>(&self.label),
801            size: size as BufferAddress,
802            usage: BufferUsages::COPY_DST | self.buffer_usage,
803            mapped_at_creation: false,
804        }));
805
806        self.label_changed = false;
807    }
808
809    /// Materializes the buffer on the GPU, with an appropriate size for the
810    /// elements that have been pushed so far.
811    pub fn write_buffer(&mut self, device: &RenderDevice) {
812        if !self.is_empty() {
813            self.reserve(self.len, device);
814        }
815    }
816}
817
818/// A hybrid of [`RawBufferVec`] and [`UninitBufferVec`] that allows the CPU to
819/// push elements and to leave room for uninitialized elements for the GPU to
820/// populate at the end of the array.
821///
822/// All CPU elements mush be pushed *before* any trailing uninitialized elements
823/// can be reserved. In debug mode, this data structure enforces these
824/// preconditions with assertions.
825pub struct PartialBufferVec<T>
826where
827    T: NoUninit,
828{
829    /// The CPU-side values.
830    values: Vec<T>,
831    /// The GPU buffer, if allocated.
832    buffer: Option<Buffer>,
833    /// The total number of elements that have been allocated in the GPU buffer.
834    capacity: usize,
835    /// The number of extra uninitialized elements at the end.
836    ///
837    /// Thus the total needed length of the buffer is `self.values.len() +
838    /// self.uninit_element_count`.
839    uninit_element_count: usize,
840    /// The allowed `wgpu` usages of the buffer.
841    buffer_usages: BufferUsages,
842    /// An identifying debugging label for this buffer.
843    label: String,
844}
845
846impl<T> PartialBufferVec<T>
847where
848    T: NoUninit,
849{
850    /// Creates a new [`PartialBufferVec`] with the given allowed usages and the
851    /// given debugging label.
852    ///
853    /// `BufferUsages::COPY_DST` is implicitly added to the supplied set of
854    /// usages.
855    pub fn new(buffer_usages: BufferUsages, label: String) -> PartialBufferVec<T> {
856        PartialBufferVec {
857            values: vec![],
858            buffer: None,
859            capacity: 0,
860            uninit_element_count: 0,
861            buffer_usages: buffer_usages | BufferUsages::COPY_DST,
862            label,
863        }
864    }
865
866    /// Returns the allocated GPU buffer, if one exists.
867    pub fn buffer(&self) -> Option<&Buffer> {
868        self.buffer.as_ref()
869    }
870
871    /// Clears out the buffer, setting both the number of CPU-initialized
872    /// elements and extra uninitialized trailing elements to 0.
873    pub fn clear(&mut self) {
874        self.values.clear();
875        self.uninit_element_count = 0;
876    }
877
878    /// Ensures that the GPU buffer is allocated with the given capacity.
879    ///
880    /// If the cached GPU buffer is already big enough, this method does
881    /// nothing.
882    fn reserve(&mut self, capacity: usize, render_device: &RenderDevice) {
883        if capacity <= self.capacity {
884            return;
885        }
886
887        let size = size_of::<T>() * capacity;
888        self.capacity = capacity;
889        self.buffer = Some(render_device.create_buffer(&wgpu::BufferDescriptor {
890            label: Some(&self.label),
891            size: size as u64,
892            usage: self.buffer_usages,
893            mapped_at_creation: false,
894        }));
895    }
896
897    /// Writes the buffer to the GPU.
898    ///
899    /// `Self::reserve` is called automatically to ensure that the buffer has
900    /// the correct length (including enough space to hold all the trailing
901    /// uninitialized elements).
902    pub fn write_buffer(&mut self, render_device: &RenderDevice, render_queue: &RenderQueue) {
903        if self.is_empty() {
904            return;
905        }
906
907        self.reserve(self.len(), render_device);
908
909        let Some(ref buffer) = self.buffer else {
910            return;
911        };
912        render_queue.write_buffer(buffer, 0, must_cast_slice(&self.values[..]));
913    }
914
915    /// Returns true if this buffer is empty: i.e. if [`Self::len`] would return
916    /// 0.
917    pub fn is_empty(&self) -> bool {
918        self.len() == 0
919    }
920
921    /// Returns the total number of elements, both initialized and
922    /// uninitialized, in this buffer.
923    ///
924    /// That is, this method returns the sum of the number of initialized values
925    /// that the CPU pushed and the number of trailing uninitialized elements
926    /// that have been allocated.
927    pub fn len(&self) -> usize {
928        self.values.len() + self.uninit_element_count
929    }
930
931    /// Pushes an element with the given value to the buffer and returns its
932    /// index.
933    ///
934    /// Since this element is initialized by the CPU, and all CPU-initialized
935    /// elements must precede any trailing uninitialized elements, this method
936    /// panics in debug mode if [`Self::push_multiple_uninit`] has been called
937    /// since the last call to [`Self::clear`].
938    pub fn push_init(&mut self, value: T) -> usize {
939        debug_assert_eq!(self.uninit_element_count, 0);
940        let index = self.values.len();
941        self.values.push(value);
942        index
943    }
944
945    /// Pushes the given number of uninitialized elements to the end of the list
946    /// and returns the index of the first such element that was pushed.
947    ///
948    /// After calling this method with a nonzero `count`, it's no longer legal
949    /// to call [`Self::push_init`] without calling [`Self::clear`] first.
950    pub fn push_multiple_uninit(&mut self, count: usize) -> usize {
951        let first_index = self.values.len() + self.uninit_element_count;
952        self.uninit_element_count += count;
953        first_index
954    }
955}
956
957/// Error returned when `write_buffer_range` fails
958///
959/// See [`RawBufferVec::write_buffer_range`] [`BufferVec::write_buffer_range`]
960#[derive(Debug, Eq, PartialEq, Copy, Clone, Error)]
961pub enum WriteBufferRangeError {
962    #[error("the range is bigger than the capacity of the buffer")]
963    RangeBiggerThanBuffer,
964    #[error("the gpu buffer is not initialized")]
965    BufferNotInitialized,
966    #[error("there are no values to upload")]
967    NoValuesToUpload,
968}
969
970#[inline]
971#[cfg_attr(
972    not(feature = "type_label_buffers"),
973    expect(
974        clippy::extra_unused_type_parameters,
975        reason = "conditional compilation"
976    )
977)]
978pub(crate) fn make_buffer_label<'a, T>(label: &'a Option<String>) -> Option<&'a str> {
979    #[cfg(feature = "type_label_buffers")]
980    if label.is_none() {
981        return Some(core::any::type_name::<T>());
982    }
983    label.as_deref()
984}