Skip to main content

wgpu/api/
buffer.rs

1use alloc::{boxed::Box, string::String, sync::Arc, vec::Vec};
2use core::{
3    error, fmt,
4    num::NonZero,
5    ops::{Bound, Range, RangeBounds},
6};
7
8use crate::util::Mutex;
9use crate::*;
10
11/// Handle to a GPU-accessible buffer.
12///
13/// A `Buffer` is a memory allocation for use by the GPU, somewhat analogous to
14/// <code>[Box]&lt;[\[u8\]][primitive@slice]&gt;</code> in Rust.
15/// The contents of buffers are untyped bytes; it is up to the application to
16/// specify the interpretation of the bytes when the buffer is used, in ways
17/// such as [`VertexBufferLayout`].
18/// A single buffer can be used to hold multiple independent pieces of data at
19/// different offsets (e.g. both vertices and indices for one or more meshes).
20///
21/// A `Buffer`'s bytes have "interior mutability": functions like
22/// [`Queue::write_buffer`] or [mapping] a buffer for writing only require a
23/// `&Buffer`, not a `&mut Buffer`, even though they modify its contents. `wgpu`
24/// prevents simultaneous reads and writes of buffer contents using run-time
25/// checks.
26///
27/// Created with [`Device::create_buffer()`] or
28/// [`DeviceExt::create_buffer_init()`].
29///
30/// Corresponds to [WebGPU `GPUBuffer`](https://gpuweb.github.io/gpuweb/#buffer-interface).
31///
32/// [mapping]: Buffer#mapping-buffers
33///
34/// # How to get your data into a buffer
35///
36/// Every `Buffer` starts with all bytes zeroed.
37/// There are many ways to load data into a `Buffer`:
38///
39/// - When creating a buffer, you may set the [`mapped_at_creation`][mac] flag,
40///   then write to its [`get_mapped_range_mut()`][Buffer::get_mapped_range_mut].
41///   This only works when the buffer is created and has not yet been used by
42///   the GPU, but it is all you need for buffers whose contents do not change
43///   after creation.
44///   - You may use [`DeviceExt::create_buffer_init()`] as a convenient way to
45///     do that and copy data from a `&[u8]` you provide.
46/// - After creation, you may use [`Buffer::map_async()`] to map it again;
47///   however, you then need to wait until the GPU is no longer using the buffer
48///   before you begin writing.
49/// - You may use [`CommandEncoder::copy_buffer_to_buffer()`] to copy data into
50///   this buffer from another buffer.
51/// - You may use [`Queue::write_buffer()`] to copy data into the buffer from a
52///   `&[u8]`. This uses a temporary “staging” buffer managed by `wgpu` to hold
53///   the data.
54///   - [`Queue::write_buffer_with()`] allows you to write directly into temporary
55///     storage instead of providing a slice you already prepared, which may
56///     allow *your* code to save the allocation of a [`Vec`] or such.
57/// - You may use [`util::StagingBelt`] to manage a set of temporary buffers.
58///   This may be more efficient than [`Queue::write_buffer_with()`] when you
59///   have many small copies to perform, but requires more steps to use, and
60///   tuning of the belt buffer size.
61/// - You may write your own staging buffer management customized to your
62///   application, based on mapped buffers and
63///   [`CommandEncoder::copy_buffer_to_buffer()`].
64/// - A GPU computation’s results can be stored in a buffer:
65///   - A [compute shader][ComputePipeline] may write to a buffer bound as a
66///     [storage buffer][BufferBindingType::Storage].
67///   - A render pass may render to a texture which is then copied to a buffer
68///     using [`CommandEncoder::copy_texture_to_buffer()`].
69///
70/// # Mapping buffers
71///
72/// If a `Buffer` is created with the appropriate [`usage`], it can be *mapped*:
73/// you can make its contents accessible to the CPU as an ordinary `&[u8]` or
74/// `&mut [u8]` slice of bytes. Buffers created with the
75/// [`mapped_at_creation`][mac] flag set are also mapped initially.
76///
77/// Depending on the hardware, the buffer could be memory shared between CPU and
78/// GPU, so that the CPU has direct access to the same bytes the GPU will
79/// consult; or it may be ordinary CPU memory, whose contents the system must
80/// copy to/from the GPU as needed. This crate's API is designed to work the
81/// same way in either case: at any given time, a buffer is either mapped and
82/// available to the CPU, or unmapped and ready for use by the GPU, but never
83/// both. This makes it impossible for either side to observe changes by the
84/// other immediately, and any necessary transfers can be carried out when the
85/// buffer transitions from one state to the other.
86///
87/// There are two ways to map a buffer:
88///
89/// - If [`BufferDescriptor::mapped_at_creation`] is `true`, then the entire
90///   buffer is mapped when it is created. This is the easiest way to initialize
91///   a new buffer. You can set `mapped_at_creation` on any kind of buffer,
92///   regardless of its [`usage`] flags.
93///
94/// - If the buffer's [`usage`] includes the [`MAP_READ`] or [`MAP_WRITE`]
95///   flags, then you can call `buffer.slice(range).map_async(mode, callback)`
96///   to map the portion of `buffer` given by `range`. This waits for the GPU to
97///   finish using the buffer, and invokes `callback` as soon as the buffer is
98///   safe for the CPU to access.
99///
100/// Once a buffer is mapped:
101///
102/// - You can call `buffer.slice(range).get_mapped_range()` to obtain a
103///   [`BufferView`], which dereferences to a `&[u8]` that you can use to read
104///   the buffer's contents.
105///
106/// - Or, you can call `buffer.slice(range).get_mapped_range_mut()` to obtain a
107///   [`BufferViewMut`], which dereferences to a `&mut [u8]` that you can use to
108///   read and write the buffer's contents.
109///
110/// The given `range` must fall within the mapped portion of the buffer. If you
111/// attempt to access overlapping ranges, even for shared access only, these
112/// methods panic.
113///
114/// While a buffer is mapped, you may not submit any commands to the GPU that
115/// access it. You may record command buffers that use the buffer, but if you
116/// submit them while the buffer is mapped, submission will panic.
117///
118/// When you are done using the buffer on the CPU, you must call
119/// [`Buffer::unmap`] to make it available for use by the GPU again. All
120/// [`BufferView`] and [`BufferViewMut`] views referring to the buffer must be
121/// dropped before you unmap it; otherwise, [`Buffer::unmap`] will panic.
122///
123/// # Example
124///
125/// If `buffer` was created with [`BufferUsages::MAP_WRITE`], we could fill it
126/// with `f32` values like this:
127///
128/// ```
129/// # #[cfg(feature = "noop")]
130/// # let (device, _queue) = wgpu::Device::noop(&wgpu::DeviceDescriptor::default());
131/// # #[cfg(not(feature = "noop"))]
132/// # let device: wgpu::Device = { return; };
133/// #
134/// # let buffer = device.create_buffer(&wgpu::BufferDescriptor {
135/// #     label: None,
136/// #     size: 400,
137/// #     usage: wgpu::BufferUsages::MAP_WRITE,
138/// #     mapped_at_creation: false,
139/// # });
140/// let capturable = buffer.clone();
141/// buffer.map_async(wgpu::MapMode::Write, .., move |result| {
142///     if result.is_ok() {
143///         let mut view = capturable.get_mapped_range_mut(..).unwrap();
144///         let mut floats: wgpu::WriteOnly<[[u8; 4]]> = view.slice(..).into_chunks::<4>().0;
145///         floats.fill(42.0f32.to_ne_bytes());
146///         drop(view);
147///         capturable.unmap();
148///     }
149/// });
150/// ```
151///
152/// This code takes the following steps:
153///
154/// - First, it makes a cloned handle to the buffer for capture by
155///   the callback passed to [`map_async`]. Since a [`map_async`] callback may be
156///   invoked from another thread, interaction between the callback and the
157///   thread calling [`map_async`] generally requires some sort of shared heap
158///   data like this. In real code, there might be an [`Arc`] to some larger
159///   structure that itself owns `buffer`.
160///
161/// - Then, it calls [`Buffer::slice`] to make a [`BufferSlice`] referring to
162///   the buffer's entire contents.
163///
164/// - Next, it calls [`BufferSlice::map_async`] to request that the bytes to
165///   which the slice refers be made accessible to the CPU ("mapped"). This may
166///   entail waiting for previously enqueued operations on `buffer` to finish.
167///   Although [`map_async`] itself always returns immediately, it saves the
168///   callback function to be invoked later.
169///
170/// - When some later call to [`Device::poll`] or [`Instance::poll_all`] (not
171///   shown in this example) determines that the buffer is mapped and ready for
172///   the CPU to use, it invokes the callback function.
173///
174/// - The callback function calls [`Buffer::slice`] and then
175///   [`BufferSlice::get_mapped_range_mut`] to obtain a [`BufferViewMut`], which
176///   dereferences to a `&mut [u8]` slice referring to the buffer's bytes.
177///
178/// - It then uses the [`bytemuck`] crate to turn the `&mut [u8]` into a `&mut
179///   [f32]`, and calls the slice [`fill`] method to fill the buffer with a
180///   useful value.
181///
182/// - Finally, the callback drops the view and calls [`Buffer::unmap`] to unmap
183///   the buffer. In real code, the callback would also need to do some sort of
184///   synchronization to let the rest of the program know that it has completed
185///   its work.
186///
187/// If using [`map_async`] directly is awkward, you may find it more convenient to
188/// use [`Queue::write_buffer`] and [`util::DownloadBuffer::read_buffer`].
189/// However, those each have their own tradeoffs; the asynchronous nature of GPU
190/// execution makes it hard to avoid friction altogether.
191///
192/// [`Arc`]: std::sync::Arc
193/// [`map_async`]: BufferSlice::map_async
194/// [`bytemuck`]: https://crates.io/crates/bytemuck
195/// [`fill`]: slice::fill
196///
197/// ## Mapping buffers on the web
198///
199/// When compiled to WebAssembly and running in a browser content process,
200/// `wgpu` implements its API in terms of the browser's WebGPU implementation.
201/// In this context, `wgpu` is further isolated from the GPU:
202///
203/// - Depending on the browser's WebGPU implementation, mapping and unmapping
204///   buffers probably entails copies between WebAssembly linear memory and the
205///   graphics driver's buffers.
206///
207/// - All modern web browsers isolate web content in its own sandboxed process,
208///   which can only interact with the GPU via interprocess communication (IPC).
209///   Although most browsers' IPC systems use shared memory for large data
210///   transfers, there will still probably need to be copies into and out of the
211///   shared memory buffers.
212///
213/// All of these copies contribute to the cost of buffer mapping in this
214/// configuration.
215///
216/// [`usage`]: BufferDescriptor::usage
217/// [mac]: BufferDescriptor::mapped_at_creation
218/// [`MAP_READ`]: BufferUsages::MAP_READ
219/// [`MAP_WRITE`]: BufferUsages::MAP_WRITE
220/// [`DeviceExt::create_buffer_init()`]: util::DeviceExt::create_buffer_init
221#[derive(Debug, Clone)]
222pub struct Buffer {
223    pub(crate) inner: dispatch::DispatchBuffer,
224    pub(crate) map_context: Arc<Mutex<MapContext>>,
225    // Todo: missing map_state https://www.w3.org/TR/webgpu/#dom-gpubuffer-mapstate
226}
227#[cfg(send_sync)]
228static_assertions::assert_impl_all!(Buffer: Send, Sync);
229
230crate::cmp::impl_eq_ord_hash_proxy!(Buffer => .inner);
231
232impl Buffer {
233    /// Return the binding view of the entire buffer.
234    pub fn as_entire_binding(&self) -> BindingResource<'_> {
235        BindingResource::Buffer(self.as_entire_buffer_binding())
236    }
237
238    /// Return the binding view of the entire buffer.
239    pub fn as_entire_buffer_binding(&self) -> BufferBinding<'_> {
240        BufferBinding {
241            buffer: self,
242            offset: 0,
243            size: None,
244        }
245    }
246
247    /// Get the [`wgpu_hal`] buffer from this `Buffer`.
248    ///
249    /// Find the Api struct corresponding to the active backend in [`wgpu_hal::api`],
250    /// and pass that struct to the to the `A` type parameter.
251    ///
252    /// Returns a guard that dereferences to the type of the hal backend
253    /// which implements [`A::Buffer`].
254    ///
255    /// # Types
256    ///
257    /// The returned type depends on the backend:
258    ///
259    #[doc = crate::macros::hal_type_vulkan!("Buffer")]
260    #[doc = crate::macros::hal_type_metal!("Buffer")]
261    #[doc = crate::macros::hal_type_dx12!("Buffer")]
262    #[doc = crate::macros::hal_type_gles!("Buffer")]
263    ///
264    /// # Deadlocks
265    ///
266    /// - The returned guard holds a read-lock on a device-local "destruction"
267    ///   lock, which will cause all calls to `destroy` to block until the
268    ///   guard is released.
269    ///
270    /// # Errors
271    ///
272    /// This method will return None if:
273    /// - The buffer is not from the backend specified by `A`.
274    /// - The buffer is from [`Backend::BrowserWebGpu`].
275    ///   (Use `Buffer::as_webgpu()` instead.)
276    /// - The buffer is from a custom backend.
277    /// - The buffer has had [`Self::destroy()`] called on it.
278    ///
279    /// # Safety
280    ///
281    /// - The returned resource must not be destroyed unless the guard
282    ///   is the last reference to it and it is not in use by the GPU.
283    ///   The guard and handle may be dropped at any time however.
284    /// - All the safety requirements of wgpu-hal must be upheld.
285    ///
286    /// [`A::Buffer`]: hal::Api::Buffer
287    #[cfg(wgpu_core)]
288    pub unsafe fn as_hal<A: hal::Api>(
289        &self,
290    ) -> Option<impl core::ops::Deref<Target = A::Buffer> + WasmNotSendSync> {
291        let buffer = self.inner.as_core_opt()?;
292        unsafe { buffer.as_hal::<A>() }
293    }
294
295    /// Returns a [`BufferSlice`] referring to the portion of `self`'s contents
296    /// indicated by `bounds`. Regardless of what sort of data `self` stores,
297    /// `bounds` start and end are given in bytes.
298    ///
299    /// A [`BufferSlice`] can be used to supply vertex and index data, or to map
300    /// buffer contents for access from the CPU. See the [`BufferSlice`]
301    /// documentation for details.
302    ///
303    /// The `range` argument can be half or fully unbounded: for example,
304    /// `buffer.slice(..)` refers to the entire buffer, and `buffer.slice(n..)`
305    /// refers to the portion starting at the `n`th byte and extending to the
306    /// end of the buffer.
307    ///
308    /// # Panics
309    ///
310    /// - If `bounds` is outside of the bounds of `self`.
311    #[track_caller]
312    pub fn slice<S: RangeBounds<BufferAddress>>(&self, bounds: S) -> BufferSlice<'_> {
313        let (offset, size) = range_to_offset_size(bounds, self.size());
314        check_buffer_bounds(self.size(), offset, size);
315        BufferSlice {
316            buffer: self,
317            offset,
318            size,
319        }
320    }
321
322    /// Unmaps the buffer from host memory.
323    ///
324    /// This terminates the effect of all previous [`map_async()`](Self::map_async) operations and
325    /// makes the buffer available for use by the GPU again.
326    pub fn unmap(&self) {
327        self.map_context.lock().reset();
328        self.inner.unmap();
329    }
330
331    /// Destroy the associated native resources as soon as possible.
332    pub fn destroy(&self) {
333        self.inner.destroy();
334    }
335
336    /// Returns the length of the buffer allocation in bytes.
337    ///
338    /// This is always equal to the `size` that was specified when creating the buffer.
339    pub fn size(&self) -> BufferAddress {
340        self.inner.size()
341    }
342
343    /// Returns the allowed usages for this `Buffer`.
344    ///
345    /// This is always equal to the `usage` that was specified when creating the buffer.
346    pub fn usage(&self) -> BufferUsages {
347        self.inner.usage()
348    }
349
350    /// Map the buffer to host (CPU) memory, making it available for reading or writing via
351    /// [`get_mapped_range()`](Self::get_mapped_range). The buffer becomes accessible once the
352    /// `callback` is invoked with [`Ok`].
353    ///
354    /// Use this when you want to map the buffer immediately. If you need to submit GPU work that
355    /// uses the buffer before mapping it, use `map_buffer_on_submit` on
356    /// [`CommandEncoder`][CEmbos], [`CommandBuffer`][CBmbos], [`RenderPass`][RPmbos], or
357    /// [`ComputePass`][CPmbos] to schedule the mapping after submission. This avoids extra calls to
358    /// [`Buffer::map_async()`] or [`BufferSlice::map_async()`] and lets you initiate mapping from a
359    /// more convenient place.
360    ///
361    /// For the callback to run, either [`queue.submit(..)`][q::s], [`instance.poll_all(..)`][i::p_a],
362    /// or [`device.poll(..)`][d::p] must be called elsewhere in the runtime, possibly integrated into
363    /// an event loop or run on a separate thread.
364    ///
365    /// The callback runs on the thread that first calls one of the above functions after the GPU work
366    /// completes. There are no restrictions on the code you can run in the callback; however, on native
367    /// the polling call will not return until the callback finishes, so keep callbacks short (set flags,
368    /// send messages, etc.).
369    ///
370    /// While a buffer is mapped, it cannot be used by other commands; at any time, either the GPU or
371    /// the CPU has exclusive access to the buffer’s contents.
372    ///
373    /// This can also be performed using [`BufferSlice::map_async()`].
374    ///
375    /// # Panics
376    ///
377    /// - If the buffer is already mapped.
378    /// - If the buffer’s [`BufferUsages`] do not allow the requested [`MapMode`].
379    /// - If `bounds` is outside of the bounds of `self`.
380    /// - If `bounds` does not start at a multiple of [`MAP_ALIGNMENT`].
381    /// - If `bounds` has a length that is not a multiple of 4 greater than 0.
382    ///
383    /// [CEmbos]: CommandEncoder::map_buffer_on_submit
384    /// [CBmbos]: CommandBuffer::map_buffer_on_submit
385    /// [RPmbos]: RenderPass::map_buffer_on_submit
386    /// [CPmbos]: ComputePass::map_buffer_on_submit
387    /// [q::s]: Queue::submit
388    /// [i::p_a]: Instance::poll_all
389    /// [d::p]: Device::poll
390    pub fn map_async<S: RangeBounds<BufferAddress>>(
391        &self,
392        mode: MapMode,
393        bounds: S,
394        callback: impl FnOnce(Result<(), BufferAsyncError>) + WasmNotSend + 'static,
395    ) {
396        self.slice(bounds).map_async(mode, callback)
397    }
398
399    /// Gain read-only access to the bytes of a [mapped] [`Buffer`].
400    ///
401    /// Returns a [`BufferView`] referring to the buffer range represented by
402    /// `self`. See the documentation for [`BufferView`] for details.
403    ///
404    /// `bounds` may be less than the bounds passed to [`Self::map_async()`],
405    /// and multiple views may be obtained and used simultaneously as long as they do not overlap.
406    ///
407    /// This can also be performed using [`BufferSlice::get_mapped_range()`].
408    ///
409    /// # Errors
410    ///
411    /// - If `bounds` is outside of the bounds of `self`.
412    /// - If `bounds` does not start at a multiple of [`MAP_ALIGNMENT`].
413    /// - If `bounds` has a length that is not a multiple of 4 greater than 0.
414    /// - If the buffer to which `self` refers is not currently [mapped].
415    /// - If you try to create a view which overlaps an existing [`BufferViewMut`].
416    ///
417    /// [mapped]: Buffer#mapping-buffers
418    #[track_caller]
419    pub fn get_mapped_range<S: RangeBounds<BufferAddress>>(
420        &self,
421        bounds: S,
422    ) -> Result<BufferView, MapRangeError> {
423        self.slice(bounds).get_mapped_range()
424    }
425
426    /// Gain write access to the bytes of a [mapped] [`Buffer`].
427    ///
428    /// Returns a [`BufferViewMut`] referring to the buffer range represented by
429    /// `self`. See the documentation for [`BufferViewMut`] for more details.
430    ///
431    /// `bounds` may be less than the bounds passed to [`Self::map_async()`],
432    /// and multiple views may be obtained and used simultaneously as long as they do not overlap.
433    ///
434    /// This can also be performed using [`BufferSlice::get_mapped_range_mut()`].
435    ///
436    /// # Errors
437    ///
438    /// - If `bounds` is outside of the bounds of `self`.
439    /// - If `bounds` does not start at a multiple of [`MAP_ALIGNMENT`].
440    /// - If `bounds` has a length that is not a multiple of 4 greater than 0.
441    /// - If the buffer to which `self` refers is not currently [mapped].
442    /// - If you try to create a view which overlaps an existing [`BufferView`] or [`BufferViewMut`].
443    ///
444    /// [mapped]: Buffer#mapping-buffers
445    #[track_caller]
446    pub fn get_mapped_range_mut<S: RangeBounds<BufferAddress>>(
447        &self,
448        bounds: S,
449    ) -> Result<BufferViewMut, MapRangeError> {
450        self.slice(bounds).get_mapped_range_mut()
451    }
452
453    #[cfg(custom)]
454    /// Returns custom implementation of Buffer (if custom backend and is internally T)
455    pub fn as_custom<T: custom::BufferInterface>(&self) -> Option<&T> {
456        self.inner.as_custom()
457    }
458
459    /// Returns the underlying [`webgpu::GpuBuffer`] handle if this `Buffer`
460    /// is on the WebGPU backend, otherwise `None`.
461    #[cfg(webgpu)]
462    pub fn as_webgpu(&self) -> Option<&webgpu::GpuBuffer> {
463        self.inner.as_webgpu_opt().map(|wb| &wb.inner)
464    }
465}
466
467#[cfg(wgpu_core)]
468impl Buffer {
469    /// Create a new buffer of wgpu from a wgpu-core buffer.
470    ///
471    /// # Arguments
472    ///
473    /// - `core_buffer` - wgpu-core buffer.
474    ///
475    /// # Safety
476    ///
477    /// The caller must ensure that the current state of the wgpu-core buffer is compatible with the provided `mapped_range`.
478    /// Changes to the wgpu-core buffer's state after this call may lead to undefined behavior if they are not compatible with the provided `mapped_range`.
479    pub unsafe fn from_core(
480        core_buffer: alloc::sync::Arc<wgc::resource::Buffer>,
481        mapped_range: Option<Range<BufferAddress>>,
482    ) -> Self {
483        Self {
484            inner: crate::backend::wgpu_core::CoreBuffer::from_core(core_buffer).into(),
485            map_context: Arc::new(Mutex::new(MapContext::new(mapped_range))),
486        }
487    }
488
489    /// Returns the underlying wgpu-core buffer if this `Buffer` is on the wgpu-core backend, otherwise `None`.
490    ///
491    /// # Safety
492    ///
493    /// Returning the underlying wgpu-core buffer allows for direct manipulation of the buffer's state,
494    /// which can lead to undefined behavior if not done carefully.
495    /// The caller must ensure that any operations performed on the returned buffer are compatible with the current state of the `Buffer` and its mapping context
496    /// or not use this buffer after calling this function.
497    pub unsafe fn as_core(&self) -> Option<alloc::sync::Arc<wgc::resource::Buffer>> {
498        self.inner.as_core_opt().map(|cd| cd.as_core())
499    }
500}
501
502/// A slice of a [`Buffer`], to be mapped, used for vertex or index data, or the like.
503///
504/// You can create a `BufferSlice` by calling [`Buffer::slice`]:
505///
506/// ```no_run
507/// # let buffer: wgpu::Buffer = todo!();
508/// let slice = buffer.slice(10..20);
509/// ```
510///
511/// This returns a slice referring to the second ten bytes of `buffer`. To get a
512/// slice of the entire `Buffer`:
513///
514/// ```no_run
515/// # let buffer: wgpu::Buffer = todo!();
516/// let whole_buffer_slice = buffer.slice(..);
517/// ```
518///
519/// You can pass buffer slices to methods like [`RenderPass::set_vertex_buffer`]
520/// and [`RenderPass::set_index_buffer`] to indicate which portion of the buffer
521/// a draw call should consult. You can also convert it to a [`BufferBinding`]
522/// with `.try_into()`, which fails if the slice length is 0.
523///
524/// To access the slice's contents on the CPU, you must first [map] the buffer,
525/// and then call [`BufferSlice::get_mapped_range`] or
526/// [`BufferSlice::get_mapped_range_mut`] to obtain a view of the slice's
527/// contents. See the documentation on [mapping][map] for more details,
528/// including example code.
529///
530/// Unlike a Rust shared slice `&[T]`, whose existence guarantees that
531/// nobody else is modifying the `T` values to which it refers, a
532/// [`BufferSlice`] doesn't guarantee that the buffer's contents aren't
533/// changing. You can still record and submit commands operating on the
534/// buffer while holding a [`BufferSlice`]. A [`BufferSlice`] simply
535/// represents a certain range of the buffer's bytes.
536///
537/// The `BufferSlice` type is unique to the Rust API of `wgpu`. In the WebGPU
538/// specification, an offset and size are specified as arguments to each call
539/// working with the [`Buffer`], instead.
540///
541/// [map]: Buffer#mapping-buffers
542#[derive(Copy, Clone, Debug, PartialEq)]
543pub struct BufferSlice<'a> {
544    pub(crate) buffer: &'a Buffer,
545    pub(crate) offset: BufferAddress,
546    pub(crate) size: BufferAddress,
547}
548#[cfg(send_sync)]
549static_assertions::assert_impl_all!(BufferSlice<'_>: Send, Sync);
550
551impl<'a> BufferSlice<'a> {
552    /// Return another [`BufferSlice`] referring to the portion of `self`'s contents
553    /// indicated by `bounds`.
554    ///
555    /// The `range` argument can be half or fully unbounded: for example,
556    /// `buffer.slice(..)` refers to the entire buffer, and `buffer.slice(n..)`
557    /// refers to the portion starting at the `n`th byte and extending to the
558    /// end of the buffer.
559    ///
560    /// # Panics
561    ///
562    /// - If `bounds` is outside of the bounds of `self`.
563    #[track_caller]
564    pub fn slice<S: RangeBounds<BufferAddress>>(&self, bounds: S) -> BufferSlice<'a> {
565        let (offset, size) = range_to_offset_size(bounds, self.size);
566        check_buffer_bounds(self.size, offset, size);
567        BufferSlice {
568            buffer: self.buffer,
569            offset: self.offset + offset, // check_buffer_bounds ensures this does not overflow
570            size,                         // check_buffer_bounds ensures this is essentially min()
571        }
572    }
573
574    /// Map the buffer to host (CPU) memory, making it available for reading or writing via
575    /// [`get_mapped_range()`](Self::get_mapped_range). The buffer becomes accessible once the
576    /// `callback` is invoked with [`Ok`].
577    ///
578    /// Use this when you want to map the buffer immediately. If you need to submit GPU work that
579    /// uses the buffer before mapping it, use `map_buffer_on_submit` on
580    /// [`CommandEncoder`][CEmbos], [`CommandBuffer`][CBmbos], [`RenderPass`][RPmbos], or
581    /// [`ComputePass`][CPmbos] to schedule the mapping after submission. This avoids extra calls to
582    /// [`Buffer::map_async()`] or [`BufferSlice::map_async()`] and lets you initiate mapping from a
583    /// more convenient place.
584    ///
585    /// For the callback to run, either [`queue.submit(..)`][q::s], [`instance.poll_all(..)`][i::p_a],
586    /// or [`device.poll(..)`][d::p] must be called elsewhere in the runtime, possibly integrated into
587    /// an event loop or run on a separate thread.
588    ///
589    /// The callback runs on the thread that first calls one of the above functions after the GPU work
590    /// completes. There are no restrictions on the code you can run in the callback; however, on native
591    /// the polling call will not return until the callback finishes, so keep callbacks short (set flags,
592    /// send messages, etc.).
593    ///
594    /// While a buffer is mapped, it cannot be used by other commands; at any time, either the GPU or
595    /// the CPU has exclusive access to the buffer’s contents.
596    ///
597    /// This can also be performed using [`Buffer::map_async()`].
598    ///
599    /// # Panics
600    ///
601    /// - If the buffer’s [`BufferUsages`] do not allow the requested [`MapMode`].
602    /// - If the beginning of this slice is not aligned to [`MAP_ALIGNMENT`] within the buffer.
603    /// - If the length of this slice is not a multiple of 4.
604    ///
605    /// [CEmbos]: CommandEncoder::map_buffer_on_submit
606    /// [CBmbos]: CommandBuffer::map_buffer_on_submit
607    /// [RPmbos]: RenderPass::map_buffer_on_submit
608    /// [CPmbos]: ComputePass::map_buffer_on_submit
609    /// [q::s]: Queue::submit
610    /// [i::p_a]: Instance::poll_all
611    /// [d::p]: Device::poll
612    pub fn map_async(
613        &self,
614        mode: MapMode,
615        callback: impl FnOnce(Result<(), BufferAsyncError>) + WasmNotSend + 'static,
616    ) {
617        let mut mc = self.buffer.map_context.lock();
618        if mc.mapped_range.is_some() {
619            // Buffer is already mapped; fail
620            drop(mc);
621            callback(Err(BufferAsyncError));
622            return;
623        }
624
625        let end = self.offset + self.size;
626        mc.mapped_range = Some(self.offset..end);
627        drop(mc); // release the lock of map_context as callback can call lock it again
628
629        self.buffer
630            .inner
631            .map_async(mode, self.offset..end, Box::new(callback));
632    }
633
634    /// Gain read-only access to the bytes of a [mapped] [`Buffer`].
635    ///
636    /// Returns a [`BufferView`] referring to the buffer range represented by
637    /// `self`. See the documentation for [`BufferView`] for details.
638    ///
639    /// Multiple views may be obtained and used simultaneously as long as they are from
640    /// non-overlapping slices.
641    ///
642    /// This can also be performed using [`Buffer::get_mapped_range()`].
643    ///
644    /// # Errors
645    ///
646    /// - If the beginning of this slice is not aligned to [`MAP_ALIGNMENT`] within the buffer.
647    /// - If the length of this slice is not a multiple of 4.
648    /// - If the buffer to which `self` refers is not currently [mapped].
649    /// - If you try to create a view which overlaps an existing [`BufferViewMut`].
650    ///
651    /// [mapped]: Buffer#mapping-buffers
652    #[track_caller]
653    pub fn get_mapped_range(&self) -> Result<BufferView, MapRangeError> {
654        let subrange = Subrange::new(self.offset, self.size, RangeMappingKind::Immutable);
655        let range = self.buffer.inner.get_mapped_range(subrange.index.clone())?;
656        self.buffer.map_context.lock().validate_and_add(subrange)?;
657        Ok(BufferView {
658            buffer: self.buffer.clone(),
659            size: self.size,
660            offset: self.offset,
661            inner: range,
662        })
663    }
664
665    /// Gain write-only access to the bytes of a [mapped] [`Buffer`].
666    ///
667    /// Returns a [`BufferViewMut`] referring to the buffer range represented by
668    /// `self`. See the documentation for [`BufferViewMut`] for more details.
669    ///
670    /// Multiple views may be obtained and used simultaneously as long as they are from
671    /// non-overlapping slices.
672    ///
673    /// This can also be performed using [`Buffer::get_mapped_range_mut()`].
674    ///
675    /// # Errors
676    ///
677    /// - If the beginning of this slice is not aligned to [`MAP_ALIGNMENT`] within the buffer.
678    /// - If the length of this slice is not a multiple of 4.
679    /// - If the buffer to which `self` refers is not currently [mapped].
680    /// - If you try to create a view which overlaps an existing [`BufferView`] or [`BufferViewMut`].
681    ///
682    /// [mapped]: Buffer#mapping-buffers
683    #[track_caller]
684    pub fn get_mapped_range_mut(&self) -> Result<BufferViewMut, MapRangeError> {
685        let subrange = Subrange::new(self.offset, self.size, RangeMappingKind::Mutable);
686        let range = self.buffer.inner.get_mapped_range(subrange.index.clone())?;
687        self.buffer.map_context.lock().validate_and_add(subrange)?;
688        Ok(BufferViewMut {
689            buffer: self.buffer.clone(),
690            size: self.size,
691            offset: self.offset,
692            inner: range,
693        })
694    }
695
696    /// Returns the buffer this is a slice of.
697    ///
698    /// You should usually not need to call this, and if you received the buffer from code you
699    /// do not control, you should refrain from accessing the buffer outside the bounds of the
700    /// slice. Nevertheless, it’s possible to get this access, so this method makes it simple.
701    pub fn buffer(&self) -> &'a Buffer {
702        self.buffer
703    }
704
705    /// Returns the offset in [`Self::buffer()`] this slice starts at.
706    pub fn offset(&self) -> BufferAddress {
707        self.offset
708    }
709
710    /// Returns the size of this slice.
711    pub fn size(&self) -> BufferAddress {
712        self.size
713    }
714}
715
716impl<'a> TryFrom<BufferSlice<'a>> for crate::BufferBinding<'a> {
717    type Error = ();
718
719    /// Convert a [`BufferSlice`] to an equivalent [`BufferBinding`],
720    /// provided that it will be used without a dynamic offset.
721    fn try_from(value: BufferSlice<'a>) -> Result<Self, Self::Error> {
722        Ok(BufferBinding {
723            buffer: value.buffer,
724            offset: value.offset,
725            size: Some(NonZero::new(value.size()).ok_or(())?),
726        })
727    }
728}
729
730impl<'a> TryFrom<BufferSlice<'a>> for crate::BindingResource<'a> {
731    type Error = ();
732
733    /// Convert a [`BufferSlice`] to an equivalent [`BindingResource::Buffer`],
734    /// provided that it will be used without a dynamic offset.
735    fn try_from(value: BufferSlice<'a>) -> Result<Self, Self::Error> {
736        Ok(crate::BindingResource::Buffer(
737            crate::BufferBinding::try_from(value)?,
738        ))
739    }
740}
741
742fn range_overlaps(a: &Range<BufferAddress>, b: &Range<BufferAddress>) -> bool {
743    a.start < b.end && b.start < a.end
744}
745
746fn range_contains(a: &Range<BufferAddress>, b: &Range<BufferAddress>) -> bool {
747    a.start <= b.start && a.end >= b.end
748}
749
750#[derive(Debug, Copy, Clone)]
751enum RangeMappingKind {
752    Mutable,
753    Immutable,
754}
755
756impl RangeMappingKind {
757    /// Returns true if a range of this kind can touch the same bytes as a range of the other kind.
758    ///
759    /// This is Rust's Mutable XOR Shared rule.
760    fn allowed_concurrently_with(self, other: Self) -> bool {
761        matches!(
762            (self, other),
763            (RangeMappingKind::Immutable, RangeMappingKind::Immutable)
764        )
765    }
766}
767
768#[derive(Debug, Clone)]
769struct Subrange {
770    index: Range<BufferAddress>,
771    kind: RangeMappingKind,
772}
773
774impl Subrange {
775    fn new(offset: BufferAddress, size: BufferAddress, kind: RangeMappingKind) -> Self {
776        Self {
777            index: offset..(offset + size),
778            kind,
779        }
780    }
781}
782
783impl fmt::Display for Subrange {
784    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
785        write!(
786            f,
787            "{}..{} ({:?})",
788            self.index.start, self.index.end, self.kind
789        )
790    }
791}
792
793/// The mapped portion of a buffer, if any, and its outstanding views.
794///
795/// This ensures that views fall within the mapped range and don't overlap.
796#[derive(Debug)]
797pub(crate) struct MapContext {
798    /// The range of the buffer that is mapped.
799    ///
800    /// This becomes Some(...) when the buffer is mapped at creation time, and
801    /// when you call `map_async` on some [`BufferSlice`] (so technically, it
802    /// indicates the portion that is *or has been requested to be* mapped.)
803    ///
804    /// All [`BufferView`]s and [`BufferViewMut`]s must fall within this range.
805    mapped_range: Option<Range<BufferAddress>>,
806
807    /// The ranges covered by all outstanding [`BufferView`]s and
808    /// [`BufferViewMut`]s. These are non-overlapping, and are all contained
809    /// within `mapped_range`.
810    sub_ranges: Vec<Subrange>,
811}
812
813impl MapContext {
814    /// Creates a new `MapContext`.
815    ///
816    /// For [`mapped_at_creation`] buffers, pass the full buffer range in the
817    /// `mapped_range` argument. For other buffers, pass `None`.
818    ///
819    /// [`mapped_at_creation`]: BufferDescriptor::mapped_at_creation
820    pub(crate) fn new(mapped_range: Option<Range<BufferAddress>>) -> Self {
821        Self {
822            mapped_range,
823            sub_ranges: Vec::new(),
824        }
825    }
826
827    /// Record that the buffer is no longer mapped.
828    fn reset(&mut self) {
829        self.mapped_range = None;
830
831        assert!(
832            self.sub_ranges.is_empty(),
833            "You cannot unmap a buffer that still has accessible mapped views"
834        );
835    }
836
837    /// Record that the `size` bytes of the buffer at `offset` are now viewed.
838    ///
839    /// # Errors
840    ///
841    /// This returns an error if the given range is invalid.
842    fn validate_and_add(&mut self, new_sub: Subrange) -> Result<(), MapRangeError> {
843        if self.mapped_range.is_none() {
844            return Err(MapRangeError(
845                "tried to call get_mapped_range(_mut) on an unmapped buffer".into(),
846            ));
847        }
848        let mapped_range = self.mapped_range.as_ref().unwrap();
849        if !range_contains(mapped_range, &new_sub.index) {
850            return Err(MapRangeError(alloc::format!(
851                "tried to call get_mapped_range(_mut) on a range that is not entirely mapped. \
852                 Attempted to get range {}, but the mapped range is {}..{}",
853                new_sub,
854                mapped_range.start,
855                mapped_range.end
856            )));
857        }
858        // This check is essential for avoiding undefined behavior: it is the
859        // only thing that ensures that `&mut` references to the buffer's
860        // contents don't alias anything else.
861        for sub in self.sub_ranges.iter() {
862            if range_overlaps(&sub.index, &new_sub.index)
863                && !sub.kind.allowed_concurrently_with(new_sub.kind)
864            {
865                return Err(MapRangeError(alloc::format!(
866                    "tried to call get_mapped_range(_mut) on a range that has already \
867                     been mapped and would break Rust memory aliasing rules. Attempted \
868                     to get range {}, and the conflicting range is {}",
869                    new_sub,
870                    sub
871                )));
872            }
873        }
874        self.sub_ranges.push(new_sub);
875        Ok(())
876    }
877
878    /// Record that the `size` bytes of the buffer at `offset` are no longer viewed.
879    ///
880    /// # Panics
881    ///
882    /// This panics if the given range does not exactly match one previously
883    /// passed to [`MapContext::validate_and_add`].
884    pub(crate) fn remove(&mut self, offset: BufferAddress, size: BufferAddress) {
885        let end = offset + size;
886
887        let index = self
888            .sub_ranges
889            .iter()
890            .position(|r| r.index == (offset..end))
891            .expect("unable to remove range from map context");
892        self.sub_ranges.swap_remove(index);
893    }
894}
895
896/// Describes a [`Buffer`].
897///
898/// For use with [`Device::create_buffer`].
899///
900/// Corresponds to [WebGPU `GPUBufferDescriptor`](
901/// https://gpuweb.github.io/gpuweb/#dictdef-gpubufferdescriptor).
902pub type BufferDescriptor<'a> = wgt::BufferDescriptor<Label<'a>>;
903static_assertions::assert_impl_all!(BufferDescriptor<'_>: Send, Sync);
904
905/// Error occurred when trying to async map a buffer.
906#[derive(Clone, PartialEq, Eq, Debug)]
907pub struct BufferAsyncError;
908static_assertions::assert_impl_all!(BufferAsyncError: Send, Sync);
909
910impl fmt::Display for BufferAsyncError {
911    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
912        write!(f, "Error occurred when trying to async map a buffer")
913    }
914}
915
916impl error::Error for BufferAsyncError {}
917
918/// Error returned by [`BufferSlice::get_mapped_range`] and [`BufferSlice::get_mapped_range_mut`].
919///
920/// Corresponds to the `OperationError` thrown by
921/// [`getMappedRange()`](https://gpuweb.github.io/gpuweb/#dom-gpubuffer-getmappedrange)
922/// in the WebGPU spec.
923#[derive(Clone, Debug)]
924pub struct MapRangeError(pub(crate) String);
925static_assertions::assert_impl_all!(MapRangeError: Send, Sync);
926
927impl fmt::Display for MapRangeError {
928    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
929        write!(f, "Buffer view error: {}", self.0)
930    }
931}
932
933impl error::Error for MapRangeError {}
934
935/// A read-only view of a mapped buffer's bytes.
936///
937/// To get a `BufferView`, first [map] the buffer, and then
938/// call `buffer.slice(range).get_mapped_range()`.
939///
940/// `BufferView` dereferences to `&[u8]`, so you can use all the usual Rust
941/// slice methods to access the buffer's contents. It also implements
942/// `AsRef<[u8]>`, if that's more convenient.
943///
944/// Before the buffer can be unmapped, all `BufferView`s observing it
945/// must be dropped. Otherwise, the call to [`Buffer::unmap`] will panic.
946///
947/// For example code, see the documentation on [mapping buffers][map].
948///
949/// [map]: Buffer#mapping-buffers
950/// [`map_async`]: BufferSlice::map_async
951#[derive(Debug)]
952pub struct BufferView {
953    // `buffer, offset, size` are similar to `BufferSlice`, except that they own the buffer.
954    buffer: Buffer,
955    offset: BufferAddress,
956    size: BufferAddress,
957    inner: dispatch::DispatchBufferMappedRange,
958}
959
960/// A write-only view of a mapped buffer's bytes.
961///
962/// To get a `BufferViewMut`, first [map] the buffer, and then
963/// call `buffer.slice(range).get_mapped_range_mut()`.
964///
965/// Because Rust has no write-only reference type
966/// (`&[u8]` is read-only and `&mut [u8]` is read-write),
967/// this type does not dereference to a slice in the way that [`BufferView`] does.
968/// Instead, [`.slice()`][BufferViewMut::slice] returns a special [`WriteOnly`] pointer type,
969/// and there are also a few convenience methods such as [`BufferViewMut::copy_from_slice()`].
970///
971/// Before the buffer can be unmapped, all `BufferViewMut`s observing it
972/// must be dropped. Otherwise, the call to [`Buffer::unmap`] will panic.
973///
974/// For example code, see the documentation on [mapping buffers][map].
975///
976/// [map]: Buffer#mapping-buffers
977#[derive(Debug)]
978pub struct BufferViewMut {
979    // `buffer, offset, size` are similar to `BufferSlice`, except that they own the buffer.
980    buffer: Buffer,
981    offset: BufferAddress,
982    size: BufferAddress,
983    inner: dispatch::DispatchBufferMappedRange,
984}
985
986// `BufferView` simply dereferences. `BufferViewMut` cannot, because mapped memory may be
987// write-combining memory <https://en.wikipedia.org/wiki/Write_combining>,
988// and not support the expected behavior of atomic accesses.
989// Further context: <https://github.com/gfx-rs/wgpu/issues/8897>
990
991impl core::ops::Deref for BufferView {
992    type Target = [u8];
993
994    #[inline]
995    fn deref(&self) -> &[u8] {
996        // SAFETY: this is a read mapping
997        unsafe { self.inner.read_slice() }
998    }
999}
1000
1001impl AsRef<[u8]> for BufferView {
1002    #[inline]
1003    fn as_ref(&self) -> &[u8] {
1004        self
1005    }
1006}
1007
1008impl Drop for BufferView {
1009    fn drop(&mut self) {
1010        self.buffer
1011            .map_context
1012            .lock()
1013            .remove(self.offset, self.size);
1014    }
1015}
1016
1017impl Drop for BufferViewMut {
1018    fn drop(&mut self) {
1019        self.buffer
1020            .map_context
1021            .lock()
1022            .remove(self.offset, self.size);
1023    }
1024}
1025
1026#[cfg(webgpu)]
1027impl BufferView {
1028    /// Provides the same data as dereferencing the view, but as a `Uint8Array` in js.
1029    /// This can be MUCH faster than dereferencing the view which copies the data into
1030    /// the Rust / wasm heap.
1031    pub fn as_uint8array(&self) -> &js_sys::Uint8Array {
1032        self.inner.as_uint8array()
1033    }
1034}
1035
1036/// These methods are equivalent to the methods of the same names on [`WriteOnly`].
1037impl BufferViewMut {
1038    /// Returns the length of this view; the number of bytes to be written.
1039    pub fn len(&self) -> usize {
1040        // cannot fail because we can't actually map more than isize::MAX bytes
1041        usize::try_from(self.size).unwrap()
1042    }
1043
1044    /// Returns `true` if the view has a length of 0.
1045    ///
1046    /// Note that this is currently impossible.
1047    pub fn is_empty(&self) -> bool {
1048        self.len() == 0
1049    }
1050
1051    /// Returns a [`WriteOnly`] reference to a portion of this.
1052    ///
1053    /// `.slice(..)` can be used to access the whole data.
1054    pub fn slice<'a, S: RangeBounds<usize>>(&'a mut self, bounds: S) -> WriteOnly<'a, [u8]> {
1055        // SAFETY: this is a write mapping
1056        unsafe { self.inner.write_slice() }.into_slice(bounds)
1057    }
1058
1059    /// Copies all elements from src into `self`.
1060    ///
1061    /// The length of `src` must be the same as `self`.
1062    ///
1063    /// This method is equivalent to
1064    /// [`self.slice(..).copy_from_slice(src)`][WriteOnly::copy_from_slice].
1065    pub fn copy_from_slice(&mut self, src: &[u8]) {
1066        self.slice(..).copy_from_slice(src)
1067    }
1068}
1069
1070#[track_caller]
1071fn check_buffer_bounds(
1072    whole_size: BufferAddress,
1073    slice_offset: BufferAddress,
1074    slice_size: BufferAddress,
1075) {
1076    if slice_offset > whole_size {
1077        panic!(
1078            "slice offset {} is out of range for buffer of size {}",
1079            slice_offset, whole_size
1080        );
1081    }
1082
1083    // Detect integer overflow.
1084    let end = slice_offset.checked_add(slice_size);
1085    if end.is_none_or(|end| end > whole_size) {
1086        panic!(
1087            "slice offset {} size {} is out of range for buffer of size {}",
1088            slice_offset, slice_size, whole_size
1089        );
1090    }
1091}
1092
1093#[track_caller]
1094pub(crate) fn range_to_offset_size<S: RangeBounds<BufferAddress>>(
1095    bounds: S,
1096    whole_size: BufferAddress,
1097) -> (BufferAddress, BufferAddress) {
1098    let offset = match bounds.start_bound() {
1099        Bound::Included(&bound) => bound,
1100        Bound::Excluded(&bound) => bound + 1,
1101        Bound::Unbounded => 0,
1102    };
1103    let size = match bounds.end_bound() {
1104        Bound::Included(&bound) => bound + 1 - offset,
1105        Bound::Excluded(&bound) => bound - offset,
1106        Bound::Unbounded => whole_size - offset,
1107    };
1108
1109    (offset, size)
1110}
1111
1112#[cfg(test)]
1113mod tests {
1114    use super::{check_buffer_bounds, range_overlaps, range_to_offset_size};
1115
1116    #[test]
1117    fn range_to_offset_size_works() {
1118        let whole = 100;
1119
1120        assert_eq!(range_to_offset_size(0..2, whole), (0, 2));
1121        assert_eq!(range_to_offset_size(2..5, whole), (2, 3));
1122        assert_eq!(range_to_offset_size(.., whole), (0, whole));
1123        assert_eq!(range_to_offset_size(21.., whole), (21, whole - 21));
1124        assert_eq!(range_to_offset_size(0.., whole), (0, whole));
1125        assert_eq!(range_to_offset_size(..21, whole), (0, 21));
1126    }
1127
1128    #[test]
1129    fn check_buffer_bounds_works_for_end_in_range() {
1130        check_buffer_bounds(200, 100, 50);
1131        check_buffer_bounds(200, 100, 100);
1132        check_buffer_bounds(u64::MAX, u64::MAX - 100, 100);
1133        check_buffer_bounds(u64::MAX, 0, u64::MAX);
1134        check_buffer_bounds(u64::MAX, 1, u64::MAX - 1);
1135        // Test empty buffer slices
1136        check_buffer_bounds(0, 0, 0);
1137        check_buffer_bounds(u64::MAX, u64::MAX, 0);
1138    }
1139
1140    #[test]
1141    #[should_panic]
1142    fn check_buffer_bounds_panics_for_end_over_size() {
1143        check_buffer_bounds(200, 100, 101);
1144    }
1145
1146    #[test]
1147    #[should_panic]
1148    fn check_buffer_bounds_panics_for_end_wraparound() {
1149        check_buffer_bounds(u64::MAX, 1, u64::MAX);
1150    }
1151
1152    #[test]
1153    fn range_overlapping() {
1154        // First range to the left
1155        assert_eq!(range_overlaps(&(0..1), &(1..3)), false);
1156        // First range overlaps left edge
1157        assert_eq!(range_overlaps(&(0..2), &(1..3)), true);
1158        // First range completely inside second
1159        assert_eq!(range_overlaps(&(1..2), &(0..3)), true);
1160        // First range completely surrounds second
1161        assert_eq!(range_overlaps(&(0..3), &(1..2)), true);
1162        // First range overlaps right edge
1163        assert_eq!(range_overlaps(&(1..3), &(0..2)), true);
1164        // First range entirely to the right
1165        assert_eq!(range_overlaps(&(2..3), &(0..2)), false);
1166    }
1167}