Struct rerun::external::eframe::egui_wgpu::wgpu::Buffer

pub struct Buffer {
    pub(crate) context: Arc<dyn DynContext>,
    pub(crate) id: ObjectId,
    pub(crate) data: Box<dyn Any + Sync + Send>,
    pub(crate) map_context: Mutex<RawMutex, MapContext>,
    pub(crate) size: u64,
    pub(crate) usage: BufferUsages,
}
Expand description

Handle to a GPU-accessible buffer.

Created with Device::create_buffer or DeviceExt::create_buffer_init.

Corresponds to WebGPU GPUBuffer.

A Buffer’s bytes have “interior mutability”: functions like Queue::write_buffer or mapping a buffer for writing only require a &Buffer, not a &mut Buffer, even though they modify its contents. wgpu prevents simultaneous reads and writes of buffer contents using run-time checks.

§Mapping buffers

If a Buffer is created with the appropriate usage, it can be mapped: you can make its contents accessible to the CPU as an ordinary &[u8] or &mut [u8] slice of bytes. Buffers created with the mapped_at_creation flag set are also mapped initially.

Depending on the hardware, the buffer could be memory shared between CPU and GPU, so that the CPU has direct access to the same bytes the GPU will consult; or it may be ordinary CPU memory, whose contents the system must copy to/from the GPU as needed. This crate’s API is designed to work the same way in either case: at any given time, a buffer is either mapped and available to the CPU, or unmapped and ready for use by the GPU, but never both. This makes it impossible for either side to observe changes by the other immediately, and any necessary transfers can be carried out when the buffer transitions from one state to the other.

There are two ways to map a buffer:

  • If [BufferDescriptor::mapped_at_creation] is true, then the entire buffer is mapped when it is created. This is the easiest way to initialize a new buffer. You can set mapped_at_creation on any kind of buffer, regardless of its usage flags.

  • If the buffer’s usage includes the MAP_READ or MAP_WRITE flags, then you can call buffer.slice(range).map_async(mode, callback) to map the portion of buffer given by range. This waits for the GPU to finish using the buffer, and invokes callback as soon as the buffer is safe for the CPU to access.

Once a buffer is mapped:

  • You can call buffer.slice(range).get_mapped_range() to obtain a BufferView, which dereferences to a &[u8] that you can use to read the buffer’s contents.

  • Or, you can call buffer.slice(range).get_mapped_range_mut() to obtain a BufferViewMut, which dereferences to a &mut [u8] that you can use to read and write the buffer’s contents.

The given range must fall within the mapped portion of the buffer. If you attempt to access overlapping ranges, even for shared access only, these methods panic.

While a buffer is mapped, you may not submit any commands to the GPU that access it. You may record command buffers that use the buffer, but if you submit them while the buffer is mapped, submission will panic.

When you are done using the buffer on the CPU, you must call Buffer::unmap to make it available for use by the GPU again. All BufferView and BufferViewMut views referring to the buffer must be dropped before you unmap it; otherwise, Buffer::unmap will panic.

§Example

If buffer was created with BufferUsages::MAP_WRITE, we could fill it with f32 values like this:

let buffer = std::sync::Arc::new(buffer);
let capturable = buffer.clone();
buffer.slice(..).map_async(wgpu::MapMode::Write, move |result| {
    if result.is_ok() {
        let mut view = capturable.slice(..).get_mapped_range_mut();
        let floats: &mut [f32] = bytemuck::cast_slice_mut(&mut view);
        floats.fill(42.0);
        drop(view);
        capturable.unmap();
    }
});

This code takes the following steps:

  • First, it moves buffer into an Arc, and makes a clone for capture by the callback passed to map_async. Since a map_async callback may be invoked from another thread, interaction between the callback and the thread calling map_async generally requires some sort of shared heap data like this. In real code, the Arc would probably own some larger structure that itself owns buffer.

  • Then, it calls Buffer::slice to make a BufferSlice referring to the buffer’s entire contents.

  • Next, it calls BufferSlice::map_async to request that the bytes to which the slice refers be made accessible to the CPU (“mapped”). This may entail waiting for previously enqueued operations on buffer to finish. Although map_async itself always returns immediately, it saves the callback function to be invoked later.

  • When some later call to Device::poll or Instance::poll_all (not shown in this example) determines that the buffer is mapped and ready for the CPU to use, it invokes the callback function.

  • The callback function calls Buffer::slice and then BufferSlice::get_mapped_range_mut to obtain a BufferViewMut, which dereferences to a &mut [u8] slice referring to the buffer’s bytes.

  • It then uses the bytemuck crate to turn the &mut [u8] into a &mut [f32], and calls the slice fill method to fill the buffer with a useful value.

  • Finally, the callback drops the view and calls Buffer::unmap to unmap the buffer. In real code, the callback would also need to do some sort of synchronization to let the rest of the program know that it has completed its work.

If using map_async directly is awkward, you may find it more convenient to use Queue::write_buffer and util::DownloadBuffer::read_buffer. However, those each have their own tradeoffs; the asynchronous nature of GPU execution makes it hard to avoid friction altogether.

§Mapping buffers on the web

When compiled to WebAssembly and running in a browser content process, wgpu implements its API in terms of the browser’s WebGPU implementation. In this context, wgpu is further isolated from the GPU:

  • Depending on the browser’s WebGPU implementation, mapping and unmapping buffers probably entails copies between WebAssembly linear memory and the graphics driver’s buffers.

  • All modern web browsers isolate web content in its own sandboxed process, which can only interact with the GPU via interprocess communication (IPC). Although most browsers’ IPC systems use shared memory for large data transfers, there will still probably need to be copies into and out of the shared memory buffers.

All of these copies contribute to the cost of buffer mapping in this configuration.

Fields§

§context: Arc<dyn DynContext>§id: ObjectId§data: Box<dyn Any + Sync + Send>§map_context: Mutex<RawMutex, MapContext>§size: u64§usage: BufferUsages

Implementations§

§

impl Buffer

pub fn as_entire_binding(&self) -> BindingResource<'_>

Return the binding view of the entire buffer.

pub fn as_entire_buffer_binding(&self) -> BufferBinding<'_>

Return the binding view of the entire buffer.

pub unsafe fn as_hal<A, F, R>(&self, hal_buffer_callback: F) -> R
where A: HalApi, F: FnOnce(Option<&<A as Api>::Buffer>) -> R,

Returns the inner hal Buffer using a callback. The hal buffer will be None if the backend type argument does not match with this wgpu Buffer

§Safety
  • The raw handle obtained from the hal Buffer must not be manually destroyed

pub fn slice<S>(&self, bounds: S) -> BufferSlice<'_>
where S: RangeBounds<u64>,

Return a slice of a Buffer’s bytes.

Return a BufferSlice referring to the portion of self’s contents indicated by bounds. Regardless of what sort of data self stores, bounds start and end are given in bytes.

A BufferSlice can be used to supply vertex and index data, or to map buffer contents for access from the CPU. See the BufferSlice documentation for details.

The range argument can be half or fully unbounded: for example, buffer.slice(..) refers to the entire buffer, and buffer.slice(n..) refers to the portion starting at the nth byte and extending to the end of the buffer.

pub fn unmap(&self)

Flushes any pending write operations and unmaps the buffer from host memory.

pub fn destroy(&self)

Destroy the associated native resources as soon as possible.

pub fn size(&self) -> u64

Returns the length of the buffer allocation in bytes.

This is always equal to the size that was specified when creating the buffer.

pub fn usage(&self) -> BufferUsages

Returns the allowed usages for this Buffer.

This is always equal to the usage that was specified when creating the buffer.

§

impl Buffer

pub fn global_id(&self) -> Id<Buffer>

Returns a globally-unique identifier for this Buffer.

Calling this method multiple times on the same object will always return the same value. The returned value is guaranteed to be different for all resources created from the same Instance.

Trait Implementations§

§

impl Debug for Buffer

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Drop for Buffer

§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl !Freeze for Buffer

§

impl !RefUnwindSafe for Buffer

§

impl Send for Buffer

§

impl Sync for Buffer

§

impl Unpin for Buffer

§

impl !UnwindSafe for Buffer

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Az for T

source§

fn az<Dst>(self) -> Dst
where T: Cast<Dst>,

Casts the value.
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<Src, Dst> CastFrom<Src> for Dst
where Src: Cast<Dst>,

source§

fn cast_from(src: Src) -> Dst

Casts the value.
source§

impl<T> CheckedAs for T

source§

fn checked_as<Dst>(self) -> Option<Dst>
where T: CheckedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> CheckedCastFrom<Src> for Dst
where Src: CheckedCast<Dst>,

source§

fn checked_cast_from(src: Src) -> Option<Dst>

Casts the value.
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T> IntoRequest<T> for T

source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
source§

impl<Src, Dst> LosslessTryInto<Dst> for Src
where Dst: LosslessTryFrom<Src>,

source§

fn lossless_try_into(self) -> Option<Dst>

Performs the conversion.
source§

impl<Src, Dst> LossyInto<Dst> for Src
where Dst: LossyFrom<Src>,

source§

fn lossy_into(self) -> Dst

Performs the conversion.
source§

impl<T> OverflowingAs for T

source§

fn overflowing_as<Dst>(self) -> (Dst, bool)
where T: OverflowingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> OverflowingCastFrom<Src> for Dst
where Src: OverflowingCast<Dst>,

source§

fn overflowing_cast_from(src: Src) -> (Dst, bool)

Casts the value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> SaturatingAs for T

source§

fn saturating_as<Dst>(self) -> Dst
where T: SaturatingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> SaturatingCastFrom<Src> for Dst
where Src: SaturatingCast<Dst>,

source§

fn saturating_cast_from(src: Src) -> Dst

Casts the value.
§

impl<T> To for T
where T: ?Sized,

§

fn to<T>(self) -> T
where Self: Into<T>,

Converts to T by calling Into<T>::into.
§

fn try_to<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Tries to convert to T by calling TryInto<T>::try_into.
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> UnwrappedAs for T

source§

fn unwrapped_as<Dst>(self) -> Dst
where T: UnwrappedCast<Dst>,

Casts the value.
source§

impl<Src, Dst> UnwrappedCastFrom<Src> for Dst
where Src: UnwrappedCast<Dst>,

source§

fn unwrapped_cast_from(src: Src) -> Dst

Casts the value.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
source§

impl<T> WrappingAs for T

source§

fn wrapping_as<Dst>(self) -> Dst
where T: WrappingCast<Dst>,

Casts the value.
source§

impl<Src, Dst> WrappingCastFrom<Src> for Dst
where Src: WrappingCast<Dst>,

source§

fn wrapping_cast_from(src: Src) -> Dst

Casts the value.
§

impl<T> Ungil for T
where T: Send,

§

impl<T> WasmNotSend for T
where T: Send,

§

impl<T> WasmNotSendSync for T

§

impl<T> WasmNotSync for T
where T: Sync,