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