diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 9dbb9ed5de..6a2fe298ae 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -90,7 +90,17 @@ impl BakedCommands { .get_mut(buffer_use.id) .map_err(|_| DestroyedBufferError(buffer_use.id))?; - let uninitialized_ranges = buffer.initialization_status.drain(buffer_use.range.clone()); + // align the end to 4 + let end_remainder = buffer_use.range.end % wgt::COPY_BUFFER_ALIGNMENT; + let end = if end_remainder == 0 { + buffer_use.range.end + } else { + buffer_use.range.end + wgt::COPY_BUFFER_ALIGNMENT - end_remainder + }; + let uninitialized_ranges = buffer + .initialization_status + .drain(buffer_use.range.start..end); + match buffer_use.kind { MemoryInitKind::ImplicitlyInitialized => { uninitialized_ranges.for_each(drop); @@ -140,8 +150,8 @@ impl BakedCommands { } for range in ranges.iter() { - assert!(range.start % 4 == 0, "Buffer {:?} has an uninitialized range with a start not aligned to 4 (start was {})", raw_buf, range.start); - assert!(range.end % 4 == 0, "Buffer {:?} has an uninitialized range with an end not aligned to 4 (end was {})", raw_buf, range.end); + assert!(range.start % wgt::COPY_BUFFER_ALIGNMENT == 0, "Buffer {:?} has an uninitialized range with a start not aligned to 4 (start was {})", raw_buf, range.start); + assert!(range.end % wgt::COPY_BUFFER_ALIGNMENT == 0, "Buffer {:?} has an uninitialized range with an end not aligned to 4 (end was {})", raw_buf, range.end); unsafe { self.encoder.clear_buffer(raw_buf, range.clone()); diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 277a28cc6c..a874f65025 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -160,6 +160,8 @@ fn map_buffer( _ => None, }; + assert_eq!(offset % wgt::COPY_BUFFER_ALIGNMENT, 0); + assert_eq!(size % wgt::COPY_BUFFER_ALIGNMENT, 0); // Zero out uninitialized parts of the mapping. (Spec dictates all resources behave as if they were initialized with zero) // // If this is a read mapping, ideally we would use a `clear_buffer` command before reading the data from GPU (i.e. `invalidate_range`). @@ -510,13 +512,19 @@ impl Device { } else { desc.size }; + let clear_remainder = actual_size % wgt::COPY_BUFFER_ALIGNMENT; + let aligned_size = if clear_remainder != 0 { + actual_size + wgt::COPY_BUFFER_ALIGNMENT - clear_remainder + } else { + actual_size + }; let mut memory_flags = hal::MemoryFlags::empty(); memory_flags.set(hal::MemoryFlags::TRANSIENT, transient); let hal_desc = hal::BufferDescriptor { label: desc.label.borrow_option(), - size: actual_size, + size: aligned_size, usage, memory_flags, }; @@ -1323,9 +1331,10 @@ impl Device { return Err(Error::BindingZeroSize(bb.buffer_id)); } + assert_eq!(bb.offset % wgt::COPY_BUFFER_ALIGNMENT, 0); used_buffer_ranges.extend(buffer.initialization_status.create_action( bb.buffer_id, - bb.offset..(bb.offset + bind_size), + bb.offset..bb.offset + bind_size, MemoryInitKind::NeedsInitializedMemory, )); @@ -2771,6 +2780,7 @@ impl Global { } }; + assert_eq!(buffer.size % wgt::COPY_BUFFER_ALIGNMENT, 0); // Zero initialize memory and then mark both staging and buffer as initialized // (it's guaranteed that this is the case by the time the buffer is usable) unsafe { ptr::write_bytes(mapping.ptr.as_ptr(), 0, buffer.size as usize) }; diff --git a/wgpu-core/src/init_tracker/mod.rs b/wgpu-core/src/init_tracker/mod.rs index dd6a6cc32d..527cb3d72a 100644 --- a/wgpu-core/src/init_tracker/mod.rs +++ b/wgpu-core/src/init_tracker/mod.rs @@ -14,7 +14,7 @@ // therefore this leads to a `MemoryInitKind.ImplicitlyInitialized` action, exactly like a read would. use smallvec::SmallVec; -use std::{iter, ops::Range}; +use std::{fmt, iter, ops::Range}; mod buffer; //mod texture; @@ -46,7 +46,7 @@ pub(crate) struct InitTracker { uninitialized_ranges: UninitializedRangeVec, } -pub(crate) struct InitTrackerDrain<'a, Idx: Ord + Copy> { +pub(crate) struct InitTrackerDrain<'a, Idx: fmt::Debug + Ord + Copy> { uninitialized_ranges: &'a mut UninitializedRangeVec, drain_range: Range, first_index: usize, @@ -55,7 +55,7 @@ pub(crate) struct InitTrackerDrain<'a, Idx: Ord + Copy> { impl<'a, Idx> Iterator for InitTrackerDrain<'a, Idx> where - Idx: Ord + Copy, + Idx: fmt::Debug + Ord + Copy, { type Item = Range; @@ -78,7 +78,6 @@ where if num_affected == 0 { return None; } - let first_range = &mut self.uninitialized_ranges[self.first_index]; // Split one "big" uninitialized range? @@ -118,7 +117,7 @@ where impl InitTracker where - Idx: Ord + Copy + Default, + Idx: fmt::Debug + Ord + Copy + Default, { pub(crate) fn new(size: Idx) -> Self { Self {