@@ -22,6 +22,27 @@ public enum OrtCompiledModelCompatibility
2222 EP_UNSUPPORTED = 3 ,
2323 }
2424
25+ /// <summary>
26+ /// Reasons why an execution provider might not be compatible with a device.
27+ /// </summary>
28+ /// <remarks>
29+ /// This is a flags enum. Multiple reasons can be combined using bitwise OR.
30+ /// </remarks>
31+ [ Flags ]
32+ public enum OrtDeviceEpIncompatibilityReason : uint
33+ {
34+ /// <summary>No incompatibility.</summary>
35+ None = 0 ,
36+ /// <summary>Driver is incompatible with the execution provider.</summary>
37+ DriverIncompatible = 1 << 0 ,
38+ /// <summary>Device itself is incompatible with the execution provider.</summary>
39+ DeviceIncompatible = 1 << 1 ,
40+ /// <summary>Required dependency is missing.</summary>
41+ MissingDependency = 1 << 2 ,
42+ /// <summary>Unknown incompatibility reason.</summary>
43+ Unknown = 1u << 31
44+ }
45+
2546 /// <summary>
2647 /// Delegate for logging function callback.
2748 /// Supply your function and register it with the environment to receive logging callbacks via
@@ -593,6 +614,76 @@ public string GetCompatibilityInfoFromModelBytes(byte[] modelData, string epType
593614 return NativeOnnxValueHelper . StringFromNativeUtf8 ( compatInfoPtr , allocator ) ;
594615 }
595616
617+ /// <summary>
618+ /// Get the number of available hardware devices.
619+ /// </summary>
620+ /// <returns>The number of hardware devices discovered on the system.</returns>
621+ public int GetNumHardwareDevices ( )
622+ {
623+ NativeApiStatus . VerifySuccess (
624+ NativeMethods . OrtGetNumHardwareDevices ( Handle , out UIntPtr numDevices ) ) ;
625+ return checked ( ( int ) numDevices ) ;
626+ }
627+
628+ /// <summary>
629+ /// Get the list of available hardware devices.
630+ /// </summary>
631+ /// <returns>A list of OrtHardwareDevice objects. The underlying native handles are owned by ORT and should not be released.</returns>
632+ public IReadOnlyList < OrtHardwareDevice > GetHardwareDevices ( )
633+ {
634+ NativeApiStatus . VerifySuccess (
635+ NativeMethods . OrtGetNumHardwareDevices ( Handle , out UIntPtr numDevices ) ) ;
636+
637+ int count = checked ( ( int ) numDevices ) ;
638+ if ( count == 0 )
639+ {
640+ return Array . Empty < OrtHardwareDevice > ( ) ;
641+ }
642+
643+ var devicePtrs = new IntPtr [ count ] ;
644+ NativeApiStatus . VerifySuccess (
645+ NativeMethods . OrtGetHardwareDevices ( Handle , devicePtrs , numDevices ) ) ;
646+
647+ var devices = new OrtHardwareDevice [ count ] ;
648+ for ( int i = 0 ; i < count ; i ++ )
649+ {
650+ devices [ i ] = new OrtHardwareDevice ( devicePtrs [ i ] ) ;
651+ }
652+ return devices ;
653+ }
654+
655+ /// <summary>
656+ /// Check for known incompatibility issues between a hardware device and a specific execution provider.
657+ /// </summary>
658+ /// <param name="epName">The name of the execution provider to check.</param>
659+ /// <param name="hardwareDevice">The hardware device to check for incompatibility.</param>
660+ /// <returns>Details about incompatibility including reasons and notes.</returns>
661+ /// <remarks>
662+ /// This method can be used with built-in execution providers without calling
663+ /// RegisterExecutionProviderLibrary.
664+ /// For execution providers supplied by external libraries, the provider library must be
665+ /// registered before calling this method.
666+ /// If the returned details have non-zero reasons, the device is not compatible.
667+ /// However, zero reasons don't guarantee 100% compatibility for all models.
668+ /// </remarks>
669+ public OrtDeviceEpIncompatibilityDetails GetHardwareDeviceEpIncompatibilityDetails (
670+ string epName , OrtHardwareDevice hardwareDevice )
671+ {
672+ if ( epName == null )
673+ throw new ArgumentNullException ( nameof ( epName ) ) ;
674+ if ( epName . Length == 0 )
675+ throw new ArgumentException ( "epName must be non-empty" , nameof ( epName ) ) ;
676+ if ( hardwareDevice == null )
677+ throw new ArgumentNullException ( nameof ( hardwareDevice ) ) ;
678+
679+ var epNameUtf8 = NativeOnnxValueHelper . StringToZeroTerminatedUtf8 ( epName ) ;
680+ NativeApiStatus . VerifySuccess (
681+ NativeMethods . OrtGetHardwareDeviceEpIncompatibilityDetails (
682+ Handle , epNameUtf8 , hardwareDevice . Handle , out IntPtr details ) ) ;
683+
684+ return new OrtDeviceEpIncompatibilityDetails ( details ) ;
685+ }
686+
596687
597688 /// <summary>
598689 /// Get/Set log level property of OrtEnv instance
@@ -738,4 +829,120 @@ protected override bool ReleaseHandle()
738829 }
739830 #endregion
740831 }
832+
833+ /// <summary>
834+ /// Contains details about why an execution provider is incompatible with a hardware device.
835+ /// </summary>
836+ /// <remarks>
837+ /// This class wraps the native OrtDeviceEpIncompatibilityDetails object.
838+ /// Use the properties to query specific incompatibility information.
839+ /// </remarks>
840+ public sealed class OrtDeviceEpIncompatibilityDetails : IDisposable
841+ {
842+ private IntPtr _handle ;
843+ private bool _disposed = false ;
844+
845+ /// <summary>
846+ /// Creates a new OrtDeviceEpIncompatibilityDetails wrapper.
847+ /// </summary>
848+ /// <param name="handle">The native handle to wrap.</param>
849+ internal OrtDeviceEpIncompatibilityDetails ( IntPtr handle )
850+ {
851+ _handle = handle ;
852+ }
853+
854+ /// <summary>
855+ /// Gets the bitmask of incompatibility reasons.
856+ /// </summary>
857+ /// <remarks>
858+ /// If this value is 0 (None), there are no known incompatibility issues.
859+ /// However, this doesn't guarantee 100% compatibility for all models.
860+ /// </remarks>
861+ public OrtDeviceEpIncompatibilityReason ReasonsBitmask
862+ {
863+ get
864+ {
865+ if ( _disposed )
866+ throw new ObjectDisposedException ( nameof ( OrtDeviceEpIncompatibilityDetails ) ) ;
867+
868+ NativeApiStatus . VerifySuccess (
869+ NativeMethods . OrtDeviceEpIncompatibilityDetails_GetReasonsBitmask ( _handle , out uint bitmask ) ) ;
870+ return ( OrtDeviceEpIncompatibilityReason ) bitmask ;
871+ }
872+ }
873+
874+ /// <summary>
875+ /// Gets human-readable notes about the incompatibility.
876+ /// </summary>
877+ /// <remarks>
878+ /// May be null if no notes are available.
879+ /// </remarks>
880+ public string Notes
881+ {
882+ get
883+ {
884+ if ( _disposed )
885+ throw new ObjectDisposedException ( nameof ( OrtDeviceEpIncompatibilityDetails ) ) ;
886+
887+ NativeApiStatus . VerifySuccess (
888+ NativeMethods . OrtDeviceEpIncompatibilityDetails_GetNotes ( _handle , out IntPtr notesPtr ) ) ;
889+
890+ if ( notesPtr == IntPtr . Zero )
891+ return null ;
892+
893+ return NativeOnnxValueHelper . StringFromNativeUtf8 ( notesPtr ) ;
894+ }
895+ }
896+
897+ /// <summary>
898+ /// Gets the EP-specific error code.
899+ /// </summary>
900+ /// <remarks>
901+ /// This allows Independent Hardware Vendors (IHVs) to define their own error codes
902+ /// to provide additional details about device incompatibility.
903+ /// A value of 0 indicates no error code was set.
904+ /// </remarks>
905+ public int ErrorCode
906+ {
907+ get
908+ {
909+ if ( _disposed )
910+ throw new ObjectDisposedException ( nameof ( OrtDeviceEpIncompatibilityDetails ) ) ;
911+
912+ NativeApiStatus . VerifySuccess (
913+ NativeMethods . OrtDeviceEpIncompatibilityDetails_GetErrorCode ( _handle , out int errorCode ) ) ;
914+ return errorCode ;
915+ }
916+ }
917+
918+ /// <summary>
919+ /// Disposes the native resources.
920+ /// </summary>
921+ public void Dispose ( )
922+ {
923+ Dispose ( true ) ;
924+ GC . SuppressFinalize ( this ) ;
925+ }
926+
927+ private void Dispose ( bool disposing )
928+ {
929+ if ( ! _disposed )
930+ {
931+ if ( _handle != IntPtr . Zero )
932+ {
933+ NativeMethods . OrtReleaseDeviceEpIncompatibilityDetails ( _handle ) ;
934+ _handle = IntPtr . Zero ;
935+ }
936+ _disposed = true ;
937+ }
938+ }
939+
940+ /// <summary>
941+ /// Finalizer.
942+ /// </summary>
943+ ~ OrtDeviceEpIncompatibilityDetails ( )
944+ {
945+ Dispose ( false ) ;
946+ }
947+ }
741948}
0 commit comments