1use thiserror::Error;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, Error)]
20#[repr(u32)]
21pub enum CudaRtError {
22 #[error("CUDA RT: invalid value")]
24 InvalidValue = 1,
25
26 #[error("CUDA RT: out of device memory")]
28 MemoryAllocation = 2,
29
30 #[error("CUDA RT: initialization error")]
32 InitializationError = 3,
33
34 #[error("CUDA RT: CUDA runtime is unloading")]
36 CudartUnloading = 4,
37
38 #[error("CUDA RT: profiler disabled")]
40 ProfilerDisabled = 5,
41
42 #[error("CUDA RT: invalid launch configuration")]
44 InvalidConfiguration = 9,
45
46 #[error("CUDA RT: invalid pitch value")]
48 InvalidPitchValue = 12,
49
50 #[error("CUDA RT: invalid symbol")]
52 InvalidSymbol = 13,
53
54 #[error("CUDA RT: invalid host pointer")]
56 InvalidHostPointer = 16,
57
58 #[error("CUDA RT: invalid device pointer")]
60 InvalidDevicePointer = 17,
61
62 #[error("CUDA RT: invalid texture")]
64 InvalidTexture = 18,
65
66 #[error("CUDA RT: invalid texture binding")]
68 InvalidTextureBinding = 19,
69
70 #[error("CUDA RT: invalid channel descriptor")]
72 InvalidChannelDescriptor = 20,
73
74 #[error("CUDA RT: invalid memcpy direction")]
76 InvalidMemcpyDirection = 21,
77
78 #[error("CUDA RT: invalid filter setting")]
80 InvalidFilterSetting = 26,
81
82 #[error("CUDA RT: invalid norm setting")]
84 InvalidNormSetting = 27,
85
86 #[error("CUDA RT: stub library")]
88 StubLibrary = 34,
89
90 #[error("CUDA RT: installed driver version is insufficient")]
92 InsufficientDriver = 35,
93
94 #[error("CUDA RT: call requires a newer driver version")]
96 CallRequiresNewerDriver = 36,
97
98 #[error("CUDA RT: invalid surface")]
100 InvalidSurface = 37,
101
102 #[error("CUDA RT: duplicate variable name")]
104 DuplicateVariableName = 43,
105
106 #[error("CUDA RT: duplicate texture name")]
108 DuplicateTextureName = 44,
109
110 #[error("CUDA RT: duplicate surface name")]
112 DuplicateSurfaceName = 45,
113
114 #[error("CUDA RT: all CUDA-capable devices are busy or unavailable")]
116 DevicesUnavailable = 46,
117
118 #[error("CUDA RT: incompatible driver context")]
120 IncompatibleDriverContext = 49,
121
122 #[error("CUDA RT: missing configuration")]
124 MissingConfiguration = 52,
125
126 #[error("CUDA RT: launch max depth exceeded (dynamic parallelism)")]
128 LaunchMaxDepthExceeded = 65,
129
130 #[error("CUDA RT: attempted launch of file-scoped texture")]
132 LaunchFileScopedTex = 66,
133
134 #[error("CUDA RT: attempted launch of file-scoped surface")]
136 LaunchFileScopedSurf = 67,
137
138 #[error("CUDA RT: sync depth exceeded")]
140 SyncDepthExceeded = 68,
141
142 #[error("CUDA RT: launch pending count exceeded")]
144 LaunchPendingCountExceeded = 69,
145
146 #[error("CUDA RT: invalid device function")]
148 InvalidDeviceFunction = 98,
149
150 #[error("CUDA RT: no CUDA-capable device found")]
152 NoDevice = 100,
153
154 #[error("CUDA RT: invalid device ordinal")]
156 InvalidDevice = 101,
157
158 #[error("CUDA RT: device not licensed for compute")]
160 DeviceNotLicensed = 102,
161
162 #[error("CUDA RT: software validity not established")]
164 SoftwareValidityNotEstablished = 103,
165
166 #[error("CUDA RT: startup failure")]
168 StartupFailure = 127,
169
170 #[error("CUDA RT: invalid kernel image")]
172 InvalidKernelImage = 200,
173
174 #[error("CUDA RT: device uninitialized")]
176 DeviceUninitialized = 201,
177
178 #[error("CUDA RT: map buffer object failed")]
180 MapBufferObjectFailed = 205,
181
182 #[error("CUDA RT: unmap buffer object failed")]
184 UnmapBufferObjectFailed = 206,
185
186 #[error("CUDA RT: array is mapped")]
188 ArrayIsMapped = 207,
189
190 #[error("CUDA RT: already mapped")]
192 AlreadyMapped = 208,
193
194 #[error("CUDA RT: no kernel image for this device")]
196 NoKernelImageForDevice = 209,
197
198 #[error("CUDA RT: already acquired")]
200 AlreadyAcquired = 210,
201
202 #[error("CUDA RT: not mapped")]
204 NotMapped = 211,
205
206 #[error("CUDA RT: not mapped as array")]
208 NotMappedAsArray = 212,
209
210 #[error("CUDA RT: not mapped as pointer")]
212 NotMappedAsPointer = 213,
213
214 #[error("CUDA RT: uncorrectable ECC error")]
216 EccUncorrectable = 214,
217
218 #[error("CUDA RT: unsupported limit")]
220 UnsupportedLimit = 215,
221
222 #[error("CUDA RT: device already in use")]
224 DeviceAlreadyInUse = 216,
225
226 #[error("CUDA RT: peer access unsupported")]
228 PeerAccessUnsupported = 217,
229
230 #[error("CUDA RT: invalid PTX")]
232 InvalidPtx = 218,
233
234 #[error("CUDA RT: invalid graphics context")]
236 InvalidGraphicsContext = 219,
237
238 #[error("CUDA RT: NVLink uncorrectable error")]
240 NvlinkUncorrectable = 220,
241
242 #[error("CUDA RT: JIT compiler not found")]
244 JitCompilerNotFound = 221,
245
246 #[error("CUDA RT: unsupported PTX version")]
248 UnsupportedPtxVersion = 222,
249
250 #[error("CUDA RT: JIT compilation disabled")]
252 JitCompilationDisabled = 223,
253
254 #[error("CUDA RT: unsupported exec affinity")]
256 UnsupportedExecAffinity = 224,
257
258 #[error("CUDA RT: unsupported device-side sync")]
260 UnsupportedDevSideSync = 225,
261
262 #[error("CUDA RT: invalid source")]
264 InvalidSource = 300,
265
266 #[error("CUDA RT: file not found")]
268 FileNotFound = 301,
269
270 #[error("CUDA RT: shared object symbol not found")]
272 SharedObjectSymbolNotFound = 302,
273
274 #[error("CUDA RT: shared object init failed")]
276 SharedObjectInitFailed = 303,
277
278 #[error("CUDA RT: operating system error")]
280 OperatingSystem = 304,
281
282 #[error("CUDA RT: invalid resource handle")]
284 InvalidResourceHandle = 400,
285
286 #[error("CUDA RT: illegal state")]
288 IllegalState = 401,
289
290 #[error("CUDA RT: lost connection to client")]
292 LostConnection = 402,
293
294 #[error("CUDA RT: named symbol not found")]
296 SymbolNotFound = 500,
297
298 #[error("CUDA RT: operation not ready")]
300 NotReady = 600,
301
302 #[error("CUDA RT: illegal memory access")]
304 IllegalAddress = 700,
305
306 #[error("CUDA RT: launch out of resources")]
308 LaunchOutOfResources = 701,
309
310 #[error("CUDA RT: launch timed out")]
312 LaunchTimeout = 702,
313
314 #[error("CUDA RT: incompatible texturing mode")]
316 LaunchIncompatibleTexturing = 703,
317
318 #[error("CUDA RT: peer access already enabled")]
320 PeerAccessAlreadyEnabled = 704,
321
322 #[error("CUDA RT: peer access not enabled")]
324 PeerAccessNotEnabled = 705,
325
326 #[error("CUDA RT: cannot set while active process")]
328 SetOnActiveProcess = 708,
329
330 #[error("CUDA RT: context is destroyed")]
332 ContextIsDestroyed = 709,
333
334 #[error("CUDA RT: device assertion triggered")]
336 Assert = 710,
337
338 #[error("CUDA RT: too many peer mappings")]
340 TooManyPeers = 711,
341
342 #[error("CUDA RT: host memory already registered")]
344 HostMemoryAlreadyRegistered = 712,
345
346 #[error("CUDA RT: host memory not registered")]
348 HostMemoryNotRegistered = 713,
349
350 #[error("CUDA RT: hardware stack error")]
352 HardwareStackError = 714,
353
354 #[error("CUDA RT: illegal instruction")]
356 IllegalInstruction = 715,
357
358 #[error("CUDA RT: misaligned address")]
360 MisalignedAddress = 716,
361
362 #[error("CUDA RT: invalid address space")]
364 InvalidAddressSpace = 717,
365
366 #[error("CUDA RT: invalid program counter")]
368 InvalidPc = 718,
369
370 #[error("CUDA RT: exception during kernel launch")]
372 LaunchFailure = 719,
373
374 #[error("CUDA RT: cooperative launch too large")]
376 CooperativeLaunchTooLarge = 720,
377
378 #[error("CUDA RT: not permitted")]
380 NotPermitted = 800,
381
382 #[error("CUDA RT: not supported")]
384 NotSupported = 801,
385
386 #[error("CUDA RT: system not ready")]
388 SystemNotReady = 802,
389
390 #[error("CUDA RT: system driver mismatch")]
392 SystemDriverMismatch = 803,
393
394 #[error("CUDA RT: compat mode not supported on device")]
396 CompatNotSupportedOnDevice = 804,
397
398 #[error("CUDA RT: MPS connection failed")]
400 MpsConnectionFailed = 805,
401
402 #[error("CUDA RT: MPS RPC failure")]
404 MpsRpcFailure = 806,
405
406 #[error("CUDA RT: MPS server not ready")]
408 MpsServerNotReady = 807,
409
410 #[error("CUDA RT: MPS max clients reached")]
412 MpsMaxClientsReached = 808,
413
414 #[error("CUDA RT: MPS max connections reached")]
416 MpsMaxConnectionsReached = 809,
417
418 #[error("CUDA RT: MPS client terminated")]
420 MpsClientTerminated = 810,
421
422 #[error("CUDA RT: CDP not supported")]
424 CdpNotSupported = 811,
425
426 #[error("CUDA RT: CDP version mismatch")]
428 CdpVersionMismatch = 812,
429
430 #[error("CUDA RT: stream capture unsupported")]
432 StreamCaptureUnsupported = 900,
433
434 #[error("CUDA RT: stream capture invalidated")]
436 StreamCaptureInvalidated = 901,
437
438 #[error("CUDA RT: stream capture merge failed")]
440 StreamCaptureMerge = 902,
441
442 #[error("CUDA RT: stream capture unmatched")]
444 StreamCaptureUnmatched = 903,
445
446 #[error("CUDA RT: stream capture unjoined")]
448 StreamCaptureUnjoined = 904,
449
450 #[error("CUDA RT: stream capture isolation")]
452 StreamCaptureIsolation = 905,
453
454 #[error("CUDA RT: stream capture implicit")]
456 StreamCaptureImplicit = 906,
457
458 #[error("CUDA RT: captured event")]
460 CapturedEvent = 907,
461
462 #[error("CUDA RT: stream capture wrong thread")]
464 StreamCaptureWrongThread = 908,
465
466 #[error("CUDA RT: timeout")]
468 Timeout = 909,
469
470 #[error("CUDA RT: CUDA graph exec update failure")]
472 GraphExecUpdateFailure = 910,
473
474 #[error("CUDA RT: external device error")]
476 ExternalDevice = 911,
477
478 #[error("CUDA RT: invalid cluster size")]
480 InvalidClusterSize = 912,
481
482 #[error("CUDA RT: function not loaded")]
484 FunctionNotLoaded = 913,
485
486 #[error("CUDA RT: invalid resource type")]
488 InvalidResourceType = 914,
489
490 #[error("CUDA RT: invalid resource configuration")]
492 InvalidResourceConfiguration = 915,
493
494 #[error("CUDA RT: unknown error")]
496 Unknown = 999,
497
498 #[error("CUDA RT: CUDA driver not available")]
500 DriverNotAvailable,
501
502 #[error("CUDA RT: no GPU device available")]
504 NoGpu,
505
506 #[error("CUDA RT: device not set — call cudaSetDevice before using runtime API")]
508 DeviceNotSet,
509}
510
511pub type CudaRtResult<T> = Result<T, CudaRtError>;
513
514impl CudaRtError {
515 #[must_use]
519 pub fn from_code(code: u32) -> Option<Self> {
520 match code {
521 0 => None, 1 => Some(Self::InvalidValue),
523 2 => Some(Self::MemoryAllocation),
524 3 => Some(Self::InitializationError),
525 4 => Some(Self::CudartUnloading),
526 5 => Some(Self::ProfilerDisabled),
527 9 => Some(Self::InvalidConfiguration),
528 12 => Some(Self::InvalidPitchValue),
529 13 => Some(Self::InvalidSymbol),
530 16 => Some(Self::InvalidHostPointer),
531 17 => Some(Self::InvalidDevicePointer),
532 18 => Some(Self::InvalidTexture),
533 19 => Some(Self::InvalidTextureBinding),
534 20 => Some(Self::InvalidChannelDescriptor),
535 21 => Some(Self::InvalidMemcpyDirection),
536 26 => Some(Self::InvalidFilterSetting),
537 27 => Some(Self::InvalidNormSetting),
538 34 => Some(Self::StubLibrary),
539 35 => Some(Self::InsufficientDriver),
540 36 => Some(Self::CallRequiresNewerDriver),
541 37 => Some(Self::InvalidSurface),
542 43 => Some(Self::DuplicateVariableName),
543 44 => Some(Self::DuplicateTextureName),
544 45 => Some(Self::DuplicateSurfaceName),
545 46 => Some(Self::DevicesUnavailable),
546 49 => Some(Self::IncompatibleDriverContext),
547 52 => Some(Self::MissingConfiguration),
548 65 => Some(Self::LaunchMaxDepthExceeded),
549 66 => Some(Self::LaunchFileScopedTex),
550 67 => Some(Self::LaunchFileScopedSurf),
551 68 => Some(Self::SyncDepthExceeded),
552 69 => Some(Self::LaunchPendingCountExceeded),
553 98 => Some(Self::InvalidDeviceFunction),
554 100 => Some(Self::NoDevice),
555 101 => Some(Self::InvalidDevice),
556 102 => Some(Self::DeviceNotLicensed),
557 103 => Some(Self::SoftwareValidityNotEstablished),
558 127 => Some(Self::StartupFailure),
559 200 => Some(Self::InvalidKernelImage),
560 201 => Some(Self::DeviceUninitialized),
561 205 => Some(Self::MapBufferObjectFailed),
562 206 => Some(Self::UnmapBufferObjectFailed),
563 207 => Some(Self::ArrayIsMapped),
564 208 => Some(Self::AlreadyMapped),
565 209 => Some(Self::NoKernelImageForDevice),
566 210 => Some(Self::AlreadyAcquired),
567 211 => Some(Self::NotMapped),
568 212 => Some(Self::NotMappedAsArray),
569 213 => Some(Self::NotMappedAsPointer),
570 214 => Some(Self::EccUncorrectable),
571 215 => Some(Self::UnsupportedLimit),
572 216 => Some(Self::DeviceAlreadyInUse),
573 217 => Some(Self::PeerAccessUnsupported),
574 218 => Some(Self::InvalidPtx),
575 219 => Some(Self::InvalidGraphicsContext),
576 220 => Some(Self::NvlinkUncorrectable),
577 221 => Some(Self::JitCompilerNotFound),
578 222 => Some(Self::UnsupportedPtxVersion),
579 223 => Some(Self::JitCompilationDisabled),
580 224 => Some(Self::UnsupportedExecAffinity),
581 225 => Some(Self::UnsupportedDevSideSync),
582 300 => Some(Self::InvalidSource),
583 301 => Some(Self::FileNotFound),
584 302 => Some(Self::SharedObjectSymbolNotFound),
585 303 => Some(Self::SharedObjectInitFailed),
586 304 => Some(Self::OperatingSystem),
587 400 => Some(Self::InvalidResourceHandle),
588 401 => Some(Self::IllegalState),
589 402 => Some(Self::LostConnection),
590 500 => Some(Self::SymbolNotFound),
591 600 => Some(Self::NotReady),
592 700 => Some(Self::IllegalAddress),
593 701 => Some(Self::LaunchOutOfResources),
594 702 => Some(Self::LaunchTimeout),
595 703 => Some(Self::LaunchIncompatibleTexturing),
596 704 => Some(Self::PeerAccessAlreadyEnabled),
597 705 => Some(Self::PeerAccessNotEnabled),
598 708 => Some(Self::SetOnActiveProcess),
599 709 => Some(Self::ContextIsDestroyed),
600 710 => Some(Self::Assert),
601 711 => Some(Self::TooManyPeers),
602 712 => Some(Self::HostMemoryAlreadyRegistered),
603 713 => Some(Self::HostMemoryNotRegistered),
604 714 => Some(Self::HardwareStackError),
605 715 => Some(Self::IllegalInstruction),
606 716 => Some(Self::MisalignedAddress),
607 717 => Some(Self::InvalidAddressSpace),
608 718 => Some(Self::InvalidPc),
609 719 => Some(Self::LaunchFailure),
610 720 => Some(Self::CooperativeLaunchTooLarge),
611 800 => Some(Self::NotPermitted),
612 801 => Some(Self::NotSupported),
613 802 => Some(Self::SystemNotReady),
614 803 => Some(Self::SystemDriverMismatch),
615 804 => Some(Self::CompatNotSupportedOnDevice),
616 805 => Some(Self::MpsConnectionFailed),
617 806 => Some(Self::MpsRpcFailure),
618 807 => Some(Self::MpsServerNotReady),
619 808 => Some(Self::MpsMaxClientsReached),
620 809 => Some(Self::MpsMaxConnectionsReached),
621 810 => Some(Self::MpsClientTerminated),
622 811 => Some(Self::CdpNotSupported),
623 812 => Some(Self::CdpVersionMismatch),
624 900 => Some(Self::StreamCaptureUnsupported),
625 901 => Some(Self::StreamCaptureInvalidated),
626 902 => Some(Self::StreamCaptureMerge),
627 903 => Some(Self::StreamCaptureUnmatched),
628 904 => Some(Self::StreamCaptureUnjoined),
629 905 => Some(Self::StreamCaptureIsolation),
630 906 => Some(Self::StreamCaptureImplicit),
631 907 => Some(Self::CapturedEvent),
632 908 => Some(Self::StreamCaptureWrongThread),
633 909 => Some(Self::Timeout),
634 910 => Some(Self::GraphExecUpdateFailure),
635 911 => Some(Self::ExternalDevice),
636 912 => Some(Self::InvalidClusterSize),
637 913 => Some(Self::FunctionNotLoaded),
638 914 => Some(Self::InvalidResourceType),
639 915 => Some(Self::InvalidResourceConfiguration),
640 _ => Some(Self::Unknown),
641 }
642 }
643
644 #[must_use]
646 pub fn is_transient(self) -> bool {
647 matches!(self, Self::NotReady)
648 }
649
650 #[must_use]
652 pub fn is_no_device(self) -> bool {
653 matches!(self, Self::NoDevice | Self::NoGpu | Self::DeviceNotSet)
654 }
655}
656
657impl From<oxicuda_driver::error::CudaError> for CudaRtError {
659 fn from(e: oxicuda_driver::error::CudaError) -> Self {
660 use oxicuda_driver::error::CudaError as D;
662 match e {
663 D::InvalidValue => Self::InvalidValue,
664 D::OutOfMemory => Self::MemoryAllocation,
665 D::NotInitialized => Self::InitializationError,
666 D::Deinitialized => Self::CudartUnloading,
667 D::ProfilerDisabled => Self::ProfilerDisabled,
668 D::StubLibrary => Self::StubLibrary,
669 D::DeviceUnavailable => Self::DevicesUnavailable,
670 D::NoDevice => Self::NoDevice,
671 D::InvalidDevice => Self::InvalidDevice,
672 D::InvalidImage => Self::InvalidKernelImage,
673 D::NotReady => Self::NotReady,
674 D::IllegalAddress => Self::IllegalAddress,
675 D::LaunchOutOfResources => Self::LaunchOutOfResources,
676 D::LaunchTimeout => Self::LaunchTimeout,
677 D::LaunchFailed => Self::LaunchFailure,
678 D::NotPermitted => Self::NotPermitted,
679 D::NotSupported => Self::NotSupported,
680 D::Unknown(_) => Self::Unknown,
681 _ => Self::Unknown,
682 }
683 }
684}
685
686#[cfg(test)]
691mod tests {
692 use super::*;
693
694 #[test]
695 fn from_code_success_returns_none() {
696 assert!(CudaRtError::from_code(0).is_none());
697 }
698
699 #[test]
700 fn from_code_known_errors() {
701 assert_eq!(CudaRtError::from_code(1), Some(CudaRtError::InvalidValue));
702 assert_eq!(
703 CudaRtError::from_code(2),
704 Some(CudaRtError::MemoryAllocation)
705 );
706 assert_eq!(CudaRtError::from_code(100), Some(CudaRtError::NoDevice));
707 assert_eq!(
708 CudaRtError::from_code(719),
709 Some(CudaRtError::LaunchFailure)
710 );
711 assert_eq!(CudaRtError::from_code(999), Some(CudaRtError::Unknown));
712 }
713
714 #[test]
715 fn from_code_unrecognised_becomes_unknown() {
716 assert_eq!(CudaRtError::from_code(12345), Some(CudaRtError::Unknown));
717 }
718
719 #[test]
720 fn is_transient_only_for_not_ready() {
721 assert!(CudaRtError::NotReady.is_transient());
722 assert!(!CudaRtError::LaunchFailure.is_transient());
723 }
724
725 #[test]
726 fn is_no_device_variants() {
727 assert!(CudaRtError::NoDevice.is_no_device());
728 assert!(CudaRtError::NoGpu.is_no_device());
729 assert!(CudaRtError::DeviceNotSet.is_no_device());
730 assert!(!CudaRtError::InvalidValue.is_no_device());
731 }
732
733 #[test]
734 fn error_display() {
735 let e = CudaRtError::MemoryAllocation;
736 assert!(e.to_string().contains("out of device memory"));
737 }
738
739 #[test]
740 fn from_driver_error() {
741 let rt: CudaRtError = oxicuda_driver::error::CudaError::OutOfMemory.into();
742 assert_eq!(rt, CudaRtError::MemoryAllocation);
743 }
744}