mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-23 15:24:25 +00:00
Move BufferSlice to its own module
This commit is contained in:
parent
f14825dd54
commit
fe68323b6c
@ -58,23 +58,11 @@
|
||||
//! Using uniform/storage texel buffers requires creating a *buffer view*. See the `view` module
|
||||
//! for how to create a buffer view.
|
||||
//!
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
|
||||
use buffer::traits::TrackedBuffer;
|
||||
use buffer::traits::SubmitInfos;
|
||||
use buffer::traits::PipelineBarrierRequest;
|
||||
use device::Queue;
|
||||
|
||||
use sync::AccessFlagBits;
|
||||
use sync::Fence;
|
||||
use sync::PipelineStages;
|
||||
|
||||
pub use self::cpu_access::CpuAccessibleBuffer;
|
||||
pub use self::device_local::DeviceLocalBuffer;
|
||||
pub use self::immutable::ImmutableBuffer;
|
||||
pub use self::slice::BufferSlice;
|
||||
pub use self::sys::BufferCreationError;
|
||||
pub use self::sys::Usage as BufferUsage;
|
||||
pub use self::traits::Buffer;
|
||||
@ -85,260 +73,7 @@ pub use self::view::BufferView;
|
||||
pub mod cpu_access;
|
||||
pub mod device_local;
|
||||
pub mod immutable;
|
||||
mod slice;
|
||||
pub mod sys;
|
||||
pub mod traits;
|
||||
pub mod view;
|
||||
|
||||
/// A subpart of a buffer.
|
||||
///
|
||||
/// This object doesn't correspond to any Vulkan object. It exists for API convenience.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Creating a slice:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::buffer::BufferSlice;
|
||||
/// # let buffer: std::sync::Arc<vulkano::buffer::DeviceLocalBuffer<[u8]>> =
|
||||
/// unsafe { std::mem::uninitialized() };
|
||||
/// let _slice = BufferSlice::from(&buffer);
|
||||
/// ```
|
||||
///
|
||||
/// Selecting a slice of a buffer that contains `[T]`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::buffer::BufferSlice;
|
||||
/// # let buffer: std::sync::Arc<vulkano::buffer::DeviceLocalBuffer<[u8]>> =
|
||||
/// unsafe { std::mem::uninitialized() };
|
||||
/// let _slice = BufferSlice::from(&buffer).slice(12 .. 14).unwrap();
|
||||
/// ```
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub struct BufferSlice<T: ?Sized, B> {
|
||||
marker: PhantomData<T>,
|
||||
resource: B,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
/// 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) -> usize {
|
||||
self.offset
|
||||
}
|
||||
|
||||
/// Returns the size of that slice in bytes.
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
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: &T = mem::zeroed();
|
||||
let result = f(data);
|
||||
let size = mem::size_of_val(result);
|
||||
let result = result as *const R as *const () as usize;
|
||||
|
||||
assert!(result <= self.size());
|
||||
assert!(result + size <= self.size());
|
||||
|
||||
BufferSlice {
|
||||
marker: PhantomData,
|
||||
resource: self.resource,
|
||||
offset: self.offset + result,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, B> BufferSlice<[T], B> {
|
||||
/// Returns the number of elements in this slice.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
debug_assert_eq!(self.size() % mem::size_of::<T>(), 0);
|
||||
self.size() / mem::size_of::<T>()
|
||||
}
|
||||
|
||||
/// Reduces the slice to just one element of the array.
|
||||
///
|
||||
/// Returns `None` if out of range.
|
||||
#[inline]
|
||||
pub fn index(self, index: usize) -> 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>(),
|
||||
size: mem::size_of::<T>(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Reduces the slice to just a range of the array.
|
||||
///
|
||||
/// Returns `None` if out of range.
|
||||
#[inline]
|
||||
pub fn slice(self, range: Range<usize>) -> 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>(),
|
||||
size: (range.end - range.start) * mem::size_of::<T>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized, B> Buffer for BufferSlice<T, B> where B: Buffer {
|
||||
#[inline]
|
||||
fn inner(&self) -> BufferInner {
|
||||
let inner = self.resource.inner();
|
||||
BufferInner {
|
||||
buffer: inner.buffer,
|
||||
offset: inner.offset + self.offset,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized, B> TypedBuffer for BufferSlice<T, B> where B: Buffer, T: 'static {
|
||||
type Content = T;
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized, B, S> TrackedBuffer<S> for BufferSlice<T, B> where B: TrackedBuffer<S> {
|
||||
#[inline]
|
||||
fn transition(&self, states: &mut S, num_command: usize, offset: usize, size: usize,
|
||||
write: bool, stage: PipelineStages, access: AccessFlagBits)
|
||||
-> Option<PipelineBarrierRequest>
|
||||
{
|
||||
debug_assert!(size < self.size);
|
||||
let mut rq = self.resource.transition(states, num_command, offset + self.offset,
|
||||
size, write, stage, access);
|
||||
|
||||
if let Some(ref mut rq) = rq {
|
||||
if let Some(ref mut mb) = rq.memory_barrier {
|
||||
mb.offset -= self.offset as isize;
|
||||
}
|
||||
}
|
||||
|
||||
rq
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finish(&self, in_s: &mut S, out: &mut S) -> Option<PipelineBarrierRequest> {
|
||||
let mut rq = self.resource.finish(in_s, out);
|
||||
|
||||
if let Some(ref mut rq) = rq {
|
||||
if let Some(ref mut mb) = rq.memory_barrier {
|
||||
mb.offset -= self.offset as isize;
|
||||
}
|
||||
}
|
||||
|
||||
rq
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn on_submit<F>(&self, states: &S, queue: &Arc<Queue>, fence: F) -> SubmitInfos
|
||||
where F: FnOnce() -> Arc<Fence>
|
||||
{
|
||||
self.resource.on_submit(states, queue, fence)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, B> From<B> for BufferSlice<T, B>
|
||||
where B: TypedBuffer<Content = T>, T: 'static
|
||||
{
|
||||
#[inline]
|
||||
fn from(r: B) -> BufferSlice<T, B> {
|
||||
let size = r.size();
|
||||
|
||||
BufferSlice {
|
||||
marker: PhantomData,
|
||||
resource: r,
|
||||
offset: 0,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) }
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// TODO: restore these tests
|
||||
/*use std::mem;
|
||||
|
||||
use buffer::Usage;
|
||||
use buffer::Buffer;
|
||||
use buffer::BufferView;
|
||||
use buffer::BufferViewCreationError;
|
||||
use memory::DeviceLocal;
|
||||
|
||||
#[test]
|
||||
fn create() {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let _ = Buffer::<[i8; 16], _>::new(&device, &Usage::all(), DeviceLocal, &queue).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_len() {
|
||||
let (device, queue) = gfx_dev_and_queue!();
|
||||
|
||||
let b = Buffer::<[i16], _>::array(&device, 12, &Usage::all(),
|
||||
DeviceLocal, &queue).unwrap();
|
||||
assert_eq!(b.len(), 12);
|
||||
assert_eq!(b.size(), 12 * mem::size_of::<i16>());
|
||||
}*/
|
||||
}
|
||||
|
250
vulkano/src/buffer/slice.rs
Normal file
250
vulkano/src/buffer/slice.rs
Normal file
@ -0,0 +1,250 @@
|
||||
// Copyright (c) 2016 The vulkano developers
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||
// license <LICENSE-MIT or http://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 std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
|
||||
use buffer::traits::Buffer;
|
||||
use buffer::traits::BufferInner;
|
||||
use buffer::traits::TypedBuffer;
|
||||
use buffer::traits::TrackedBuffer;
|
||||
use buffer::traits::SubmitInfos;
|
||||
use buffer::traits::PipelineBarrierRequest;
|
||||
use device::Queue;
|
||||
|
||||
use sync::AccessFlagBits;
|
||||
use sync::Fence;
|
||||
use sync::PipelineStages;
|
||||
|
||||
/// A subpart of a buffer.
|
||||
///
|
||||
/// This object doesn't correspond to any Vulkan object. It exists for API convenience.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Creating a slice:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::buffer::BufferSlice;
|
||||
/// # let buffer: std::sync::Arc<vulkano::buffer::DeviceLocalBuffer<[u8]>> =
|
||||
/// unsafe { std::mem::uninitialized() };
|
||||
/// let _slice = BufferSlice::from(&buffer);
|
||||
/// ```
|
||||
///
|
||||
/// Selecting a slice of a buffer that contains `[T]`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use vulkano::buffer::BufferSlice;
|
||||
/// # let buffer: std::sync::Arc<vulkano::buffer::DeviceLocalBuffer<[u8]>> =
|
||||
/// unsafe { std::mem::uninitialized() };
|
||||
/// let _slice = BufferSlice::from(&buffer).slice(12 .. 14).unwrap();
|
||||
/// ```
|
||||
///
|
||||
#[derive(Clone)]
|
||||
pub struct BufferSlice<T: ?Sized, B> {
|
||||
marker: PhantomData<T>,
|
||||
resource: B,
|
||||
offset: usize,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl<T: ?Sized, B> BufferSlice<T, B> {
|
||||
/// 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) -> usize {
|
||||
self.offset
|
||||
}
|
||||
|
||||
/// Returns the size of that slice in bytes.
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
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: &T = mem::zeroed();
|
||||
let result = f(data);
|
||||
let size = mem::size_of_val(result);
|
||||
let result = result as *const R as *const () as usize;
|
||||
|
||||
assert!(result <= self.size());
|
||||
assert!(result + size <= self.size());
|
||||
|
||||
BufferSlice {
|
||||
marker: PhantomData,
|
||||
resource: self.resource,
|
||||
offset: self.offset + result,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, B> BufferSlice<[T], B> {
|
||||
/// Returns the number of elements in this slice.
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
debug_assert_eq!(self.size() % mem::size_of::<T>(), 0);
|
||||
self.size() / mem::size_of::<T>()
|
||||
}
|
||||
|
||||
/// Reduces the slice to just one element of the array.
|
||||
///
|
||||
/// Returns `None` if out of range.
|
||||
#[inline]
|
||||
pub fn index(self, index: usize) -> 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>(),
|
||||
size: mem::size_of::<T>(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Reduces the slice to just a range of the array.
|
||||
///
|
||||
/// Returns `None` if out of range.
|
||||
#[inline]
|
||||
pub fn slice(self, range: Range<usize>) -> 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>(),
|
||||
size: (range.end - range.start) * mem::size_of::<T>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized, B> Buffer for BufferSlice<T, B> where B: Buffer {
|
||||
#[inline]
|
||||
fn inner(&self) -> BufferInner {
|
||||
let inner = self.resource.inner();
|
||||
BufferInner {
|
||||
buffer: inner.buffer,
|
||||
offset: inner.offset + self.offset,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized, B> TypedBuffer for BufferSlice<T, B> where B: Buffer, T: 'static {
|
||||
type Content = T;
|
||||
}
|
||||
|
||||
unsafe impl<T: ?Sized, B, S> TrackedBuffer<S> for BufferSlice<T, B> where B: TrackedBuffer<S> {
|
||||
#[inline]
|
||||
fn transition(&self, states: &mut S, num_command: usize, offset: usize, size: usize,
|
||||
write: bool, stage: PipelineStages, access: AccessFlagBits)
|
||||
-> Option<PipelineBarrierRequest>
|
||||
{
|
||||
debug_assert!(size < self.size);
|
||||
let mut rq = self.resource.transition(states, num_command, offset + self.offset,
|
||||
size, write, stage, access);
|
||||
|
||||
if let Some(ref mut rq) = rq {
|
||||
if let Some(ref mut mb) = rq.memory_barrier {
|
||||
mb.offset -= self.offset as isize;
|
||||
}
|
||||
}
|
||||
|
||||
rq
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finish(&self, in_s: &mut S, out: &mut S) -> Option<PipelineBarrierRequest> {
|
||||
let mut rq = self.resource.finish(in_s, out);
|
||||
|
||||
if let Some(ref mut rq) = rq {
|
||||
if let Some(ref mut mb) = rq.memory_barrier {
|
||||
mb.offset -= self.offset as isize;
|
||||
}
|
||||
}
|
||||
|
||||
rq
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn on_submit<F>(&self, states: &S, queue: &Arc<Queue>, fence: F) -> SubmitInfos
|
||||
where F: FnOnce() -> Arc<Fence>
|
||||
{
|
||||
self.resource.on_submit(states, queue, fence)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized, B> From<B> for BufferSlice<T, B>
|
||||
where B: TypedBuffer<Content = T>, T: 'static
|
||||
{
|
||||
#[inline]
|
||||
fn from(r: B) -> BufferSlice<T, B> {
|
||||
let size = r.size();
|
||||
|
||||
BufferSlice {
|
||||
marker: PhantomData,
|
||||
resource: r,
|
||||
offset: 0,
|
||||
size: size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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) }
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user