Struct re_renderer::allocator::gpu_readback_belt::GpuReadbackBelt
source · pub struct GpuReadbackBelt {
chunk_size: u64,
active_chunks: Vec<Chunk>,
free_chunks: Vec<Chunk>,
received_chunks: Vec<Chunk>,
sender: Sender<Chunk>,
receiver: Receiver<Chunk>,
frame_index: u64,
}
Expand description
Efficiently performs many buffer reads by sharing and reusing temporary buffers.
Internally it uses a ring-buffer of staging buffers that are sub-allocated.
Fields§
§chunk_size: u64
Minimum size for new buffers.
active_chunks: Vec<Chunk>
Chunks for which the GPU writes are scheduled, but we haven’t mapped them yet.
free_chunks: Vec<Chunk>
Chunks that have been unmapped and are ready for writing by the GPU.
received_chunks: Vec<Chunk>
Chunks that are currently mapped and ready for reading by the CPU.
sender: Sender<Chunk>
When a chunk mapping is successful, it is moved to this sender to be read by the CPU.
receiver: Receiver<Chunk>
Chunks are received here are ready to be read by the CPU.
frame_index: u64
Current frame index, used for keeping track of how old chunks are.
Implementations§
source§impl GpuReadbackBelt
impl GpuReadbackBelt
sourceconst MIN_ALIGNMENT: u64 = 8u64
const MIN_ALIGNMENT: u64 = 8u64
All allocations of this allocator will be aligned to at least this size.
Buffer mappings however are currently NOT guaranteed to be aligned to this size! See this issue on Alignment guarantees for mapped buffers.
sourcepub fn new(chunk_size: BufferSize) -> Self
pub fn new(chunk_size: BufferSize) -> Self
Create a ring buffer for efficient & easy gpu memory readback.
The chunk_size
is the unit of internal buffer allocation. Reads will be
sub-allocated within each chunk. Therefore, for optimal use of memory, the
chunk size should be:
- larger than the largest single
GpuReadbackBelt::allocate
operation; - 1-4 times less than the total amount of data uploaded per submission
- bigger is better, within these bounds.
TODO(andreas): Adaptive chunk sizes TODO(andreas): Shrinking after usage spikes (e.g. screenshots of different sizes!)
sourcepub fn allocate(
&mut self,
device: &Device,
buffer_pool: &GpuBufferPool,
size_in_bytes: BufferAddress,
identifier: GpuReadbackIdentifier,
user_data: Box<dyn Any + Send + 'static>
) -> GpuReadbackBuffer
pub fn allocate( &mut self, device: &Device, buffer_pool: &GpuBufferPool, size_in_bytes: BufferAddress, identifier: GpuReadbackIdentifier, user_data: Box<dyn Any + Send + 'static> ) -> GpuReadbackBuffer
Allocates a Gpu writable buffer & cpu readable buffer with a given size.
sourcepub fn after_queue_submit(&mut self)
pub fn after_queue_submit(&mut self)
Prepare used buffers for CPU read.
This should be called after the command encoder(s) used in GpuReadbackBuffer
copy operations are submitted.
sourcepub fn begin_frame(&mut self, frame_index: u64)
pub fn begin_frame(&mut self, frame_index: u64)
Should be called at the beginning of a new frame.
Discards stale data that hasn’t been received by GpuReadbackBelt::readback_data
for more than a frame.
sourcepub fn readback_data<UserDataType: 'static>(
&mut self,
identifier: GpuReadbackIdentifier,
callback: impl FnOnce(&[u8], Box<UserDataType>)
)
pub fn readback_data<UserDataType: 'static>( &mut self, identifier: GpuReadbackIdentifier, callback: impl FnOnce(&[u8], Box<UserDataType>) )
Try to receive a pending data readback with the given identifier and the given user data type.
Returns the oldest received data with the given identifier & type. This is almost certainly also the oldest scheduled readback. But there is no strict guarantee for this. It could in theory happen that a readback is scheduled after a previous one, but finishes before it!
ATTENTION: Do NOT assume any alignment on the slice passed to on_data_received
.
See this issue on Alignment guarantees for mapped buffers.
sourcefn receive_chunks(&mut self)
fn receive_chunks(&mut self)
Check if any new chunks are ready to be read.
fn reuse_chunk(&mut self, chunk: Chunk)
Trait Implementations§
Auto Trait Implementations§
impl Freeze for GpuReadbackBelt
impl !RefUnwindSafe for GpuReadbackBelt
impl Send for GpuReadbackBelt
impl !Sync for GpuReadbackBelt
impl Unpin for GpuReadbackBelt
impl !UnwindSafe for GpuReadbackBelt
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
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>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
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)
fn as_any(&self) -> &(dyn Any + 'static)
&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)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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