@@ -49,6 +49,8 @@ pub enum CpuWriteGpuReadError {
49
49
/// Note that the "vec like behavior" further encourages
50
50
/// * not leaving holes
51
51
/// * keeping writes sequential
52
+ ///
53
+ /// Must be dropped before calling [`CpuWriteGpuReadBelt::before_queue_submit`] (typically the end of a frame).
52
54
pub struct CpuWriteGpuReadBuffer < T : bytemuck:: Pod + Send + Sync > {
53
55
/// Write view into the relevant buffer portion.
54
56
write_view : wgpu:: BufferViewMut ,
@@ -551,18 +553,21 @@ impl CpuWriteGpuReadBelt {
551
553
552
554
/// Prepare currently mapped buffers for use in a submission.
553
555
///
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.
555
558
///
556
- /// At this point, all the partially used staging buffers are closed (cannot be used for
557
- /// further writes) until after [`CpuWriteGpuReadBelt::after_queue_submit`] is called *and* the GPU is done
558
- /// copying the data from them.
559
+ /// This must be called BEFORE the command encoder(s) used in any [`CpuWriteGpuReadBuffer`] copy operations are submitted.
559
560
pub fn before_queue_submit ( & mut self ) {
560
561
re_tracing:: profile_function!( ) ;
561
562
562
563
// This would be a great usecase for persistent memory mapping, i.e. mapping without the need to unmap
563
564
// https://github.com/gfx-rs/wgpu/issues/1468
564
565
// However, WebGPU does not support this!
565
566
567
+ // We're done with writing to this chunk and are ready to have the GPU read it!
568
+ //
569
+ // This part has to happen before submit, otherwise we get a validation error that
570
+ // the buffers are still mapped and can't be read by the gpu.
566
571
for chunk in self . active_chunks . drain ( ..) {
567
572
chunk. buffer . unmap ( ) ;
568
573
self . closed_chunks . push ( chunk) ;
@@ -574,12 +579,16 @@ impl CpuWriteGpuReadBelt {
574
579
/// This must only be called after the command encoder(s) used in [`CpuWriteGpuReadBuffer`]
575
580
/// copy operations are submitted. Additional calls are harmless.
576
581
/// Not calling this as soon as possible may result in increased buffer memory usage.
582
+ ///
583
+ /// Implementation note:
584
+ /// We can't use [`wgpu::CommandEncoder::map_buffer_on_submit`] here because for that we'd need to know which
585
+ /// command encoder is the last one scheduling any cpu->gpu copy operations.
586
+ /// Note that if chunks were fully tied to a single encoder, we could call [`wgpu::CommandEncoder::map_buffer_on_submit`]
587
+ /// once we know a chunk has all its cpu->gpu copy operations scheduled on that very encoder.
577
588
pub fn after_queue_submit ( & mut self ) {
578
589
re_tracing:: profile_function!( ) ;
579
590
self . receive_chunks ( ) ;
580
591
581
- // TODO(andreas): Use `map_buffer_on_submit` https://github.com/gfx-rs/wgpu/pull/8125 once available.
582
-
583
592
let sender = & self . sender ;
584
593
for chunk in self . closed_chunks . drain ( ..) {
585
594
let sender = sender. clone ( ) ;
0 commit comments