1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use std::sync::Arc;

use erupt::vk;
#[cfg(feature = "tracing")]
use tracing1::error;

use crate::context::Context;
use crate::{AscheError, Result};

/// A handle of a binary semaphore.
#[derive(Debug, Clone, Copy)]
pub struct BinarySemaphoreHandle(pub(crate) vk::Semaphore);

/// A handle of a timeline semaphore.
#[derive(Debug, Clone, Copy)]
pub struct TimelineSemaphoreHandle(pub(crate) vk::Semaphore);

/// A binary semaphore.
#[derive(Debug, Clone)]
pub struct BinarySemaphore {
    raw: vk::Semaphore,
    context: Arc<Context>,
}

impl Drop for BinarySemaphore {
    fn drop(&mut self) {
        unsafe {
            self.context.device.destroy_semaphore(Some(self.raw), None);
        };
    }
}

impl BinarySemaphore {
    /// Creates a new semaphore.
    pub(crate) fn new(context: Arc<Context>, semaphore: vk::Semaphore) -> Self {
        Self {
            context,
            raw: semaphore,
        }
    }

    /// Returns the handle of the binary semaphore.
    pub fn handle(&self) -> BinarySemaphoreHandle {
        BinarySemaphoreHandle(self.raw)
    }

    /// The raw Vulkan semaphore handle.
    #[inline]
    pub(crate) fn raw(&self) -> vk::Semaphore {
        self.raw
    }
}

/// A semaphore that uses the timeline feature.
#[derive(Debug)]
pub struct TimelineSemaphore {
    pub(crate) raw: vk::Semaphore,
    context: Arc<Context>,
}

impl Drop for TimelineSemaphore {
    fn drop(&mut self) {
        unsafe {
            self.context.device.destroy_semaphore(Some(self.raw), None);
        };
    }
}

impl TimelineSemaphore {
    /// Creates a new timeline semaphore.
    pub(crate) fn new(context: Arc<Context>, semaphore: vk::Semaphore) -> Self {
        Self {
            context,
            raw: semaphore,
        }
    }

    /// Returns the handle of the timeline semaphore.
    pub fn handle(&self) -> TimelineSemaphoreHandle {
        TimelineSemaphoreHandle(self.raw)
    }

    /// Query the timeline value.
    #[cfg_attr(feature = "profiling", profiling::function)]
    pub unsafe fn query_value(&self) -> Result<u64> {
        let value = self
            .context
            .device
            .get_semaphore_counter_value(self.raw)
            .map_err(|err| {
                #[cfg(feature = "tracing")]
                error!("Unable to get a semaphore counter value: {}", err);
                AscheError::VkResult(err)
            })?;
        Ok(value)
    }

    /// Sets the timeline value.
    #[cfg_attr(feature = "profiling", profiling::function)]
    pub unsafe fn set_value(&self, timeline_value: u64) -> Result<()> {
        let signal_info = vk::SemaphoreSignalInfoBuilder::new()
            .semaphore(self.raw)
            .value(timeline_value);

        self.context
            .device
            .signal_semaphore(&signal_info)
            .map_err(|err| {
                #[cfg(feature = "tracing")]
                error!("Unable to signal a semaphore: {}", err);
                AscheError::VkResult(err)
            })?;

        Ok(())
    }

    /// Wait for the given timeline value.
    #[cfg_attr(feature = "profiling", profiling::function)]
    pub unsafe fn wait_for_value(&self, timeline_value: u64) -> Result<()> {
        let semaphores = [self.raw];
        let timeline_values = [timeline_value];
        let wait_info = vk::SemaphoreWaitInfoBuilder::new()
            .semaphores(&semaphores)
            .values(&timeline_values);

        // 10 sec timeout
        self.context
            .device
            .wait_semaphores(&wait_info, 10000000000)
            .map_err(|err| {
                #[cfg(feature = "tracing")]
                error!("Unable to wait for a semaphore: {}", err);
                AscheError::VkResult(err)
            })?;

        Ok(())
    }
}