mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-22 06:45:23 +00:00
Better synchronization handling
This commit is contained in:
parent
cdc573a5d7
commit
c644b76346
@ -25,6 +25,7 @@ use device::Queue;
|
||||
use memory::CpuAccessible;
|
||||
use memory::CpuWriteAccessible;
|
||||
use memory::ChunkProperties;
|
||||
use memory::ChunkRange;
|
||||
use memory::MemorySource;
|
||||
use memory::MemorySourceChunk;
|
||||
use sync::Fence;
|
||||
@ -235,7 +236,7 @@ unsafe impl<T: ?Sized, M> Resource for Buffer<T, M> where M: MemorySourceChunk {
|
||||
semaphore: Option<Arc<Semaphore>>)
|
||||
-> (Option<Arc<Semaphore>>, Option<Arc<Semaphore>>)
|
||||
{
|
||||
let out = self.inner.memory.gpu_access(write, 0, self.size(), queue, fence, semaphore);
|
||||
let out = self.inner.memory.gpu_access(write, ChunkRange::All, queue, fence, semaphore);
|
||||
(out, None)
|
||||
}
|
||||
}
|
||||
@ -401,7 +402,7 @@ unsafe impl<'a, T: ?Sized + 'a, M: 'a> Resource for BufferSlice<'a, T, M>
|
||||
semaphore: Option<Arc<Semaphore>>)
|
||||
-> (Option<Arc<Semaphore>>, Option<Arc<Semaphore>>)
|
||||
{
|
||||
let out = self.inner.memory.gpu_access(write, self.offset, self.size,
|
||||
let out = self.inner.memory.gpu_access(write, ChunkRange::Range { offset: self.offset, size: self.size },
|
||||
queue, fence, semaphore);
|
||||
(out, None)
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ use device::Device;
|
||||
use device::Queue;
|
||||
use formats::FormatMarker;
|
||||
use memory::ChunkProperties;
|
||||
use memory::ChunkRange;
|
||||
use memory::MemorySource;
|
||||
use memory::MemorySourceChunk;
|
||||
use sync::Fence;
|
||||
@ -392,7 +393,7 @@ unsafe impl<Ty, F, M> Resource for Image<Ty, F, M>
|
||||
semaphore: Option<Arc<Semaphore>>)
|
||||
-> (Option<Arc<Semaphore>>, Option<Arc<Semaphore>>)
|
||||
{
|
||||
let out = self.memory.gpu_access(write, 0, self.memory.size(), queue, fence, semaphore);
|
||||
let out = self.memory.gpu_access(write, ChunkRange::All, queue, fence, semaphore);
|
||||
// FIXME: if the image is in its initial transition phase, we need to return a second semaphore
|
||||
(out, None)
|
||||
}
|
||||
|
@ -118,9 +118,6 @@ pub unsafe trait MemorySourceChunk {
|
||||
/// Returns the properties of this chunk.
|
||||
fn properties(&self) -> ChunkProperties;
|
||||
|
||||
/// Size in bytes of the chunk.
|
||||
fn size(&self) -> usize;
|
||||
|
||||
/// Returns true if the `gpu_access` function should be passed a fence.
|
||||
#[inline]
|
||||
fn requires_fence(&self) -> bool {
|
||||
@ -140,7 +137,7 @@ pub unsafe trait MemorySourceChunk {
|
||||
/// `write` indicates whether the GPU will write to the memory. If `false`, then it will only
|
||||
/// be written.
|
||||
///
|
||||
/// `offset` and `size` indicate the part of the chunk that is concerned.
|
||||
/// `range` indicates the part of the chunk that is concerned.
|
||||
///
|
||||
/// `queue` is the queue where the command buffer that accesses the memory will be submitted.
|
||||
/// If the `gpu_access` function submits something to that queue, it will thus be submitted
|
||||
@ -158,7 +155,7 @@ pub unsafe trait MemorySourceChunk {
|
||||
/// return a semaphore that must be waited upon by the GPU before the access can start. The
|
||||
/// semaphore being returned is usually one that has been previously passed to this function,
|
||||
/// but it doesn't need to be the case.
|
||||
fn gpu_access(&self, write: bool, offset: usize, size: usize, queue: &mut Queue,
|
||||
fn gpu_access(&self, write: bool, range: ChunkRange, queue: &mut Queue,
|
||||
fence: Option<Arc<Fence>>, semaphore: Option<Arc<Semaphore>>)
|
||||
-> Option<Arc<Semaphore>>;
|
||||
|
||||
@ -171,6 +168,11 @@ pub unsafe trait MemorySourceChunk {
|
||||
fn may_alias(&self) -> bool;
|
||||
}
|
||||
|
||||
pub enum ChunkRange {
|
||||
All,
|
||||
Range { offset: usize, size: usize }
|
||||
}
|
||||
|
||||
pub enum ChunkProperties<'a> {
|
||||
Regular {
|
||||
memory: &'a DeviceMemory,
|
||||
|
@ -14,6 +14,7 @@ use memory::MemorySource;
|
||||
use memory::MemorySourceChunk;
|
||||
use memory::DeviceMemory;
|
||||
use memory::MappedDeviceMemory;
|
||||
use memory::ChunkRange;
|
||||
use sync::Fence;
|
||||
use sync::Semaphore;
|
||||
|
||||
@ -68,12 +69,7 @@ pub struct DeviceLocalChunk {
|
||||
|
||||
unsafe impl MemorySourceChunk for DeviceLocalChunk {
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
self.mem.size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn gpu_access(&self, _write: bool, _offset: usize, _size: usize, _: &mut Queue,
|
||||
fn gpu_access(&self, _write: bool, _range: ChunkRange, _: &mut Queue,
|
||||
_: Option<Arc<Fence>>, mut semaphore: Option<Arc<Semaphore>>)
|
||||
-> Option<Arc<Semaphore>>
|
||||
{
|
||||
@ -153,12 +149,7 @@ pub struct HostVisibleChunk {
|
||||
|
||||
unsafe impl MemorySourceChunk for HostVisibleChunk {
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
self.mem.memory().size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn gpu_access(&self, _write: bool, _offset: usize, _size: usize, _: &mut Queue,
|
||||
fn gpu_access(&self, _write: bool, _range: ChunkRange, _: &mut Queue,
|
||||
fence: Option<Arc<Fence>>, mut semaphore: Option<Arc<Semaphore>>)
|
||||
-> Option<Arc<Semaphore>>
|
||||
{
|
||||
|
@ -3,6 +3,7 @@ use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
use device::Device;
|
||||
use device::Queue;
|
||||
@ -12,6 +13,7 @@ use image::ImagePrototype;
|
||||
use image::Type2d;
|
||||
use image::Usage as ImageUsage;
|
||||
use memory::ChunkProperties;
|
||||
use memory::ChunkRange;
|
||||
use memory::MemorySourceChunk;
|
||||
use swapchain::CompositeAlpha;
|
||||
use swapchain::PresentMode;
|
||||
@ -34,6 +36,8 @@ pub struct Swapchain {
|
||||
device: Arc<Device>,
|
||||
surface: Arc<Surface>,
|
||||
swapchain: vk::SwapchainKHR,
|
||||
|
||||
images_semaphores: Mutex<Vec<Option<Arc<Semaphore>>>>,
|
||||
}
|
||||
|
||||
impl Swapchain {
|
||||
@ -111,6 +115,7 @@ impl Swapchain {
|
||||
device: device.clone(),
|
||||
surface: surface.clone(),
|
||||
swapchain: swapchain,
|
||||
images_semaphores: Mutex::new(Vec::new()),
|
||||
});
|
||||
|
||||
let images = unsafe {
|
||||
@ -127,11 +132,18 @@ impl Swapchain {
|
||||
images
|
||||
};
|
||||
|
||||
let images = images.into_iter().map(|image| unsafe {
|
||||
let mem = SwapchainAllocatedChunk { swapchain: swapchain.clone() };
|
||||
let images = images.into_iter().enumerate().map(|(id, image)| unsafe {
|
||||
let mem = SwapchainAllocatedChunk { swapchain: swapchain.clone(), id: id };
|
||||
Image::from_raw_unowned(&device, image, mem, sharing.clone(), usage, dimensions, (), 1)
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
{
|
||||
let mut semaphores = swapchain.images_semaphores.lock().unwrap();
|
||||
for _ in 0 .. images.len() {
|
||||
semaphores.push(None);
|
||||
}
|
||||
}
|
||||
|
||||
Ok((swapchain, images))
|
||||
}
|
||||
|
||||
@ -146,18 +158,26 @@ impl Swapchain {
|
||||
let vk = self.device.pointers();
|
||||
|
||||
unsafe {
|
||||
let semaphore = Semaphore::new(&self.device).unwrap(); // TODO: error
|
||||
|
||||
let mut out = mem::uninitialized();
|
||||
let r = try!(check_errors(vk.AcquireNextImageKHR(self.device.internal_object(),
|
||||
self.swapchain, 1000000, 0, 0, // TODO: timeout
|
||||
self.swapchain, 1000000,
|
||||
semaphore.internal_object(), 0, // TODO: timeout
|
||||
&mut out)));
|
||||
|
||||
match r {
|
||||
Success::Success => Ok(out as usize),
|
||||
Success::Suboptimal => Ok(out as usize), // TODO: give that info to the user
|
||||
Success::NotReady => Err(AcquireError::Timeout),
|
||||
Success::Timeout => Err(AcquireError::Timeout),
|
||||
let id = match r {
|
||||
Success::Success => out as usize,
|
||||
Success::Suboptimal => out as usize, // TODO: give that info to the user
|
||||
Success::NotReady => return Err(AcquireError::Timeout),
|
||||
Success::Timeout => return Err(AcquireError::Timeout),
|
||||
s => panic!("unexpected success value: {:?}", s)
|
||||
}
|
||||
};
|
||||
|
||||
let mut images_semaphores = self.images_semaphores.lock().unwrap();
|
||||
images_semaphores[id] = Some(semaphore);
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,16 +190,23 @@ impl Swapchain {
|
||||
/// swapchain.
|
||||
pub fn present(&self, queue: &mut Queue, index: usize) -> Result<(), OomError> { // FIXME: wrong error
|
||||
let vk = self.device.pointers();
|
||||
let index = index as u32;
|
||||
|
||||
let wait_semaphore = {
|
||||
let mut images_semaphores = self.images_semaphores.lock().unwrap();
|
||||
images_semaphores[index].take()
|
||||
};
|
||||
|
||||
// FIXME: the semaphore will be destroyed ; need to return it
|
||||
|
||||
unsafe {
|
||||
let mut result = mem::uninitialized();
|
||||
|
||||
let index = index as u32;
|
||||
let infos = vk::PresentInfoKHR {
|
||||
sType: vk::STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||
pNext: ptr::null(),
|
||||
waitSemaphoreCount: 0,
|
||||
pWaitSemaphores: ptr::null(),
|
||||
waitSemaphoreCount: if let Some(_) = wait_semaphore { 1 } else { 0 },
|
||||
pWaitSemaphores: if let Some(ref sem) = wait_semaphore { &sem.internal_object() } else { ptr::null() },
|
||||
swapchainCount: 1,
|
||||
pSwapchains: &self.swapchain,
|
||||
pImageIndices: &index,
|
||||
@ -243,8 +270,8 @@ impl From<Error> for AcquireError {
|
||||
|
||||
/// "Dummy" object used for images that indicates that they were allocated as part of a swapchain.
|
||||
pub struct SwapchainAllocatedChunk {
|
||||
// the dummy object is also used to keep ownership of the swapchain
|
||||
swapchain: Arc<Swapchain>,
|
||||
id: usize,
|
||||
}
|
||||
|
||||
// FIXME: needs correct synchronization as well
|
||||
@ -254,22 +281,21 @@ unsafe impl MemorySourceChunk for SwapchainAllocatedChunk {
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn requires_fence(&self) -> bool { false }
|
||||
#[inline]
|
||||
fn requires_semaphore(&self) -> bool { false }
|
||||
fn requires_semaphore(&self) -> bool { true }
|
||||
#[inline]
|
||||
fn may_alias(&self) -> bool { false }
|
||||
|
||||
#[inline]
|
||||
fn gpu_access(&self, _: bool, _: usize, _: usize, _: &mut Queue, _: Option<Arc<Fence>>,
|
||||
_: Option<Arc<Semaphore>>) -> Option<Arc<Semaphore>>
|
||||
fn gpu_access(&self, _: bool, _: ChunkRange, _: &mut Queue, _: Option<Arc<Fence>>,
|
||||
post_semaphore: Option<Arc<Semaphore>>) -> Option<Arc<Semaphore>>
|
||||
{
|
||||
None
|
||||
assert!(post_semaphore.is_some());
|
||||
// FIXME: must also check that image has been acquired
|
||||
let mut semaphores = self.swapchain.images_semaphores.lock().unwrap();
|
||||
let pre_semaphore = mem::replace(&mut semaphores[self.id], post_semaphore);
|
||||
pre_semaphore
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user