Add CpuAccessibleBuffer

This commit is contained in:
Pierre Krieger 2016-03-23 11:01:43 +01:00
parent 6ef29608e4
commit 8cc816e9f3
3 changed files with 154 additions and 2 deletions

View File

@ -0,0 +1,151 @@
use std::marker::PhantomData;
use std::mem;
use std::ops::Range;
use std::sync::Arc;
use std::sync::Mutex;
use smallvec::SmallVec;
use buffer::traits::Buffer;
use buffer::unsafe_buffer::UnsafeBuffer;
use buffer::unsafe_buffer::Usage;
use command_buffer::Submission;
use device::Device;
use instance::QueueFamily;
use memory::Content;
use memory::CpuAccess;
use memory::DeviceMemory;
use memory::MappedDeviceMemory;
use sync::Sharing;
use OomError;
pub struct CpuAccessibleBuffer<T: ?Sized> {
// Inner content.
inner: UnsafeBuffer,
memory: MappedDeviceMemory,
// Queue families allowed to access this buffer.
queue_families: SmallVec<[u32; 4]>,
latest_submission: Mutex<Option<Arc<Submission>>>,
marker: PhantomData<*const T>,
}
impl<T> CpuAccessibleBuffer<T> {
#[inline]
pub fn new<'a, I>(device: &Arc<Device>, usage: &Usage, queue_families: I)
-> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
where I: IntoIterator<Item = QueueFamily<'a>>
{
unsafe {
CpuAccessibleBuffer::raw(device, mem::size_of::<T>(), usage, queue_families)
}
}
}
impl<T> CpuAccessibleBuffer<[T]> {
#[inline]
pub fn array<'a, I>(device: &Arc<Device>, len: usize, usage: &Usage, queue_families: I)
-> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
where I: IntoIterator<Item = QueueFamily<'a>>
{
unsafe {
CpuAccessibleBuffer::raw(device, len * mem::size_of::<T>(), usage, queue_families)
}
}
}
impl<T: ?Sized> CpuAccessibleBuffer<T> {
pub unsafe fn raw<'a, I>(device: &Arc<Device>, size: usize, usage: &Usage, queue_families: I)
-> Result<Arc<CpuAccessibleBuffer<T>>, OomError>
where I: IntoIterator<Item = QueueFamily<'a>>
{
let queue_families = queue_families.into_iter().map(|f| f.id())
.collect::<SmallVec<[u32; 4]>>();
let (buffer, mem_reqs) = {
let sharing = if queue_families.len() >= 2 {
Sharing::Concurrent(queue_families.iter().cloned())
} else {
Sharing::Exclusive
};
try!(UnsafeBuffer::new(device, size, &usage, sharing))
};
let mem_ty = device.physical_device().memory_types()
.filter(|t| (mem_reqs.memory_type_bits & (1 << t.id())) != 0)
.filter(|t| t.is_host_visible())
.next().unwrap(); // Vk specs guarantee that this can't fail
// note: alignment doesn't need to be checked because allocating memory is guaranteed to
// fulfill any alignment requirement
let mem = try!(DeviceMemory::alloc_and_map(device, &mem_ty, mem_reqs.size));
try!(buffer.bind_memory(mem.memory(), 0 .. mem_reqs.size));
Ok(Arc::new(CpuAccessibleBuffer {
inner: buffer,
memory: mem,
queue_families: queue_families,
latest_submission: Mutex::new(None),
marker: PhantomData,
}))
}
}
impl<T: ?Sized> CpuAccessibleBuffer<T> where T: Content + 'static {
fn read(&self, timeout_ns: u64) -> CpuAccess<T> { // FIXME: error
// FIXME: correct implementation
unsafe { self.memory.read() }
}
fn try_read(&self) -> Option<CpuAccess<T>> {
// FIXME: correct implementation
unsafe { Some(self.memory.read()) }
}
fn write(&self, timeout_ns: u64) -> CpuAccess<T> { // FIXME: error
// FIXME: correct implementation
unsafe { self.memory.write() }
}
fn try_write(&self) -> Option<CpuAccess<T>> {
// FIXME: correct implementation
unsafe { Some(self.memory.write()) }
}
}
unsafe impl<T: ?Sized> Buffer for CpuAccessibleBuffer<T> {
#[inline]
fn inner_buffer(&self) -> &UnsafeBuffer {
&self.inner
}
fn needs_fence(&self, _: bool, _: Range<usize>) -> Option<bool> {
Some(true)
}
unsafe fn gpu_access(&self, write: bool, _: Range<usize>, submission: &Arc<Submission>)
-> Vec<Arc<Submission>>
{
let queue_id = submission.queue().family().id();
if self.queue_families.iter().find(|&&id| id == queue_id).is_none() {
panic!()
}
let dependency = {
let mut latest_submission = self.latest_submission.lock().unwrap();
mem::replace(&mut *latest_submission, Some(submission.clone()))
};
if let Some(dependency) = dependency {
vec![dependency]
} else {
vec![]
}
}
}

View File

@ -45,6 +45,7 @@ pub use self::traits::Buffer;
pub use self::traits::TypedBuffer;
pub use self::unsafe_buffer::Usage;
pub mod cpu_access;
pub mod immutable;
pub mod staging;
pub mod traits;

View File

@ -162,12 +162,12 @@ impl MappedDeviceMemory {
}
#[inline]
pub unsafe fn read<T>(&self) -> CpuAccess<T> where T: Content + 'static {
pub unsafe fn read<T: ?Sized>(&self) -> CpuAccess<T> where T: Content + 'static {
self.write()
}
#[inline]
pub unsafe fn write<T>(&self) -> CpuAccess<T> where T: Content + 'static {
pub unsafe fn write<T: ?Sized>(&self) -> CpuAccess<T> where T: Content + 'static {
let vk = self.memory.device().pointers();
let pointer = T::ref_from_ptr(self.pointer, self.memory.size()).unwrap(); // TODO: error