Skip to main content

ReadbackStream

Struct ReadbackStream 

Source
pub struct ReadbackStream { /* private fields */ }
Expand description

High-throughput, non-blocking readback pipeline based on a ring buffer.

See module documentation for architecture details and usage.

Implementations§

Source§

impl ReadbackStream

Source

pub fn new( device: &Device, width: u32, height: u32, format: TextureFormat, buffer_count: usize, max_stash_size: usize, ) -> Result<ReadbackStream, ReadbackError>

Creates a new readback stream with buffer_count ring-buffer slots.

§Arguments
  • device — GPU device for buffer allocation.
  • width / height — Dimensions of the source render target.
  • format — Pixel format (must support block_copy_size).
  • buffer_count — Number of staging buffers (ring size). Typical values are 2–4; higher counts tolerate more GPU-to-CPU latency at the cost of VRAM.
§Errors

Returns ReadbackError::UnsupportedFormat if the format does not have a known block copy size.

Source

pub fn try_submit( &mut self, device: &Device, queue: &Queue, texture: &Texture, ) -> Result<(), ReadbackError>

Submits a non-blocking copy from texture to the next ring-buffer slot.

The copy command is recorded and submitted immediately. When the GPU completes the copy, a map_async callback pushes the slot index into the internal channel, making it available via try_recv.

§Back-pressure

If all slots are in-flight, this method returns ReadbackError::RingFull without blocking. The caller may choose to skip the frame (real-time path) or drain via try_recv.

Source

pub fn submit_blocking( &mut self, device: &Device, queue: &Queue, texture: &Texture, ) -> Result<(), ReadbackError>

Submits a copy, blocking when the ring buffer is full.

When all ring-buffer slots are occupied, this method:

  1. Blocks until the GPU completes at least one pending readback.
  2. Extracts the completed frame into stashed_frames (using a recycled buffer from free_pool when available).
  3. Proceeds with the submission on the freed slot.

This guarantees zero frame loss and is intended for offline workloads such as video export and dataset generation.

§Safety on WASM

wgpu::PollType::wait_indefinitely() will panic on WebAssembly. Use try_submit for WASM targets.

§Stash limit

max_stash_size caps the number of completed-but-unconsumed frames held in memory. If the stash is full, returns ReadbackError::StashFull to prevent unbounded memory growth.

Source

pub fn try_recv(&mut self) -> Result<Option<ReadbackFrame>, ReadbackError>

Returns the next ready frame without blocking, or None if no frame is available yet.

This is the allocating receive path — a new Vec<u8> (or one from the internal pool) is returned for each frame. For zero-copy steady-state operation, prefer try_recv_into.

Source

pub fn try_recv_into( &mut self, output: &mut Vec<u8>, ) -> Result<Option<u64>, ReadbackError>

Zero-allocation receive: writes pixel data into a caller-supplied buffer.

On success the previous contents of output are swapped into the internal free pool (preserving its heap capacity for future frames), and output receives the new frame’s pixel data. Returns the frame index, or None if no frame is ready.

After the initial warm-up period (≤ buffer_count frames), this method performs zero heap allocations per call.

Source

pub fn flush( &mut self, device: &Device, ) -> Result<Vec<ReadbackFrame>, ReadbackError>

Blocks until all in-flight frames have been read back.

Returns all remaining frames (stashed + in-flight) as a Vec. This should be called at the end of a recording session to ensure no frames are lost.

Source

pub fn format(&self) -> TextureFormat

Returns the pixel format of the readback stream.

Source

pub fn dimensions(&self) -> (u32, u32)

Returns the render target dimensions.

Source

pub fn bytes_per_pixel(&self) -> u32

Returns the number of bytes per pixel for the current format.

Source

pub fn buffer_count(&self) -> usize

Returns the number of ring-buffer slots.

Source

pub fn frames_submitted(&self) -> u64

Returns the total number of frames submitted so far.

Source

pub fn frame_byte_size(&self) -> usize

Returns the expected byte size of one tightly-packed frame.

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

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

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

Source§

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

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

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

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

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

Source§

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

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.

Source§

impl<T> Instrument for T

Source§

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

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

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> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

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

Source§

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> Upcast<T> for T

Source§

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

Source§

impl<T> WithSubscriber for T

Source§

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

fn with_current_subscriber(self) -> WithDispatch<Self>

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

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

Source§

impl<T> WasmNotSendSync for T

Source§

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