atagen

monolith

public
Star0
Watch0
f00961b08216f587ac2ef74fe48fe69c9b901fde
1
ssh://brewery@pls.lobotomise.me:33/atagen/monolith.git

Blame: crates/render-vk/src/sync.rs

824bf02b6e55atagen2026-10-16 09:15 UTC1
use crate::device::Shared;
824bf02b6e55atagen2026-10-16 09:15 UTC2
use ash::vk;
7de49c2aa70batagen2026-10-16 09:27 UTC3
use rustix::event::{PollFd, PollFlags, poll};
824bf02b6e55atagen2026-10-16 09:15 UTC4
use smithay::backend::renderer::sync::{Fence, Interrupted};
824bf02b6e55atagen2026-10-16 09:15 UTC5
use std::fmt;
7de49c2aa70batagen2026-10-16 09:27 UTC6
use std::os::fd::{FromRawFd, OwnedFd};
7de49c2aa70batagen2026-10-16 09:27 UTC7
use std::sync::{Arc, Mutex};
7de49c2aa70batagen2026-10-16 09:27 UTC8
7de49c2aa70batagen2026-10-16 09:27 UTC9
enum State {
7de49c2aa70batagen2026-10-16 09:27 UTC10
    Pending,
7de49c2aa70batagen2026-10-16 09:27 UTC11
    /// Exporting a sync_file resets the Vulkan fence, so from then on the
7de49c2aa70batagen2026-10-16 09:27 UTC12
    /// file is the only record of completion. `None` means it had already
7de49c2aa70batagen2026-10-16 09:27 UTC13
    /// signalled when exported.
7de49c2aa70batagen2026-10-16 09:27 UTC14
    Exported(Option<OwnedFd>),
7de49c2aa70batagen2026-10-16 09:27 UTC15
}
824bf02b6e55atagen2026-10-16 09:15 UTC16
824bf02b6e55atagen2026-10-16 09:15 UTC17
pub(crate) struct FenceInner {
7de49c2aa70batagen2026-10-16 09:27 UTC18
    shared: Arc<Shared>,
7de49c2aa70batagen2026-10-16 09:27 UTC19
    fence: vk::Fence,
7de49c2aa70batagen2026-10-16 09:27 UTC20
    exportable: bool,
7de49c2aa70batagen2026-10-16 09:27 UTC21
    state: Mutex<State>,
824bf02b6e55atagen2026-10-16 09:15 UTC22
}
824bf02b6e55atagen2026-10-16 09:15 UTC23
824bf02b6e55atagen2026-10-16 09:15 UTC24
impl FenceInner {
824bf02b6e55atagen2026-10-16 09:15 UTC25
    pub fn new(shared: &Arc<Shared>) -> Result<Arc<Self>, vk::Result> {
7de49c2aa70batagen2026-10-16 09:27 UTC26
        let exportable = shared.device.dmabuf.is_some();
7de49c2aa70batagen2026-10-16 09:27 UTC27
        let mut export = vk::ExportFenceCreateInfo::default()
7de49c2aa70batagen2026-10-16 09:27 UTC28
            .handle_types(vk::ExternalFenceHandleTypeFlags::SYNC_FD);
7de49c2aa70batagen2026-10-16 09:27 UTC29
        let mut info = vk::FenceCreateInfo::default();
7de49c2aa70batagen2026-10-16 09:27 UTC30
        if exportable {
7de49c2aa70batagen2026-10-16 09:27 UTC31
            info = info.push_next(&mut export);
7de49c2aa70batagen2026-10-16 09:27 UTC32
        }
7de49c2aa70batagen2026-10-16 09:27 UTC33
        let fence = unsafe { shared.device.device.create_fence(&info, None)? };
824bf02b6e55atagen2026-10-16 09:15 UTC34
        Ok(Arc::new(Self {
824bf02b6e55atagen2026-10-16 09:15 UTC35
            shared: shared.clone(),
824bf02b6e55atagen2026-10-16 09:15 UTC36
            fence,
7de49c2aa70batagen2026-10-16 09:27 UTC37
            exportable,
7de49c2aa70batagen2026-10-16 09:27 UTC38
            state: Mutex::new(State::Pending),
824bf02b6e55atagen2026-10-16 09:15 UTC39
        }))
824bf02b6e55atagen2026-10-16 09:15 UTC40
    }
824bf02b6e55atagen2026-10-16 09:15 UTC41
7de49c2aa70batagen2026-10-16 09:27 UTC42
    pub fn fence(&self) -> vk::Fence {
7de49c2aa70batagen2026-10-16 09:27 UTC43
        self.fence
7de49c2aa70batagen2026-10-16 09:27 UTC44
    }
7de49c2aa70batagen2026-10-16 09:27 UTC45
824bf02b6e55atagen2026-10-16 09:15 UTC46
    pub fn signaled(&self) -> bool {
7de49c2aa70batagen2026-10-16 09:27 UTC47
        match &*self.state.lock().unwrap_or_else(|e| e.into_inner()) {
7de49c2aa70batagen2026-10-16 09:27 UTC48
            State::Pending => {
7de49c2aa70batagen2026-10-16 09:27 UTC49
                unsafe { self.shared.device.device.get_fence_status(self.fence) }.unwrap_or(true)
7de49c2aa70batagen2026-10-16 09:27 UTC50
            }
7de49c2aa70batagen2026-10-16 09:27 UTC51
            State::Exported(None) => true,
7de49c2aa70batagen2026-10-16 09:27 UTC52
            State::Exported(Some(fd)) => readable(fd, Some(&Default::default())),
7de49c2aa70batagen2026-10-16 09:27 UTC53
        }
824bf02b6e55atagen2026-10-16 09:15 UTC54
    }
824bf02b6e55atagen2026-10-16 09:15 UTC55
cabbef6c998aatagen2026-10-16 13:42 UTC56
    /// Blocks until the GPU signals. A pending fence is first turned into its
cabbef6c998aatagen2026-10-16 13:42 UTC57
    /// sync_file and polled, because waiting on the Vulkan fence itself sleeps
cabbef6c998aatagen2026-10-16 13:42 UTC58
    /// in 10 ms steps on NVIDIA even when the work is done in microseconds.
824bf02b6e55atagen2026-10-16 09:15 UTC59
    pub fn wait(&self) -> Result<(), vk::Result> {
cabbef6c998aatagen2026-10-16 13:42 UTC60
        if self.exportable {
cabbef6c998aatagen2026-10-16 13:42 UTC61
            drop(self.export());
cabbef6c998aatagen2026-10-16 13:42 UTC62
        }
7de49c2aa70batagen2026-10-16 09:27 UTC63
        match &*self.state.lock().unwrap_or_else(|e| e.into_inner()) {
7de49c2aa70batagen2026-10-16 09:27 UTC64
            State::Pending => unsafe {
7de49c2aa70batagen2026-10-16 09:27 UTC65
                self.shared
7de49c2aa70batagen2026-10-16 09:27 UTC66
                    .device
7de49c2aa70batagen2026-10-16 09:27 UTC67
                    .device
7de49c2aa70batagen2026-10-16 09:27 UTC68
                    .wait_for_fences(&[self.fence], true, u64::MAX)
7de49c2aa70batagen2026-10-16 09:27 UTC69
            },
7de49c2aa70batagen2026-10-16 09:27 UTC70
            State::Exported(None) => Ok(()),
7de49c2aa70batagen2026-10-16 09:27 UTC71
            State::Exported(Some(fd)) => {
7de49c2aa70batagen2026-10-16 09:27 UTC72
                readable(fd, None);
7de49c2aa70batagen2026-10-16 09:27 UTC73
                Ok(())
7de49c2aa70batagen2026-10-16 09:27 UTC74
            }
7de49c2aa70batagen2026-10-16 09:27 UTC75
        }
7de49c2aa70batagen2026-10-16 09:27 UTC76
    }
7de49c2aa70batagen2026-10-16 09:27 UTC77
cabbef6c998aatagen2026-10-16 13:42 UTC78
    #[profiling::function]
7de49c2aa70batagen2026-10-16 09:27 UTC79
    fn export(&self) -> Option<OwnedFd> {
7de49c2aa70batagen2026-10-16 09:27 UTC80
        if !self.exportable {
7de49c2aa70batagen2026-10-16 09:27 UTC81
            return None;
7de49c2aa70batagen2026-10-16 09:27 UTC82
        }
7de49c2aa70batagen2026-10-16 09:27 UTC83
        let ext = self.shared.device.dmabuf.as_ref()?;
7de49c2aa70batagen2026-10-16 09:27 UTC84
        let mut state = self.state.lock().unwrap_or_else(|e| e.into_inner());
7de49c2aa70batagen2026-10-16 09:27 UTC85
        if let State::Pending = *state {
7de49c2aa70batagen2026-10-16 09:27 UTC86
            let info = vk::FenceGetFdInfoKHR::default()
7de49c2aa70batagen2026-10-16 09:27 UTC87
                .fence(self.fence)
7de49c2aa70batagen2026-10-16 09:27 UTC88
                .handle_type(vk::ExternalFenceHandleTypeFlags::SYNC_FD);
7de49c2aa70batagen2026-10-16 09:27 UTC89
            let raw = unsafe { ext.fence_fd.get_fence_fd(&info) }.ok()?;
7de49c2aa70batagen2026-10-16 09:27 UTC90
            *state = State::Exported((raw >= 0).then(|| unsafe { OwnedFd::from_raw_fd(raw) }));
7de49c2aa70batagen2026-10-16 09:27 UTC91
        }
7de49c2aa70batagen2026-10-16 09:27 UTC92
        match &*state {
7de49c2aa70batagen2026-10-16 09:27 UTC93
            State::Exported(Some(fd)) => fd.try_clone().ok(),
7de49c2aa70batagen2026-10-16 09:27 UTC94
            _ => None,
7de49c2aa70batagen2026-10-16 09:27 UTC95
        }
7de49c2aa70batagen2026-10-16 09:27 UTC96
    }
7de49c2aa70batagen2026-10-16 09:27 UTC97
}
7de49c2aa70batagen2026-10-16 09:27 UTC98
7de49c2aa70batagen2026-10-16 09:27 UTC99
fn readable(fd: &OwnedFd, timeout: Option<&rustix::event::Timespec>) -> bool {
7de49c2aa70batagen2026-10-16 09:27 UTC100
    let mut fds = [PollFd::new(fd, PollFlags::IN)];
7de49c2aa70batagen2026-10-16 09:27 UTC101
    loop {
7de49c2aa70batagen2026-10-16 09:27 UTC102
        match poll(&mut fds, timeout) {
7de49c2aa70batagen2026-10-16 09:27 UTC103
            Ok(n) => return n > 0,
7de49c2aa70batagen2026-10-16 09:27 UTC104
            Err(rustix::io::Errno::INTR) => continue,
7de49c2aa70batagen2026-10-16 09:27 UTC105
            Err(_) => return true,
824bf02b6e55atagen2026-10-16 09:15 UTC106
        }
824bf02b6e55atagen2026-10-16 09:15 UTC107
    }
824bf02b6e55atagen2026-10-16 09:15 UTC108
}
824bf02b6e55atagen2026-10-16 09:15 UTC109
824bf02b6e55atagen2026-10-16 09:15 UTC110
impl Drop for FenceInner {
824bf02b6e55atagen2026-10-16 09:15 UTC111
    fn drop(&mut self) {
824bf02b6e55atagen2026-10-16 09:15 UTC112
        unsafe { self.shared.device.device.destroy_fence(self.fence, None) };
824bf02b6e55atagen2026-10-16 09:15 UTC113
    }
824bf02b6e55atagen2026-10-16 09:15 UTC114
}
824bf02b6e55atagen2026-10-16 09:15 UTC115
824bf02b6e55atagen2026-10-16 09:15 UTC116
impl fmt::Debug for FenceInner {
824bf02b6e55atagen2026-10-16 09:15 UTC117
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
824bf02b6e55atagen2026-10-16 09:15 UTC118
        f.debug_tuple("FenceInner").field(&self.fence).finish()
824bf02b6e55atagen2026-10-16 09:15 UTC119
    }
824bf02b6e55atagen2026-10-16 09:15 UTC120
}
824bf02b6e55atagen2026-10-16 09:15 UTC121
824bf02b6e55atagen2026-10-16 09:15 UTC122
#[derive(Debug)]
824bf02b6e55atagen2026-10-16 09:15 UTC123
pub(crate) struct VkFence(pub Arc<FenceInner>);
824bf02b6e55atagen2026-10-16 09:15 UTC124
824bf02b6e55atagen2026-10-16 09:15 UTC125
impl Fence for VkFence {
824bf02b6e55atagen2026-10-16 09:15 UTC126
    fn is_signaled(&self) -> bool {
824bf02b6e55atagen2026-10-16 09:15 UTC127
        self.0.signaled()
824bf02b6e55atagen2026-10-16 09:15 UTC128
    }
824bf02b6e55atagen2026-10-16 09:15 UTC129
824bf02b6e55atagen2026-10-16 09:15 UTC130
    fn wait(&self) -> Result<(), Interrupted> {
824bf02b6e55atagen2026-10-16 09:15 UTC131
        self.0.wait().map_err(|_| Interrupted)
824bf02b6e55atagen2026-10-16 09:15 UTC132
    }
824bf02b6e55atagen2026-10-16 09:15 UTC133
824bf02b6e55atagen2026-10-16 09:15 UTC134
    fn is_exportable(&self) -> bool {
7de49c2aa70batagen2026-10-16 09:27 UTC135
        self.0.exportable
824bf02b6e55atagen2026-10-16 09:15 UTC136
    }
824bf02b6e55atagen2026-10-16 09:15 UTC137
7de49c2aa70batagen2026-10-16 09:27 UTC138
    fn export(&self) -> Option<OwnedFd> {
7de49c2aa70batagen2026-10-16 09:27 UTC139
        self.0.export()
824bf02b6e55atagen2026-10-16 09:15 UTC140
    }
824bf02b6e55atagen2026-10-16 09:15 UTC141
}