1use oxicuda_backend::BackendError;
4
5#[derive(Debug, thiserror::Error)]
7pub enum WebGpuError {
8 #[error("no WebGPU adapter found")]
10 NoAdapter,
11
12 #[error("device request failed: {0}")]
14 DeviceRequest(String),
15
16 #[error("out of device memory")]
18 OutOfMemory,
19
20 #[error("WGSL shader compilation failed: {0}")]
22 ShaderCompilation(String),
23
24 #[error("pipeline creation failed: {0}")]
26 PipelineCreation(String),
27
28 #[error("not initialized")]
30 NotInitialized,
31
32 #[error("unsupported operation: {0}")]
34 Unsupported(String),
35
36 #[error("invalid argument: {0}")]
38 InvalidArgument(String),
39
40 #[error("buffer mapping failed: {0}")]
42 BufferMapping(String),
43
44 #[error("adapter timeout")]
46 Timeout,
47}
48
49pub type WebGpuResult<T> = Result<T, WebGpuError>;
51
52impl From<WebGpuError> for BackendError {
53 fn from(e: WebGpuError) -> Self {
54 match e {
55 WebGpuError::NoAdapter => BackendError::DeviceError("no WebGPU adapter found".into()),
56 WebGpuError::DeviceRequest(msg) => {
57 BackendError::DeviceError(format!("device request failed: {msg}"))
58 }
59 WebGpuError::OutOfMemory => BackendError::OutOfMemory,
60 WebGpuError::ShaderCompilation(msg) => {
61 BackendError::DeviceError(format!("WGSL shader compilation failed: {msg}"))
62 }
63 WebGpuError::PipelineCreation(msg) => {
64 BackendError::DeviceError(format!("pipeline creation failed: {msg}"))
65 }
66 WebGpuError::NotInitialized => BackendError::NotInitialized,
67 WebGpuError::Unsupported(msg) => BackendError::Unsupported(msg),
68 WebGpuError::InvalidArgument(msg) => BackendError::InvalidArgument(msg),
69 WebGpuError::BufferMapping(msg) => {
70 BackendError::DeviceError(format!("buffer mapping failed: {msg}"))
71 }
72 WebGpuError::Timeout => BackendError::DeviceError("adapter timeout".into()),
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn webgpu_error_display() {
83 assert_eq!(
84 WebGpuError::NoAdapter.to_string(),
85 "no WebGPU adapter found"
86 );
87 assert_eq!(
88 WebGpuError::DeviceRequest("oops".into()).to_string(),
89 "device request failed: oops"
90 );
91 assert_eq!(WebGpuError::OutOfMemory.to_string(), "out of device memory");
92 assert_eq!(
93 WebGpuError::ShaderCompilation("syntax error".into()).to_string(),
94 "WGSL shader compilation failed: syntax error"
95 );
96 assert_eq!(
97 WebGpuError::PipelineCreation("invalid layout".into()).to_string(),
98 "pipeline creation failed: invalid layout"
99 );
100 assert_eq!(WebGpuError::NotInitialized.to_string(), "not initialized");
101 assert_eq!(
102 WebGpuError::Unsupported("foo".into()).to_string(),
103 "unsupported operation: foo"
104 );
105 assert_eq!(
106 WebGpuError::InvalidArgument("bad arg".into()).to_string(),
107 "invalid argument: bad arg"
108 );
109 assert_eq!(
110 WebGpuError::BufferMapping("lock poisoned".into()).to_string(),
111 "buffer mapping failed: lock poisoned"
112 );
113 assert_eq!(WebGpuError::Timeout.to_string(), "adapter timeout");
114 }
115
116 #[test]
117 fn webgpu_error_from_backend_error() {
118 let e = BackendError::from(WebGpuError::OutOfMemory);
120 assert_eq!(e, BackendError::OutOfMemory);
121
122 let e = BackendError::from(WebGpuError::NotInitialized);
123 assert_eq!(e, BackendError::NotInitialized);
124
125 let e = BackendError::from(WebGpuError::Unsupported("bar".into()));
126 assert_eq!(e, BackendError::Unsupported("bar".into()));
127
128 let e = BackendError::from(WebGpuError::InvalidArgument("baz".into()));
129 assert_eq!(e, BackendError::InvalidArgument("baz".into()));
130
131 let e = BackendError::from(WebGpuError::NoAdapter);
132 assert!(matches!(e, BackendError::DeviceError(_)));
133
134 let e = BackendError::from(WebGpuError::DeviceRequest("x".into()));
135 assert!(matches!(e, BackendError::DeviceError(_)));
136
137 let e = BackendError::from(WebGpuError::BufferMapping("m".into()));
138 assert!(matches!(e, BackendError::DeviceError(_)));
139
140 let e = BackendError::from(WebGpuError::Timeout);
141 assert!(matches!(e, BackendError::DeviceError(_)));
142 }
143}