From 4ee8aa5f1a201ce15ff15cffcbf05f49b9d64687 Mon Sep 17 00:00:00 2001 From: marc0246 <40955683+marc0246@users.noreply.github.com> Date: Sat, 26 Aug 2023 17:13:40 +0200 Subject: [PATCH] Remove uses of `Option::unwrap_unchecked` as a safety precaution (#2310) --- vulkano/src/buffer/subbuffer.rs | 8 +++---- vulkano/src/memory/allocator/suballocator.rs | 17 ++++++++++++++ vulkano/src/memory/mod.rs | 24 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/vulkano/src/buffer/subbuffer.rs b/vulkano/src/buffer/subbuffer.rs index d157aeb4ad..1293f11a34 100644 --- a/vulkano/src/buffer/subbuffer.rs +++ b/vulkano/src/buffer/subbuffer.rs @@ -129,11 +129,9 @@ impl Subbuffer { /// [`MappingState::slice`]: crate::memory::MappingState::slice pub fn mapped_slice(&self) -> Result, HostAccessError> { match self.buffer().memory() { - BufferMemory::Normal(a) => { - let opt = a.mapped_slice(self.range()); - + BufferMemory::Normal(allocation) => { // SAFETY: `self.range()` is in bounds of the allocation. - unsafe { opt.unwrap_unchecked() } + unsafe { allocation.mapped_slice_unchecked(self.range()) } } BufferMemory::Sparse => unreachable!(), } @@ -510,7 +508,7 @@ impl Subbuffer<[T]> { #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] pub unsafe fn slice_unchecked(mut self, range: impl RangeBounds) -> Subbuffer<[T]> { - let Range { start, end } = memory::range(range, ..self.len()).unwrap_unchecked(); + let Range { start, end } = memory::range_unchecked(range, ..self.len()); self.offset += start * size_of::() as DeviceSize; self.size = (end - start) * size_of::() as DeviceSize; diff --git a/vulkano/src/memory/allocator/suballocator.rs b/vulkano/src/memory/allocator/suballocator.rs index 9beed579fe..7a3b183d2e 100644 --- a/vulkano/src/memory/allocator/suballocator.rs +++ b/vulkano/src/memory/allocator/suballocator.rs @@ -157,6 +157,23 @@ impl MemoryAlloc { Some(res) } + #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))] + #[inline] + pub unsafe fn mapped_slice_unchecked( + &self, + range: impl RangeBounds, + ) -> Result, HostAccessError> { + let mut range = memory::range_unchecked(range, ..self.size()); + range.start += self.offset(); + range.end += self.offset(); + + if let Some(state) = self.device_memory().mapping_state() { + state.slice(range).ok_or(HostAccessError::OutOfMappedRange) + } else { + Err(HostAccessError::NotHostMapped) + } + } + pub(crate) fn atom_size(&self) -> Option { self.atom_size } diff --git a/vulkano/src/memory/mod.rs b/vulkano/src/memory/mod.rs index 5c6566d99c..8603676daa 100644 --- a/vulkano/src/memory/mod.rs +++ b/vulkano/src/memory/mod.rs @@ -590,3 +590,27 @@ pub(crate) fn range( (start <= end && end <= len).then_some(Range { start, end }) } + +/// Converts a `RangeBounds` into a `Range` without doing any bounds checking. +pub(crate) fn range_unchecked( + range: impl RangeBounds, + bounds: RangeTo, +) -> Range { + let len = bounds.end; + + let start = match range.start_bound() { + Bound::Included(&start) => start, + Bound::Excluded(start) => start + 1, + Bound::Unbounded => 0, + }; + + let end = match range.end_bound() { + Bound::Included(end) => end + 1, + Bound::Excluded(&end) => end, + Bound::Unbounded => len, + }; + + debug_assert!(start <= end && end <= len); + + Range { start, end } +}