Skip to content

Commit 0fb42a1

Browse files
committed
Improve commentary on the read/write belts and why one can not simply use map_buffer_on_submit
1 parent 0e014b7 commit 0fb42a1

File tree

3 files changed

+29
-7
lines changed

3 files changed

+29
-7
lines changed

crates/viewer/re_renderer/src/allocator/cpu_write_gpu_read_belt.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub enum CpuWriteGpuReadError {
4949
/// Note that the "vec like behavior" further encourages
5050
/// * not leaving holes
5151
/// * keeping writes sequential
52+
///
53+
/// Must be dropped before calling [`CpuWriteGpuReadBelt::before_queue_submit`] (typically the end of a frame).
5254
pub struct CpuWriteGpuReadBuffer<T: bytemuck::Pod + Send + Sync> {
5355
/// Write view into the relevant buffer portion.
5456
write_view: wgpu::BufferViewMut,
@@ -551,7 +553,10 @@ impl CpuWriteGpuReadBelt {
551553

552554
/// Prepare currently mapped buffers for use in a submission.
553555
///
554-
/// This must be called before the command encoder(s) used in [`CpuWriteGpuReadBuffer`] copy operations are submitted.
556+
/// All existing [`CpuWriteGpuReadBuffer`] MUST be dropped before calling this function.
557+
/// Any not dropped [`CpuWriteGpuReadBuffer`] will cause a validation error.
558+
///
559+
/// This must be called BEFORE the command encoder(s) used in any [`CpuWriteGpuReadBuffer`] copy operations are submitted.
555560
///
556561
/// At this point, all the partially used staging buffers are closed (cannot be used for
557562
/// further writes) until after [`CpuWriteGpuReadBelt::after_queue_submit`] is called *and* the GPU is done
@@ -563,6 +568,10 @@ impl CpuWriteGpuReadBelt {
563568
// https://github.com/gfx-rs/wgpu/issues/1468
564569
// However, WebGPU does not support this!
565570

571+
// We're done with writing to this chunk and are ready to have the GPU read it!
572+
//
573+
// This part has to happen before submit, otherwise we get a validation error that
574+
// the buffers are still mapped and can't be read by the gpu.
566575
for chunk in self.active_chunks.drain(..) {
567576
chunk.buffer.unmap();
568577
self.closed_chunks.push(chunk);
@@ -574,12 +583,16 @@ impl CpuWriteGpuReadBelt {
574583
/// This must only be called after the command encoder(s) used in [`CpuWriteGpuReadBuffer`]
575584
/// copy operations are submitted. Additional calls are harmless.
576585
/// Not calling this as soon as possible may result in increased buffer memory usage.
586+
///
587+
/// Implementation note:
588+
/// We can't use [`wgpu::CommandEncoder::map_buffer_on_submit`] here because for that we'd need to know which
589+
/// command encoder is the last one scheduling any cpu->gpu copy operations.
590+
/// Note that if chunks were fully tied to a single encoder, we could call [`wgpu::CommandEncoder::map_buffer_on_submit`]
591+
/// once we know a chunk has all its cpu->gpu copy operations scheduled on that very encoder.
577592
pub fn after_queue_submit(&mut self) {
578593
re_tracing::profile_function!();
579594
self.receive_chunks();
580595

581-
// TODO(andreas): Use `map_buffer_on_submit` https://github.com/gfx-rs/wgpu/pull/8125 once available.
582-
583596
let sender = &self.sender;
584597
for chunk in self.closed_chunks.drain(..) {
585598
let sender = sender.clone();

crates/viewer/re_renderer/src/allocator/gpu_readback_belt.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,12 @@ impl GpuReadbackBelt {
311311
/// Prepare used buffers for CPU read.
312312
///
313313
/// This should be called after the command encoder(s) used in [`GpuReadbackBuffer`] copy operations are submitted.
314+
///
315+
/// Implementation note:
316+
/// We can't use [`wgpu::CommandEncoder::map_buffer_on_submit`] here because for that we'd need to know which
317+
/// command encoder is the last one scheduling any gpu->cpu copy operations.
318+
/// Note that if chunks were fully tied to a single encoder, we could call [`wgpu::CommandEncoder::map_buffer_on_submit`]
319+
/// once we know a chunk has all its gpu->cpu copy operations scheduled on that very encoder.
314320
pub fn after_queue_submit(&mut self) {
315321
re_tracing::profile_function!();
316322

crates/viewer/re_renderer/src/context.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,12 @@ This means, either a call to RenderContext::before_submit was omitted, or the pr
413413
self.before_submit();
414414
}
415415

416-
// Request write used staging buffer back.
417-
// TODO(andreas): If we'd control all submissions, we could move this directly after the submission which would be a bit better.
416+
// Request write-staging buffers back.
417+
// Ideally we'd do this as closely as possible to the last submission containing any cpu->gpu operations as possible.
418418
self.cpu_write_gpu_read_belt.get_mut().after_queue_submit();
419-
// Map all read staging buffers.
419+
420+
// Schedule mapping for all read staging buffers.
421+
// Ideally we'd do this as closely as possible to the last submission containing any gpu->cpu operations as possible.
420422
self.gpu_readback_belt.get_mut().after_queue_submit();
421423

422424
// Close previous' frame error scope.
@@ -502,7 +504,8 @@ This means, either a call to RenderContext::before_submit was omitted, or the pr
502504
pub fn before_submit(&mut self) {
503505
re_tracing::profile_function!();
504506

505-
// Unmap all write staging buffers.
507+
// Unmap all write staging buffers, so we don't get validation errors about buffers still being mapped
508+
// that the gpu wants to read from.
506509
self.cpu_write_gpu_read_belt.lock().before_queue_submit();
507510

508511
if let Some(command_encoder) = self

0 commit comments

Comments
 (0)