use std::error::Error as StdError;
use std::fmt;
use std::sync::Arc;
use vulkano::buffer::{BufferAccess, CpuAccessibleBuffer};
use vulkano::buffer::cpu_access::{
ReadLock,
WriteLock,
ReadLockError,
WriteLockError
};
use framing::Image;
#[derive(Clone, Debug)]
pub struct Buffer<T> {
inner: Arc<CpuAccessibleBuffer<[T]>>,
width: usize,
height: usize
}
impl<T> Buffer<T> where T: Send + Sync + 'static {
pub fn new(
inner: Arc<CpuAccessibleBuffer<[T]>>,
width: usize,
height: usize
) -> Result<Self, BadLength> {
let expected_len = width * height;
let actual_len = inner.len();
if expected_len == actual_len {
Ok(Self {
inner,
width,
height
})
} else {
Err(BadLength {
expected_len,
actual_len
})
}
}
}
impl<T: 'static> Buffer<T> {
pub fn read(&self) -> Result<Reader<T>, ReadLockError> {
let inner = self.inner.read()?;
let (width, height) = (self.width, self.height);
Ok(Reader { inner, width, height })
}
pub fn write(&self) -> Result<Writer<T>, WriteLockError> {
let inner = self.inner.write()?;
let (width, height) = (self.width, self.height);
Ok(Writer { inner, width, height })
}
}
impl<T> Buffer<T> {
pub fn buffer(&self) -> &Arc<CpuAccessibleBuffer<[T]>> {
&self.inner
}
pub fn width(&self) -> usize { self.width }
pub fn height(&self) -> usize { self.height }
}
pub struct Reader<'a, T: 'a> {
inner: ReadLock<'a, [T]>,
width: usize,
height: usize
}
impl<'a, T: 'a> Image for Reader<'a, T> where T: Clone {
type Pixel = T;
fn width(&self) -> usize { self.width }
fn height(&self) -> usize { self.height }
unsafe fn pixel(&self, x: usize, y: usize) -> Self::Pixel {
self.inner.get_unchecked(y * self.width + x).clone()
}
}
impl<'a, T: 'a> AsRef<[T]> for Reader<'a, T> {
fn as_ref(&self) -> &[T] {
&self.inner
}
}
pub struct Writer<'a, T: 'a> {
inner: WriteLock<'a, [T]>,
width: usize,
height: usize
}
impl<'a, T: 'a> Image for Writer<'a, T> where T: Clone {
type Pixel = T;
fn width(&self) -> usize { self.width }
fn height(&self) -> usize { self.height }
unsafe fn pixel(&self, x: usize, y: usize) -> Self::Pixel {
self.inner.get_unchecked(y * self.width + x).clone()
}
}
impl<'a, T: 'a> AsRef<[T]> for Writer<'a, T> {
fn as_ref(&self) -> &[T] {
&self.inner
}
}
impl<'a, T: 'a> AsMut<[T]> for Writer<'a, T> {
fn as_mut(&mut self) -> &mut [T] {
&mut self.inner
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct BadLength {
expected_len: usize,
actual_len: usize
}
impl fmt::Display for BadLength {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"the buffer had to have {} pixels, but had {} pixels",
self.expected_len,
self.actual_len
)
}
}
impl StdError for BadLength {
fn description(&self) -> &str {
"incorrect buffer length"
}
}