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}