use std::mem::MaybeUninit;
use std::ptr;
use std::sync::Arc;
use crate::check_errors;
use crate::device::Device;
use crate::device::DeviceOwned;
use crate::vk;
use crate::OomError;
use crate::SafeDeref;
use crate::VulkanObject;
#[derive(Debug)]
pub struct Semaphore<D = Arc<Device>>
where
D: SafeDeref<Target = Device>,
{
semaphore: vk::Semaphore,
device: D,
must_put_in_pool: bool,
}
impl<D> Semaphore<D>
where
D: SafeDeref<Target = Device>,
{
pub fn from_pool(device: D) -> Result<Semaphore<D>, OomError> {
let maybe_raw_sem = device.semaphore_pool().lock().unwrap().pop();
match maybe_raw_sem {
Some(raw_sem) => Ok(Semaphore {
device: device,
semaphore: raw_sem,
must_put_in_pool: true,
}),
None => {
Semaphore::alloc_impl(device, true)
}
}
}
#[inline]
pub fn alloc(device: D) -> Result<Semaphore<D>, OomError> {
Semaphore::alloc_impl(device, false)
}
fn alloc_impl(device: D, must_put_in_pool: bool) -> Result<Semaphore<D>, OomError> {
let semaphore = unsafe {
static mut INFOS: vk::SemaphoreCreateInfo = vk::SemaphoreCreateInfo {
sType: vk::STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
pNext: 0 as *const _, flags: 0, };
let vk = device.pointers();
let mut output = MaybeUninit::uninit();
check_errors(vk.CreateSemaphore(
device.internal_object(),
&INFOS,
ptr::null(),
output.as_mut_ptr(),
))?;
output.assume_init()
};
Ok(Semaphore {
device: device,
semaphore: semaphore,
must_put_in_pool: must_put_in_pool,
})
}
}
unsafe impl DeviceOwned for Semaphore {
#[inline]
fn device(&self) -> &Arc<Device> {
&self.device
}
}
unsafe impl<D> VulkanObject for Semaphore<D>
where
D: SafeDeref<Target = Device>,
{
type Object = vk::Semaphore;
const TYPE: vk::ObjectType = vk::OBJECT_TYPE_SEMAPHORE;
#[inline]
fn internal_object(&self) -> vk::Semaphore {
self.semaphore
}
}
impl<D> Drop for Semaphore<D>
where
D: SafeDeref<Target = Device>,
{
#[inline]
fn drop(&mut self) {
unsafe {
if self.must_put_in_pool {
let raw_sem = self.semaphore;
self.device.semaphore_pool().lock().unwrap().push(raw_sem);
} else {
let vk = self.device.pointers();
vk.DestroySemaphore(self.device.internal_object(), self.semaphore, ptr::null());
}
}
}
}
#[cfg(test)]
mod tests {
use crate::sync::Semaphore;
use crate::VulkanObject;
#[test]
fn semaphore_create() {
let (device, _) = gfx_dev_and_queue!();
let _ = Semaphore::alloc(device.clone());
}
#[test]
fn semaphore_pool() {
let (device, _) = gfx_dev_and_queue!();
assert_eq!(device.semaphore_pool().lock().unwrap().len(), 0);
let sem1_internal_obj = {
let sem = Semaphore::from_pool(device.clone()).unwrap();
assert_eq!(device.semaphore_pool().lock().unwrap().len(), 0);
sem.internal_object()
};
assert_eq!(device.semaphore_pool().lock().unwrap().len(), 1);
let sem2 = Semaphore::from_pool(device.clone()).unwrap();
assert_eq!(device.semaphore_pool().lock().unwrap().len(), 0);
assert_eq!(sem2.internal_object(), sem1_internal_obj);
}
}