From 076aecd1507653135272efaff7d60aa063fb1e77 Mon Sep 17 00:00:00 2001 From: Andreas Reich Date: Sat, 23 Jan 2021 09:57:55 +0100 Subject: [PATCH] buffer map permeates zero init now in any case --- wgpu-core/src/device/mod.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index f69b63e7c4..e9f9de1117 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -196,27 +196,28 @@ fn map_buffer( }), _ => None, }; - let writes_are_synced = buffer.sync_mapped_writes.is_some() || block.is_coherent(); // Zero out uninitialized parts of the mapping. (Spec dictates all resources behave as if they were initialized with zero) - // Note that going through a `fill_buffer` command may be faster but we don't have the chance of interacting with the queue - // between map intent (map_buffer_async or immediately) and this call. + // + // If this is a read mapping, ideally we would use a `fill_buffer` command before reading the data from GPU (i.e. `invalidate_range`). + // However, this would require us to kick off and wait for a command buffer or piggy back on an existing one (the later is likely the only worthwhile option). + // As reading uninitialized memory isn't a particular important path to support, + // we instead just initialize the memory here and make sure it is GPU visible, so this happens at max only once for every buffer region. + // + // If this is a write mapping zeroing out the memory here is the only reasonable way as all data is pushed to GPU anyways. + let zero_init_needs_flush_now = !block.is_coherent() && buffer.sync_mapped_writes.is_none(); // No need to flush if it is flushed later anyways. + let uninitialized_ranges: Vec> = buffer.uninitialized_ranges_in_range(Range { start: offset, end: offset + size, }); for range in uninitialized_ranges { - unsafe { - ptr::write_bytes( - ptr.as_ptr().offset(range.start as isize), - 0, - (range.end - range.start) as usize, - ) - }; + let size = (range.end - range.start) as usize; + unsafe { ptr::write_bytes(ptr.as_ptr().offset(range.start as isize), 0, size) }; // (technically the buffer is only initialized when we're done unmapping but we know it can't be used otherwise meanwhile) - if writes_are_synced { - buffer.mark_initialized(range); + if zero_init_needs_flush_now { + block.flush_range(raw, range.start, Some(size))?; } }