diff options
Diffstat (limited to 'src/buffer/slice.rs')
-rw-r--r-- | src/buffer/slice.rs | 315 |
1 files changed, 0 insertions, 315 deletions
diff --git a/src/buffer/slice.rs b/src/buffer/slice.rs deleted file mode 100644 index 03995d5..0000000 --- a/src/buffer/slice.rs +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright (c) 2016 The vulkano developers -// Licensed under the Apache License, Version 2.0 -// <LICENSE-APACHE or -// https://www.apache.org/licenses/LICENSE-2.0> or the MIT -// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, -// at your option. All files in the project carrying such -// notice may not be copied, modified, or distributed except -// according to those terms. - -use crate::buffer::traits::BufferAccess; -use crate::buffer::traits::BufferInner; -use crate::buffer::traits::TypedBufferAccess; -use crate::device::Device; -use crate::device::DeviceOwned; -use crate::device::Queue; -use crate::sync::AccessError; -use crate::DeviceSize; -use std::hash::Hash; -use std::hash::Hasher; -use std::marker::PhantomData; -use std::mem; -use std::mem::MaybeUninit; -use std::ops::Range; -use std::sync::Arc; - -/// A subpart of a buffer. -/// -/// This object doesn't correspond to any Vulkan object. It exists for API convenience. -/// -/// # Example -/// -/// Creating a slice: -/// -/// ```ignore // FIXME: unignore -/// use vulkano::buffer::BufferSlice; -/// # let buffer: std::sync::Arc<vulkano::buffer::DeviceLocalBuffer<[u8]>> = return; -/// let _slice = BufferSlice::from(&buffer); -/// ``` -/// -/// Selecting a slice of a buffer that contains `[T]`: -/// -/// ```ignore // FIXME: unignore -/// use vulkano::buffer::BufferSlice; -/// # let buffer: std::sync::Arc<vulkano::buffer::DeviceLocalBuffer<[u8]>> = return; -/// let _slice = BufferSlice::from(&buffer).slice(12 .. 14).unwrap(); -/// ``` -/// -pub struct BufferSlice<T: ?Sized, B> { - marker: PhantomData<T>, - resource: B, - offset: DeviceSize, - size: DeviceSize, -} - -// We need to implement `Clone` manually, otherwise the derive adds a `T: Clone` requirement. -impl<T: ?Sized, B> Clone for BufferSlice<T, B> -where - B: Clone, -{ - #[inline] - fn clone(&self) -> Self { - BufferSlice { - marker: PhantomData, - resource: self.resource.clone(), - offset: self.offset, - size: self.size, - } - } -} - -impl<T: ?Sized, B> BufferSlice<T, B> { - #[inline] - pub fn from_typed_buffer_access(r: B) -> BufferSlice<T, B> - where - B: TypedBufferAccess<Content = T>, - { - let size = r.size(); - - BufferSlice { - marker: PhantomData, - resource: r, - offset: 0, - size: size, - } - } - - /// Returns the buffer that this slice belongs to. - pub fn buffer(&self) -> &B { - &self.resource - } - - /// Returns the offset of that slice within the buffer. - #[inline] - pub fn offset(&self) -> DeviceSize { - self.offset - } - - /// Returns the size of that slice in bytes. - #[inline] - pub fn size(&self) -> DeviceSize { - self.size - } - - /// Builds a slice that contains an element from inside the buffer. - /// - /// This method builds an object that represents a slice of the buffer. No actual operation - /// is performed. - /// - /// # Example - /// - /// TODO - /// - /// # Safety - /// - /// The object whose reference is passed to the closure is uninitialized. Therefore you - /// **must not** access the content of the object. - /// - /// You **must** return a reference to an element from the parameter. The closure **must not** - /// panic. - #[inline] - pub unsafe fn slice_custom<F, R: ?Sized>(self, f: F) -> BufferSlice<R, B> - where - F: for<'r> FnOnce(&'r T) -> &'r R, // TODO: bounds on R - { - let data: MaybeUninit<&T> = MaybeUninit::zeroed(); - let result = f(data.assume_init()); - let size = mem::size_of_val(result) as DeviceSize; - let result = result as *const R as *const () as DeviceSize; - - assert!(result <= self.size()); - assert!(result + size <= self.size()); - - BufferSlice { - marker: PhantomData, - resource: self.resource, - offset: self.offset + result, - size, - } - } - - /// Changes the `T` generic parameter of the `BufferSlice` to the desired type. This can be - /// useful when you have a buffer with various types of data and want to create a typed slice - /// of a region that contains a single type of data. - /// - /// # Example - /// - /// ``` - /// # use std::sync::Arc; - /// # use vulkano::buffer::BufferSlice; - /// # use vulkano::buffer::immutable::ImmutableBuffer; - /// # struct VertexImpl; - /// let blob_slice: BufferSlice<[u8], Arc<ImmutableBuffer<[u8]>>> = return; - /// let vertex_slice: BufferSlice<[VertexImpl], Arc<ImmutableBuffer<[u8]>>> = unsafe { - /// blob_slice.reinterpret::<[VertexImpl]>() - /// }; - /// ``` - /// - /// # Safety - /// - /// Correct `offset` and `size` must be ensured before using this `BufferSlice` on the device. - /// See `BufferSlice::slice` for adjusting these properties. - #[inline] - pub unsafe fn reinterpret<R: ?Sized>(self) -> BufferSlice<R, B> { - BufferSlice { - marker: PhantomData, - resource: self.resource, - offset: self.offset, - size: self.size, - } - } -} - -impl<T, B> BufferSlice<[T], B> { - /// Returns the number of elements in this slice. - #[inline] - pub fn len(&self) -> DeviceSize { - debug_assert_eq!(self.size() % mem::size_of::<T>() as DeviceSize, 0); - self.size() / mem::size_of::<T>() as DeviceSize - } - - /// Reduces the slice to just one element of the array. - /// - /// Returns `None` if out of range. - #[inline] - pub fn index(self, index: DeviceSize) -> Option<BufferSlice<T, B>> { - if index >= self.len() { - return None; - } - - Some(BufferSlice { - marker: PhantomData, - resource: self.resource, - offset: self.offset + index * mem::size_of::<T>() as DeviceSize, - size: mem::size_of::<T>() as DeviceSize, - }) - } - - /// Reduces the slice to just a range of the array. - /// - /// Returns `None` if out of range. - #[inline] - pub fn slice(self, range: Range<DeviceSize>) -> Option<BufferSlice<[T], B>> { - if range.end > self.len() { - return None; - } - - Some(BufferSlice { - marker: PhantomData, - resource: self.resource, - offset: self.offset + range.start * mem::size_of::<T>() as DeviceSize, - size: (range.end - range.start) * mem::size_of::<T>() as DeviceSize, - }) - } -} - -unsafe impl<T: ?Sized, B> BufferAccess for BufferSlice<T, B> -where - B: BufferAccess, -{ - #[inline] - fn inner(&self) -> BufferInner { - let inner = self.resource.inner(); - BufferInner { - buffer: inner.buffer, - offset: inner.offset + self.offset, - } - } - - #[inline] - fn size(&self) -> DeviceSize { - self.size - } - - #[inline] - fn conflict_key(&self) -> (u64, u64) { - self.resource.conflict_key() - } - - #[inline] - fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> { - self.resource.try_gpu_lock(exclusive_access, queue) - } - - #[inline] - unsafe fn increase_gpu_lock(&self) { - self.resource.increase_gpu_lock() - } - - #[inline] - unsafe fn unlock(&self) { - self.resource.unlock() - } -} - -unsafe impl<T: ?Sized, B> TypedBufferAccess for BufferSlice<T, B> -where - B: BufferAccess, -{ - type Content = T; -} - -unsafe impl<T: ?Sized, B> DeviceOwned for BufferSlice<T, B> -where - B: DeviceOwned, -{ - #[inline] - fn device(&self) -> &Arc<Device> { - self.resource.device() - } -} - -impl<T, B> From<BufferSlice<T, B>> for BufferSlice<[T], B> { - #[inline] - fn from(r: BufferSlice<T, B>) -> BufferSlice<[T], B> { - BufferSlice { - marker: PhantomData, - resource: r.resource, - offset: r.offset, - size: r.size, - } - } -} - -impl<T: ?Sized, B> PartialEq for BufferSlice<T, B> -where - B: BufferAccess, -{ - #[inline] - fn eq(&self, other: &Self) -> bool { - self.inner() == other.inner() && self.size() == other.size() - } -} - -impl<T: ?Sized, B> Eq for BufferSlice<T, B> where B: BufferAccess {} - -impl<T: ?Sized, B> Hash for BufferSlice<T, B> -where - B: BufferAccess, -{ - #[inline] - fn hash<H: Hasher>(&self, state: &mut H) { - self.inner().hash(state); - self.size().hash(state); - } -} - -/// Takes a `BufferSlice` that points to a struct, and returns a `BufferSlice` that points to -/// a specific field of that struct. -#[macro_export] -macro_rules! buffer_slice_field { - ($slice:expr, $field:ident) => { - // TODO: add #[allow(unsafe_code)] when that's allowed - unsafe { $slice.slice_custom(|s| &s.$field) } - }; -} |