atagen

monolith

public
Star0
Watch0
3a1eef6bf10b440ec762e4f6b99285eabcfb35d3
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
824bf02b6e55atagen2026-10-16 09:15 UTC56
    pub fn wait(&self) -> Result<(), vk::Result> {
7de49c2aa70batagen2026-10-16 09:27 UTC57
        match &*self.state.lock().unwrap_or_else(|e| e.into_inner()) {
7de49c2aa70batagen2026-10-16 09:27 UTC58
            State::Pending => unsafe {
7de49c2aa70batagen2026-10-16 09:27 UTC59
                self.shared
7de49c2aa70batagen2026-10-16 09:27 UTC60
                    .device
7de49c2aa70batagen2026-10-16 09:27 UTC61
                    .device
7de49c2aa70batagen2026-10-16 09:27 UTC62
                    .wait_for_fences(&[self.fence], true, u64::MAX)
7de49c2aa70batagen2026-10-16 09:27 UTC63
            },
7de49c2aa70batagen2026-10-16 09:27 UTC64
            State::Exported(None) => Ok(()),
7de49c2aa70batagen2026-10-16 09:27 UTC65
            State::Exported(Some(fd)) => {
7de49c2aa70batagen2026-10-16 09:27 UTC66
                readable(fd, None);
7de49c2aa70batagen2026-10-16 09:27 UTC67
                Ok(())
7de49c2aa70batagen2026-10-16 09:27 UTC68
            }
7de49c2aa70batagen2026-10-16 09:27 UTC69
        }
7de49c2aa70batagen2026-10-16 09:27 UTC70
    }
7de49c2aa70batagen2026-10-16 09:27 UTC71
7de49c2aa70batagen2026-10-16 09:27 UTC72
    fn export(&self) -> Option<OwnedFd> {
7de49c2aa70batagen2026-10-16 09:27 UTC73
        if !self.exportable {
7de49c2aa70batagen2026-10-16 09:27 UTC74
            return None;
7de49c2aa70batagen2026-10-16 09:27 UTC75
        }
7de49c2aa70batagen2026-10-16 09:27 UTC76
        let ext = self.shared.device.dmabuf.as_ref()?;
7de49c2aa70batagen2026-10-16 09:27 UTC77
        let mut state = self.state.lock().unwrap_or_else(|e| e.into_inner());
7de49c2aa70batagen2026-10-16 09:27 UTC78
        if let State::Pending = *state {
7de49c2aa70batagen2026-10-16 09:27 UTC79
            let info = vk::FenceGetFdInfoKHR::default()
7de49c2aa70batagen2026-10-16 09:27 UTC80
                .fence(self.fence)
7de49c2aa70batagen2026-10-16 09:27 UTC81
                .handle_type(vk::ExternalFenceHandleTypeFlags::SYNC_FD);
7de49c2aa70batagen2026-10-16 09:27 UTC82
            let raw = unsafe { ext.fence_fd.get_fence_fd(&info) }.ok()?;
7de49c2aa70batagen2026-10-16 09:27 UTC83
            *state = State::Exported((raw >= 0).then(|| unsafe { OwnedFd::from_raw_fd(raw) }));
7de49c2aa70batagen2026-10-16 09:27 UTC84
        }
7de49c2aa70batagen2026-10-16 09:27 UTC85
        match &*state {
7de49c2aa70batagen2026-10-16 09:27 UTC86
            State::Exported(Some(fd)) => fd.try_clone().ok(),
7de49c2aa70batagen2026-10-16 09:27 UTC87
            _ => None,
7de49c2aa70batagen2026-10-16 09:27 UTC88
        }
7de49c2aa70batagen2026-10-16 09:27 UTC89
    }
7de49c2aa70batagen2026-10-16 09:27 UTC90
}
7de49c2aa70batagen2026-10-16 09:27 UTC91
7de49c2aa70batagen2026-10-16 09:27 UTC92
fn readable(fd: &OwnedFd, timeout: Option<&rustix::event::Timespec>) -> bool {
7de49c2aa70batagen2026-10-16 09:27 UTC93
    let mut fds = [PollFd::new(fd, PollFlags::IN)];
7de49c2aa70batagen2026-10-16 09:27 UTC94
    loop {
7de49c2aa70batagen2026-10-16 09:27 UTC95
        match poll(&mut fds, timeout) {
7de49c2aa70batagen2026-10-16 09:27 UTC96
            Ok(n) => return n > 0,
7de49c2aa70batagen2026-10-16 09:27 UTC97
            Err(rustix::io::Errno::INTR) => continue,
7de49c2aa70batagen2026-10-16 09:27 UTC98
            Err(_) => return true,
824bf02b6e55atagen2026-10-16 09:15 UTC99
        }
824bf02b6e55atagen2026-10-16 09:15 UTC100
    }
824bf02b6e55atagen2026-10-16 09:15 UTC101
}
824bf02b6e55atagen2026-10-16 09:15 UTC102
824bf02b6e55atagen2026-10-16 09:15 UTC103
impl Drop for FenceInner {
824bf02b6e55atagen2026-10-16 09:15 UTC104
    fn drop(&mut self) {
824bf02b6e55atagen2026-10-16 09:15 UTC105
        unsafe { self.shared.device.device.destroy_fence(self.fence, None) };
824bf02b6e55atagen2026-10-16 09:15 UTC106
    }
824bf02b6e55atagen2026-10-16 09:15 UTC107
}
824bf02b6e55atagen2026-10-16 09:15 UTC108
824bf02b6e55atagen2026-10-16 09:15 UTC109
impl fmt::Debug for FenceInner {
824bf02b6e55atagen2026-10-16 09:15 UTC110
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
824bf02b6e55atagen2026-10-16 09:15 UTC111
        f.debug_tuple("FenceInner").field(&self.fence).finish()
824bf02b6e55atagen2026-10-16 09:15 UTC112
    }
824bf02b6e55atagen2026-10-16 09:15 UTC113
}
824bf02b6e55atagen2026-10-16 09:15 UTC114
824bf02b6e55atagen2026-10-16 09:15 UTC115
#[derive(Debug)]
824bf02b6e55atagen2026-10-16 09:15 UTC116
pub(crate) struct VkFence(pub Arc<FenceInner>);
824bf02b6e55atagen2026-10-16 09:15 UTC117
824bf02b6e55atagen2026-10-16 09:15 UTC118
impl Fence for VkFence {
824bf02b6e55atagen2026-10-16 09:15 UTC119
    fn is_signaled(&self) -> bool {
824bf02b6e55atagen2026-10-16 09:15 UTC120
        self.0.signaled()
824bf02b6e55atagen2026-10-16 09:15 UTC121
    }
824bf02b6e55atagen2026-10-16 09:15 UTC122
824bf02b6e55atagen2026-10-16 09:15 UTC123
    fn wait(&self) -> Result<(), Interrupted> {
824bf02b6e55atagen2026-10-16 09:15 UTC124
        self.0.wait().map_err(|_| Interrupted)
824bf02b6e55atagen2026-10-16 09:15 UTC125
    }
824bf02b6e55atagen2026-10-16 09:15 UTC126
824bf02b6e55atagen2026-10-16 09:15 UTC127
    fn is_exportable(&self) -> bool {
7de49c2aa70batagen2026-10-16 09:27 UTC128
        self.0.exportable
824bf02b6e55atagen2026-10-16 09:15 UTC129
    }
824bf02b6e55atagen2026-10-16 09:15 UTC130
7de49c2aa70batagen2026-10-16 09:27 UTC131
    fn export(&self) -> Option<OwnedFd> {
7de49c2aa70batagen2026-10-16 09:27 UTC132
        self.0.export()
824bf02b6e55atagen2026-10-16 09:15 UTC133
    }
824bf02b6e55atagen2026-10-16 09:15 UTC134
}