Skip to main content

oxicuda_launch/
error.rs

1//! Launch validation error types.
2//!
3//! These errors are returned by [`crate::LaunchParams::validate`] when launch
4//! parameters exceed device hardware limits.
5
6use std::fmt;
7
8/// Error type for launch parameter validation.
9///
10/// These variants describe specific constraint violations that would
11/// cause a kernel launch to fail at the driver level.
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub enum LaunchError {
14    /// The total number of threads per block exceeds the device maximum.
15    BlockSizeExceedsLimit {
16        /// Requested total threads per block.
17        requested: u32,
18        /// Maximum allowed by the device.
19        max: u32,
20    },
21    /// A grid dimension exceeds the device maximum.
22    GridSizeExceedsLimit {
23        /// Requested grid size in the offending dimension.
24        requested: u32,
25        /// Maximum allowed by the device.
26        max: u32,
27    },
28    /// The requested dynamic shared memory exceeds the device maximum.
29    SharedMemoryExceedsLimit {
30        /// Requested shared memory in bytes.
31        requested: u32,
32        /// Maximum allowed by the device.
33        max: u32,
34    },
35    /// A dimension value is invalid (e.g., zero).
36    InvalidDimension {
37        /// Name of the dimension (e.g., "block.x", "grid.z").
38        dim: &'static str,
39        /// The invalid value.
40        value: u32,
41    },
42}
43
44impl fmt::Display for LaunchError {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        match self {
47            Self::BlockSizeExceedsLimit { requested, max } => {
48                write!(
49                    f,
50                    "block size {requested} exceeds device maximum {max} threads per block"
51                )
52            }
53            Self::GridSizeExceedsLimit { requested, max } => {
54                write!(f, "grid dimension {requested} exceeds device maximum {max}")
55            }
56            Self::SharedMemoryExceedsLimit { requested, max } => {
57                write!(
58                    f,
59                    "shared memory {requested} bytes exceeds device maximum {max} bytes"
60                )
61            }
62            Self::InvalidDimension { dim, value } => {
63                write!(f, "invalid dimension {dim} = {value} (must be > 0)")
64            }
65        }
66    }
67}
68
69impl std::error::Error for LaunchError {}
70
71// ---------------------------------------------------------------------------
72// Tests
73// ---------------------------------------------------------------------------
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    #[test]
80    fn block_size_exceeds_display() {
81        let err = LaunchError::BlockSizeExceedsLimit {
82            requested: 2048,
83            max: 1024,
84        };
85        let msg = format!("{err}");
86        assert!(msg.contains("2048"));
87        assert!(msg.contains("1024"));
88    }
89
90    #[test]
91    fn grid_size_exceeds_display() {
92        let err = LaunchError::GridSizeExceedsLimit {
93            requested: 100_000,
94            max: 65535,
95        };
96        let msg = format!("{err}");
97        assert!(msg.contains("100000"));
98        assert!(msg.contains("65535"));
99    }
100
101    #[test]
102    fn shared_memory_exceeds_display() {
103        let err = LaunchError::SharedMemoryExceedsLimit {
104            requested: 65536,
105            max: 49152,
106        };
107        let msg = format!("{err}");
108        assert!(msg.contains("65536"));
109        assert!(msg.contains("49152"));
110    }
111
112    #[test]
113    fn invalid_dimension_display() {
114        let err = LaunchError::InvalidDimension {
115            dim: "block.x",
116            value: 0,
117        };
118        let msg = format!("{err}");
119        assert!(msg.contains("block.x"));
120        assert!(msg.contains("0"));
121    }
122
123    #[test]
124    fn launch_error_implements_std_error() {
125        fn assert_error<T: std::error::Error>() {}
126        assert_error::<LaunchError>();
127    }
128
129    #[test]
130    fn launch_error_eq() {
131        let a = LaunchError::BlockSizeExceedsLimit {
132            requested: 512,
133            max: 256,
134        };
135        let b = LaunchError::BlockSizeExceedsLimit {
136            requested: 512,
137            max: 256,
138        };
139        assert_eq!(a, b);
140    }
141
142    #[test]
143    fn launch_error_debug() {
144        let err = LaunchError::InvalidDimension {
145            dim: "grid.z",
146            value: 0,
147        };
148        let dbg = format!("{err:?}");
149        assert!(dbg.contains("InvalidDimension"));
150    }
151}