3030#include <curl/curl.h>
3131#include <gio/gio.h>
3232#include <string.h>
33+ #ifdef _WIN32
34+ #include <windows.h>
35+ #endif
3336
3437// forward declarations
3538static gchar * _get_rocm_version (void );
@@ -380,42 +383,59 @@ static gchar *_get_rocm_version(void)
380383// GPU detection
381384// ---------------------------------------------------------------------------
382385
386+ // Get CUDA toolkit version (major.minor) from nvcc, e.g. "13.2".
387+ // Returns NULL if nvcc is not available.
388+ static gchar * _get_cuda_version (void )
389+ {
390+ gchar * nvcc_out = NULL ;
391+ if (!g_spawn_command_line_sync ("nvcc --version" , & nvcc_out , NULL , NULL , NULL )
392+ || !nvcc_out )
393+ return NULL ;
394+ gchar * v = g_strstr_len (nvcc_out , -1 , ", V" );
395+ gchar * result = NULL ;
396+ if (v )
397+ result = _version_major_minor (v + 3 ); // skip ", V"
398+ g_free (nvcc_out );
399+ return result ;
400+ }
401+
383402static dt_ort_gpu_info_t * _detect_nvidia (void )
384403{
385- gchar * output = NULL ;
404+ gchar * gpu_label = NULL ;
405+
386406#ifdef _WIN32
387- const gchar * argv [] = { "nvidia-smi.exe" ,
388- "--query-gpu=name,driver_version" ,
389- "--format=csv,noheader" , NULL };
390- if (!_run_argv (argv , & output ))
407+ // enumerate display adapters via Win32 API — no subprocess overhead
408+ DISPLAY_DEVICEA dev = { .cb = sizeof (dev ) };
409+ for (DWORD i = 0 ; EnumDisplayDevicesA (NULL , i , & dev , 0 ); i ++ )
391410 {
392- // fallback to known absolute path (System32 is always on PATH but
393- // GUI processes occasionally lose env vars)
394- const gchar * argv2 [] = { "C:\\Windows\\System32\\nvidia-smi.exe" ,
395- "--query-gpu=name,driver_version" ,
396- "--format=csv,noheader" , NULL };
397- if (!_run_argv (argv2 , & output ))
398- return NULL ;
411+ if (strstr (dev .DeviceString , "NVIDIA" ))
412+ {
413+ gpu_label = g_strdup (dev .DeviceString );
414+ break ;
415+ }
399416 }
417+ if (!gpu_label ) return NULL ;
400418#else
401- const gchar * argv [] = { " nvidia-smi" ,
402- "--query-gpu=name,driver_version " ,
419+ // Linux: use nvidia-smi to get GPU name
420+ const gchar * argv [] = { "nvidia-smi" , "--query-gpu=name" ,
403421 "--format=csv,noheader" , NULL };
404- if (!_run_argv (argv , & output ))
422+ if (!_run_argv (argv , & gpu_label ) || !gpu_label || !gpu_label [0 ])
423+ {
424+ g_free (gpu_label );
405425 return NULL ;
426+ }
406427#endif
407428
408- // parse "GeForce RTX 4090, 550.54.14"
409- gchar * * fields = g_strsplit (output , "," , 2 );
410- g_free (output );
411- if (!fields [0 ]) { g_strfreev (fields ); return NULL ; }
412-
413429 dt_ort_gpu_info_t * info = g_new0 (dt_ort_gpu_info_t , 1 );
414430 info -> vendor = DT_ORT_GPU_NVIDIA ;
415- info -> label = g_strdup (g_strstrip (fields [0 ]));
416- info -> driver_version = fields [1 ] ? g_strdup (g_strstrip (fields [1 ])) : g_strdup ("unknown" );
431+ info -> label = gpu_label ;
417432 info -> download_size_mb = 200 ;
418- g_strfreev (fields );
433+
434+ gchar * cuda_ver = _get_cuda_version ();
435+ info -> runtime_version = cuda_ver
436+ ? g_strdup_printf ("CUDA %s" , cuda_ver )
437+ : g_strdup ("" );
438+ g_free (cuda_ver );
419439
420440 // check cuDNN
421441 info -> deps_met = TRUE;
@@ -496,7 +516,7 @@ static dt_ort_gpu_info_t *_detect_amd(void)
496516 dt_ort_gpu_info_t * info = g_new0 (dt_ort_gpu_info_t , 1 );
497517 info -> vendor = DT_ORT_GPU_AMD ;
498518 info -> label = gpu_name ? gpu_name : g_strdup ("AMD GPU" );
499- info -> driver_version = g_strdup_printf ("ROCm %s" , rocm_ver );
519+ info -> runtime_version = g_strdup_printf ("ROCm %s" , rocm_ver );
500520 info -> download_size_mb = 300 ;
501521
502522 // check MIGraphX
@@ -527,7 +547,26 @@ static dt_ort_gpu_info_t *_detect_amd(void)
527547static dt_ort_gpu_info_t * _detect_intel (void )
528548{
529549#ifdef _WIN32
530- return NULL ; // OpenVINO EP on Windows uses DirectML instead
550+ // enumerate display adapters via Win32 API — no subprocess overhead
551+ DISPLAY_DEVICEA dev = { .cb = sizeof (dev ) };
552+ gchar * gpu_name = NULL ;
553+ for (DWORD i = 0 ; EnumDisplayDevicesA (NULL , i , & dev , 0 ); i ++ )
554+ {
555+ if (strstr (dev .DeviceString , "Intel" ))
556+ {
557+ gpu_name = g_strdup (dev .DeviceString );
558+ break ;
559+ }
560+ }
561+ if (!gpu_name ) return NULL ;
562+
563+ dt_ort_gpu_info_t * info = g_new0 (dt_ort_gpu_info_t , 1 );
564+ info -> vendor = DT_ORT_GPU_INTEL ;
565+ info -> label = gpu_name ;
566+ info -> runtime_version = g_strdup ("" );
567+ info -> deps_met = TRUE; // OpenVINO runtime is downloaded with the ORT package
568+ info -> download_size_mb = 100 ; // ORT 60MB + OpenVINO runtime 38MB
569+ return info ;
531570#elif defined(__APPLE__ )
532571 return NULL ;
533572#else
@@ -543,7 +582,7 @@ static dt_ort_gpu_info_t *_detect_intel(void)
543582 dt_ort_gpu_info_t * info = g_new0 (dt_ort_gpu_info_t , 1 );
544583 info -> vendor = DT_ORT_GPU_INTEL ;
545584 info -> label = gpu_name ? gpu_name : g_strdup ("Intel GPU" );
546- info -> driver_version = g_strdup ("" );
585+ info -> runtime_version = g_strdup ("" );
547586 info -> deps_met = TRUE; // OpenVINO wheel bundles everything
548587 info -> download_size_mb = 150 ;
549588
@@ -571,7 +610,7 @@ void dt_ort_gpu_info_free(dt_ort_gpu_info_t *info)
571610{
572611 if (!info ) return ;
573612 g_free (info -> label );
574- g_free (info -> driver_version );
613+ g_free (info -> runtime_version );
575614 g_free (info -> deps_missing );
576615 g_free (info -> deps_hint );
577616 g_free (info );
0 commit comments