@@ -10,6 +10,16 @@ static int isGpuNameEqual(const FFGPUResult* gpu, const FFstrbuf* name)
1010    return  ffStrbufEqual (& gpu -> name , name );
1111}
1212
13+ static  int  isDeviceIdEqual (const  FFWindowGPUPci *  pci , const  FFstrbuf *  deviceId )
14+ {
15+     return  ffStrbufEqual (& pci -> deviceId , deviceId );
16+ }
17+ 
18+ static  int  isBusEqual (const  uint32_t *  bus , uint32_t *  bus2 )
19+ {
20+     return  * bus  ==  * bus2 ;
21+ }
22+ 
1323static  inline  bool  getDriverSpecificDetectionFn (const  char *  vendor , __typeof__ (& ffDetectNvidiaGpuInfo )*  pDetectFn , const  char * *  pDllName )
1424{
1525    if  (vendor  ==  FF_GPU_VENDOR_NAME_NVIDIA )
@@ -54,6 +64,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
5464    const  uint32_t  regControlVideoKeyPrefixLength  =  (uint32_t ) wcslen (regControlVideoKey );
5565    const  uint32_t  deviceKeyPrefixLength  =  strlen ("\\Registry\\Machine\\" ) +  regControlVideoKeyPrefixLength ;
5666
67+     FF_LIST_AUTO_DESTROY  pcis  =  ffListCreate (sizeof  (FFWindowGPUPci ));
68+ 
5769    for  (DWORD  i  =  0 ; EnumDisplayDevicesW (NULL , i , & displayDevice , 0 ); ++ i )
5870    {
5971        if  (displayDevice .StateFlags  &  DISPLAY_DEVICE_MIRRORING_DRIVER ) continue ;
@@ -74,6 +86,88 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
7486        // displayDevice.DeviceID = MatchingDeviceId "PCI\\VEN_10DE&DEV_2782&SUBSYS_513417AA&REV_A1" 
7587        unsigned  vendorId  =  0 , deviceId  =  0 , subSystemId  =  0 , revId  =  0 ;
7688        swscanf (displayDevice .DeviceID , L"PCI\\VEN_%x&DEV_%x&SUBSYS_%x&REV_%x" , & vendorId , & deviceId , & subSystemId , & revId );
89+         
90+         wchar_t  regEnumPciKey [MAX_PATH ] =  L"SYSTEM\\CurrentControlSet\\Enum\\" ;
91+         const  uint32_t  regEnumPciKeyPrefixLength  =  (uint32_t ) wcslen (regEnumPciKey );
92+         
93+ 
94+         FF_STRBUF_AUTO_DESTROY  pciStrBuf  =  ffStrbufCreateWS (displayDevice .DeviceID );
95+         size_t  deviceIDLength  =  wcslen (displayDevice .DeviceID );
96+         
97+         if  (regEnumPciKeyPrefixLength  +  deviceIDLength  >= MAX_PATH ) {
98+             continue ;
99+         }
100+         wmemcpy (regEnumPciKey  +  regEnumPciKeyPrefixLength , displayDevice .DeviceID , deviceIDLength );
101+         
102+         uint32_t  pciBusId  =  FF_GPU_BUS_UNSET ;
103+         uint32_t  pciIndex  =  0 ;
104+         pciIndex  =  ffListFirstIndexComp (& pcis , & pciStrBuf , (void * ) isDeviceIdEqual );
105+         if  (pciIndex  !=  pcis .length  &&  pcis .length  >  0 ) {
106+             FFWindowGPUPci *  gpuPci  =  (FFWindowGPUPci * )ffListGet (& pcis , pciIndex );
107+             for  (uint32_t  i  =  0 ; i  <  gpuPci -> busNumber ; ++ i )
108+             {
109+                 uint32_t *  currentPciBusId  =  ffListGet (& gpuPci -> buses , i );
110+                 if  (!ffListContains (& gpuPci -> usedBuses , currentPciBusId ,  (void * ) isBusEqual )) {
111+                     pciBusId  =  * currentPciBusId ;
112+                     * (uint32_t * ) ffListAdd (& gpuPci -> usedBuses ) =  pciBusId ;
113+                     break ;
114+                 }
115+             }
116+ 
117+         } else  {
118+             FFWindowGPUPci *  gpuPci  =  (FFWindowGPUPci * )ffListAdd (& pcis );
119+             gpuPci -> deviceId  =  pciStrBuf ;
120+             ffListInit (& gpuPci -> buses , sizeof (uint32_t ));
121+             ffListInit (& gpuPci -> usedBuses , sizeof (uint32_t ));         
122+ 
123+             FF_HKEY_AUTO_DESTROY  hKey  =  NULL ;
124+             if (ffRegOpenKeyForRead (HKEY_LOCAL_MACHINE , regEnumPciKey , & hKey , NULL ))
125+             {
126+                 if  (!ffRegGetNSubKeys (hKey , & gpuPci -> busNumber , NULL ))
127+                 {
128+                     continue ;
129+                 }
130+ 
131+ 
132+                 for  (uint32_t  i  =  0 ; i  <  gpuPci -> busNumber ; ++ i )
133+                 {
134+                     FF_STRBUF_AUTO_DESTROY  subKey  =  ffStrbufCreate ();
135+                     if  (!ffRegGetSubKey (hKey , i , & subKey , NULL )) {
136+                         continue ;
137+                     }
138+ 
139+                     wchar_t *  widePciDeviceKey  =  ffStrbufToWideChar (& subKey );
140+                     if  (widePciDeviceKey  ==  NULL ) {
141+                         continue ;
142+                     }
143+ 
144+                     FF_HKEY_AUTO_DESTROY  pciDevicHKey  =  NULL ;
145+                     if  (!ffRegOpenKeyForRead (hKey , widePciDeviceKey , & pciDevicHKey , NULL ))
146+                     {
147+                         free (widePciDeviceKey );
148+                         continue ;
149+                     }
150+                     free (widePciDeviceKey );
151+                     
152+                     // LocationInformation example: @System32\\drivers\\pci.sys,#65536;PCI bus %1, device %2, function %3;(114,0,0) 
153+                     FF_STRBUF_AUTO_DESTROY  locationInformation  =  ffStrbufCreate ();
154+                     if  (!ffRegReadStrbuf (pciDevicHKey , L"LocationInformation" , & locationInformation , NULL )){
155+                         continue ;
156+                     }
157+                         
158+                     int  busId  =  -1 ;
159+                     if  (sscanf (locationInformation .chars , "@System32\\drivers\\pci.sys,#65536;PCI bus %%1, device %%2, function %%3;(%d" , & busId ) ==  1 ) {
160+                         * (uint32_t * ) ffListAdd (& gpuPci -> buses ) =  (uint32_t )busId ;
161+                     } 
162+                 }
163+ 
164+                 if  (gpuPci -> buses .length  >  0 ) {
165+                     uint32_t *  busId  =  ffListGet (& gpuPci -> buses , 0 );
166+                     pciBusId  =  * busId ;
167+                     * (uint32_t * ) ffListAdd (& gpuPci -> usedBuses ) =  * busId ;
168+                 }
169+             } 
170+         } 
77171
78172        FFGPUResult *  gpu  =  (FFGPUResult * )ffListAdd (gpus );
79173        ffStrbufInitStatic (& gpu -> vendor , ffGetGPUVendorString (vendorId ));
@@ -157,6 +251,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist*
157251                            .vendorId  =  vendorId ,
158252                            .subSystemId  =  subSystemId ,
159253                            .revId  =  revId ,
254+                             .bus  =  pciBusId ,
160255                        },
161256                        .luid  =  gpu -> deviceId ,
162257                    },
0 commit comments