use std::ops::Range;
use buffer::BufferSlice;
use buffer::sys::UnsafeBuffer;
use device::DeviceOwned;
use device::Queue;
use image::ImageAccess;
use memory::Content;
use sync::AccessError;
use SafeDeref;
use VulkanObject;
pub unsafe trait Buffer {
type Access: BufferAccess;
fn access(self) -> Self::Access;
fn size(&self) -> usize;
#[inline]
fn len(&self) -> usize where Self: TypedBuffer, Self::Content: Content {
self.size() / <Self::Content as Content>::indiv_size()
}
#[inline]
fn slice<T>(self, range: Range<usize>) -> Option<BufferSlice<[T], Self>>
where Self: Sized + TypedBuffer<Content = [T]>
{
BufferSlice::slice(self.into_buffer_slice(), range)
}
#[inline]
fn into_buffer_slice(self) -> BufferSlice<Self::Content, Self>
where Self: Sized + TypedBuffer
{
BufferSlice::from_typed_buffer(self)
}
#[inline]
fn index<T>(self, index: usize) -> Option<BufferSlice<[T], Self>>
where Self: Sized + TypedBuffer<Content = [T]>
{
self.slice(index .. (index + 1))
}
}
pub unsafe trait TypedBuffer: Buffer {
type Content: ?Sized;
}
pub unsafe trait BufferAccess: DeviceOwned {
fn inner(&self) -> BufferInner;
#[inline]
fn size(&self) -> usize {
self.inner().buffer.size()
}
#[inline]
fn len(&self) -> usize where Self: TypedBufferAccess, Self::Content: Content {
self.size() / <Self::Content as Content>::indiv_size()
}
#[inline]
fn as_buffer_slice(&self) -> BufferSlice<Self::Content, &Self>
where Self: Sized + TypedBufferAccess
{
BufferSlice::from_typed_buffer_access(self)
}
#[inline]
fn slice<T>(&self, range: Range<usize>) -> Option<BufferSlice<[T], &Self>>
where Self: Sized + TypedBufferAccess<Content = [T]>
{
BufferSlice::slice(self.as_buffer_slice(), range)
}
#[inline]
fn into_buffer_slice(self) -> BufferSlice<Self::Content, Self>
where Self: Sized + TypedBufferAccess
{
BufferSlice::from_typed_buffer_access(self)
}
#[inline]
fn index<T>(&self, index: usize) -> Option<BufferSlice<[T], &Self>>
where Self: Sized + TypedBufferAccess<Content = [T]>
{
self.slice(index .. (index + 1))
}
fn conflicts_buffer(&self, self_offset: usize, self_size: usize,
other: &BufferAccess, other_offset: usize, other_size: usize)
-> bool
{
debug_assert!(self_size <= self.size());
if self.inner().buffer.internal_object() != other.inner().buffer.internal_object() {
return false;
}
let self_offset = self_offset + self.inner().offset;
let other_offset = other_offset + other.inner().offset;
if self_offset < other_offset && self_offset + self_size <= other_offset {
return false;
}
if other_offset < self_offset && other_offset + other_size <= self_offset {
return false;
}
true
}
fn conflicts_image(&self, self_offset: usize, self_size: usize, other: &ImageAccess,
other_first_layer: u32, other_num_layers: u32, other_first_mipmap: u32,
other_num_mipmaps: u32) -> bool
{
let other_key = other.conflict_key(other_first_layer, other_num_layers, other_first_mipmap,
other_num_mipmaps);
self.conflict_key(self_offset, self_size) == other_key
}
fn conflict_key(&self, self_offset: usize, self_size: usize) -> u64 {
unimplemented!()
}
#[inline]
fn conflicts_buffer_all(&self, other: &BufferAccess) -> bool {
self.conflicts_buffer(0, self.size(), other, 0, other.size())
}
#[inline]
fn conflicts_image_all(&self, other: &ImageAccess) -> bool {
self.conflicts_image(0, self.size(), other, 0, other.dimensions().array_layers(), 0,
other.mipmap_levels())
}
#[inline]
fn conflict_key_all(&self) -> u64 {
self.conflict_key(0, self.size())
}
fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError>;
unsafe fn increase_gpu_lock(&self);
}
#[derive(Copy, Clone, Debug)]
pub struct BufferInner<'a> {
pub buffer: &'a UnsafeBuffer,
pub offset: usize,
}
unsafe impl<T> BufferAccess for T where T: SafeDeref, T::Target: BufferAccess {
#[inline]
fn inner(&self) -> BufferInner {
(**self).inner()
}
#[inline]
fn size(&self) -> usize {
(**self).size()
}
#[inline]
fn conflicts_buffer(&self, self_offset: usize, self_size: usize,
other: &BufferAccess, other_offset: usize, other_size: usize) -> bool
{
(**self).conflicts_buffer(self_offset, self_size, other, other_offset, other_size)
}
#[inline]
fn conflict_key(&self, self_offset: usize, self_size: usize) -> u64 {
(**self).conflict_key(self_offset, self_size)
}
#[inline]
fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> {
(**self).try_gpu_lock(exclusive_access, queue)
}
#[inline]
unsafe fn increase_gpu_lock(&self) {
(**self).increase_gpu_lock()
}
}
pub unsafe trait TypedBufferAccess: BufferAccess {
type Content: ?Sized;
}
unsafe impl<T> TypedBufferAccess for T where T: SafeDeref, T::Target: TypedBufferAccess {
type Content = <T::Target as TypedBufferAccess>::Content;
}