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
use crate::buffer::flags::MemAccess;
use opencl_sys::{cl_svm_mem_flags, CL_MEM_SVM_ATOMICS, CL_MEM_SVM_FINE_GRAIN_BUFFER};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[non_exhaustive]
pub struct SvmFlags {
    pub access: MemAccess,
    pub utils: Option<SvmUtilsFlags>,
}

impl SvmFlags {
    pub const DEFAULT: Self = Self::const_new(MemAccess::READ_WRITE, None);

    #[inline(always)]
    pub fn new(access: MemAccess, utils: impl Into<Option<SvmUtilsFlags>>) -> Self {
        Self {
            access,
            utils: utils.into(),
        }
    }

    #[inline(always)]
    pub const fn const_new(access: MemAccess, utils: Option<SvmUtilsFlags>) -> Self {
        Self { access, utils }
    }

    #[inline(always)]
    pub const fn to_bits(self) -> cl_svm_mem_flags {
        // self.utils.map_or(0, SvmUtilsFlags::to_bits)
        self.access.to_bits()
            | match self.utils {
                Some(x) => SvmUtilsFlags::to_bits(x),
                None => 0,
            }
    }
}

impl From<MemAccess> for SvmFlags {
    #[inline(always)]
    fn from(x: MemAccess) -> Self {
        Self::new(x, None)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SvmUtilsFlags {
    FineGrain,
    Atomics,
}

impl SvmUtilsFlags {
    #[inline(always)]
    pub const fn to_bits(self) -> cl_svm_mem_flags {
        const ATOMICS: cl_svm_mem_flags = CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS;

        match self {
            Self::FineGrain => CL_MEM_SVM_FINE_GRAIN_BUFFER,
            Self::Atomics => ATOMICS,
        }
    }

    #[inline(always)]
    pub const fn from_bits(v: cl_svm_mem_flags) -> Option<Self> {
        if v & CL_MEM_SVM_FINE_GRAIN_BUFFER == 0 {
            return None;
        }

        if v & CL_MEM_SVM_ATOMICS == 0 {
            return Some(Self::FineGrain);
        }

        Some(Self::Atomics)
    }
}

impl Into<cl_svm_mem_flags> for SvmUtilsFlags {
    #[inline(always)]
    fn into(self) -> cl_svm_mem_flags {
        self.to_bits()
    }
}

impl Into<SvmFlags> for SvmUtilsFlags {
    #[inline(always)]
    fn into(self) -> SvmFlags {
        SvmFlags::new(Default::default(), self)
    }
}