Skip to main content

oxicuda_levelzero/
error.rs

1//! Error types for the `oxicuda-levelzero` backend.
2
3use oxicuda_backend::BackendError;
4
5/// Errors specific to the Level Zero compute backend.
6#[derive(Debug, thiserror::Error)]
7pub enum LevelZeroError {
8    /// Level Zero requires Linux or Windows.
9    #[error("Level Zero requires Linux or Windows")]
10    UnsupportedPlatform,
11
12    /// The Level Zero loader library could not be found or loaded.
13    #[error("Level Zero loader not found: {0}")]
14    LibraryNotFound(String),
15
16    /// A Level Zero API call returned a non-success result code.
17    #[error("Level Zero error 0x{0:08x}: {1}")]
18    ZeError(u32, String),
19
20    /// No Intel GPU device was found on this system.
21    #[error("no Intel GPU found")]
22    NoSuitableDevice,
23
24    /// Device ran out of memory during allocation.
25    #[error("out of device memory")]
26    OutOfMemory,
27
28    /// A SPIR-V shader module error occurred.
29    #[error("SPIR-V error: {0}")]
30    ShaderError(String),
31
32    /// An error occurred while operating on a command list.
33    #[error("command list error: {0}")]
34    CommandListError(String),
35
36    /// The backend has not been initialized yet.
37    #[error("not initialized")]
38    NotInitialized,
39
40    /// The requested operation is not supported.
41    #[error("unsupported: {0}")]
42    Unsupported(String),
43
44    /// An invalid argument was passed.
45    #[error("invalid argument: {0}")]
46    InvalidArgument(String),
47}
48
49/// Convenience result alias for Level Zero operations.
50pub type LevelZeroResult<T> = Result<T, LevelZeroError>;
51
52impl From<LevelZeroError> for BackendError {
53    fn from(e: LevelZeroError) -> Self {
54        match e {
55            LevelZeroError::UnsupportedPlatform => {
56                BackendError::DeviceError("Level Zero requires Linux or Windows".into())
57            }
58            LevelZeroError::LibraryNotFound(msg) => {
59                BackendError::DeviceError(format!("Level Zero loader not found: {msg}"))
60            }
61            LevelZeroError::ZeError(code, msg) => {
62                BackendError::DeviceError(format!("Level Zero error 0x{code:08x}: {msg}"))
63            }
64            LevelZeroError::NoSuitableDevice => {
65                BackendError::DeviceError("no Intel GPU found".into())
66            }
67            LevelZeroError::ShaderError(msg) => {
68                BackendError::DeviceError(format!("SPIR-V error: {msg}"))
69            }
70            LevelZeroError::CommandListError(msg) => {
71                BackendError::DeviceError(format!("command list error: {msg}"))
72            }
73            LevelZeroError::OutOfMemory => BackendError::OutOfMemory,
74            LevelZeroError::NotInitialized => BackendError::NotInitialized,
75            LevelZeroError::Unsupported(msg) => BackendError::Unsupported(msg),
76            LevelZeroError::InvalidArgument(msg) => BackendError::InvalidArgument(msg),
77        }
78    }
79}
80
81// ─── Tests ───────────────────────────────────────────────────────────────────
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn level_zero_error_display() {
89        assert_eq!(
90            LevelZeroError::UnsupportedPlatform.to_string(),
91            "Level Zero requires Linux or Windows"
92        );
93        assert_eq!(
94            LevelZeroError::LibraryNotFound("libze_loader.so".into()).to_string(),
95            "Level Zero loader not found: libze_loader.so"
96        );
97        assert_eq!(
98            LevelZeroError::ZeError(0x7800_0001, "device lost".into()).to_string(),
99            "Level Zero error 0x78000001: device lost"
100        );
101        assert_eq!(
102            LevelZeroError::NoSuitableDevice.to_string(),
103            "no Intel GPU found"
104        );
105        assert_eq!(
106            LevelZeroError::OutOfMemory.to_string(),
107            "out of device memory"
108        );
109        assert_eq!(
110            LevelZeroError::ShaderError("invalid binary".into()).to_string(),
111            "SPIR-V error: invalid binary"
112        );
113        assert_eq!(
114            LevelZeroError::CommandListError("closed".into()).to_string(),
115            "command list error: closed"
116        );
117        assert_eq!(
118            LevelZeroError::NotInitialized.to_string(),
119            "not initialized"
120        );
121        assert_eq!(
122            LevelZeroError::Unsupported("op".into()).to_string(),
123            "unsupported: op"
124        );
125        assert_eq!(
126            LevelZeroError::InvalidArgument("arg".into()).to_string(),
127            "invalid argument: arg"
128        );
129    }
130
131    #[test]
132    fn backend_error_from_level_zero_error() {
133        let e = BackendError::from(LevelZeroError::OutOfMemory);
134        assert_eq!(e, BackendError::OutOfMemory);
135
136        let e = BackendError::from(LevelZeroError::NotInitialized);
137        assert_eq!(e, BackendError::NotInitialized);
138
139        let e = BackendError::from(LevelZeroError::Unsupported("foo".into()));
140        assert_eq!(e, BackendError::Unsupported("foo".into()));
141
142        let e = BackendError::from(LevelZeroError::InvalidArgument("bar".into()));
143        assert_eq!(e, BackendError::InvalidArgument("bar".into()));
144
145        let e = BackendError::from(LevelZeroError::UnsupportedPlatform);
146        assert!(matches!(e, BackendError::DeviceError(_)));
147
148        let e = BackendError::from(LevelZeroError::LibraryNotFound("ze.so".into()));
149        assert!(matches!(e, BackendError::DeviceError(_)));
150
151        let e = BackendError::from(LevelZeroError::ZeError(1, "bad".into()));
152        assert!(matches!(e, BackendError::DeviceError(_)));
153
154        let e = BackendError::from(LevelZeroError::NoSuitableDevice);
155        assert!(matches!(e, BackendError::DeviceError(_)));
156
157        let e = BackendError::from(LevelZeroError::ShaderError("x".into()));
158        assert!(matches!(e, BackendError::DeviceError(_)));
159
160        let e = BackendError::from(LevelZeroError::CommandListError("y".into()));
161        assert!(matches!(e, BackendError::DeviceError(_)));
162    }
163}