pub struct CpuWriteGpuReadBuffer<T: Pod + Send + Sync> {
    write_view: BufferViewMut<'static>,
    unwritten_element_range: Range<usize>,
    chunk_buffer: Arc<DynamicResource<GpuBufferHandle, BufferDesc, Buffer>>,
    byte_offset_in_chunk_buffer: BufferAddress,
    _type: PhantomData<T>,
}
Expand description

A sub-allocated staging buffer that can be written to.

Behaves a bit like a fixed sized Vec in that far it keeps track of how many elements were written to it.

We do not allow reading from this buffer as it is typically write-combined memory. Reading would work, but it can be very slow. For details on why, see Write combining is not your friend, by Fabian Giesen Note that the “vec like behavior” further encourages

  • not leaving holes
  • keeping writes sequential

Fields§

§write_view: BufferViewMut<'static>

Write view into the relevant buffer portion.

UNSAFE: The lifetime is transmuted to be 'static. In actuality it is tied to the lifetime of chunk_buffer!

§unwritten_element_range: Range<usize>

Range in T elements in write_view that haven’t been written yet.

§chunk_buffer: Arc<DynamicResource<GpuBufferHandle, BufferDesc, Buffer>>§byte_offset_in_chunk_buffer: BufferAddress§_type: PhantomData<T>

Marker for the type whose alignment and size requirements are honored by write_view.

Implementations§

source§

impl<T> CpuWriteGpuReadBuffer<T>
where T: Pod + Send + Sync,

source

fn as_mut_byte_slice(&mut self) -> &mut [u8]

Memory as slice.

Note that we can’t rely on any alignment guarantees here! We could offset the mapped CPU-sided memory, but then the GPU offset won’t be aligned anymore. There’s no way we can meet conflicting alignment requirements, so we need to work with unaligned bytes instead. See this comment on this wgpu issue about what we tried before.

Once wgpu has some alignment guarantees, we might be able to use this here to allow faster copies! (copies of larger blocks are likely less affected as memcpy typically does dynamic check/dispatching for SIMD based copies)

Do not make this public as we need to guarantee that the memory is never read from!

source

pub fn extend_from_slice( &mut self, elements: &[T] ) -> Result<(), CpuWriteGpuReadError>

Pushes a slice of elements into the buffer.

If the buffer is not big enough, only the first self.remaining_capacity() elements are pushed before returning an error.

source

pub fn extend( &mut self, elements: impl ExactSizeIterator<Item = T> ) -> Result<usize, CpuWriteGpuReadError>

Pushes several elements into the buffer.

If the buffer is not big enough, only the first CpuWriteGpuReadBuffer::remaining_capacity elements are pushed before returning an error. Otherwise, returns the number of elements pushed for convenience.

source

pub fn add_n( &mut self, element: T, num_elements: usize ) -> Result<(), CpuWriteGpuReadError>

Fills the buffer with n instances of an element.

If the buffer is not big enough, only the first self.remaining_capacity() elements are pushed before returning an error.

source

pub fn push(&mut self, element: T) -> Result<(), CpuWriteGpuReadError>

Pushes a single element into the buffer and advances the write pointer.

Returns an error if the data no longer fits into the buffer.

source

pub fn is_empty(&self) -> bool

True if no elements have been pushed into the buffer so far.

source

pub fn num_written(&self) -> usize

The number of elements pushed into the buffer so far.

source

pub fn remaining_capacity(&self) -> usize

The number of elements that can still be pushed into the buffer.

source

pub fn capacity(&self) -> usize

Total number of elements that the buffer can hold.

source

pub fn copy_to_texture2d_entire_first_layer( self, encoder: &mut CommandEncoder, destination: &Arc<DynamicResource<GpuTextureHandle, TextureDesc, GpuTextureInternal>> ) -> Result<(), CpuWriteGpuReadError>

Copies all so far written data to the first layer of a 2D texture.

Assumes that the buffer consists of as-tightly-packed-as-possible rows of data. (taking into account required padding as specified by [wgpu::COPY_BYTES_PER_ROW_ALIGNMENT])

Fails if the buffer size is not sufficient to fill the entire texture.

source

pub fn copy_to_texture2d( self, encoder: &mut CommandEncoder, destination: ImageCopyTexture<'_>, copy_size: Extent3d ) -> Result<(), CpuWriteGpuReadError>

Copies all so far written data to a rectangle on a single 2D texture layer.

Assumes that the buffer consists of as-tightly-packed-as-possible rows of data. (taking into account required padding as specified by [wgpu::COPY_BYTES_PER_ROW_ALIGNMENT])

Implementation note: Does 2D-only entirely for convenience as it greatly simplifies the input parameters.

source

pub fn copy_to_buffer( self, encoder: &mut CommandEncoder, destination: &Arc<DynamicResource<GpuBufferHandle, BufferDesc, Buffer>>, destination_offset: BufferAddress ) -> Result<(), CpuWriteGpuReadError>

Copies the entire buffer to another buffer and drops it.

Auto Trait Implementations§

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> 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
§

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
§

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
§

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.
§

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
§

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

§

impl<T> WasmNotSendSync for T
where T: WasmNotSend + WasmNotSync,

§

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