Skip to content

Commit 2230240

Browse files
committed
fix: gpustack wrong gpu info for windows with multi nvidia gpu
1 parent 0a202cd commit 2230240

File tree

6 files changed

+143
-2
lines changed

6 files changed

+143
-2
lines changed

src/detection/gpu/gpu.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define FF_GPU_FREQUENCY_UNSET (0/0.0)
99
#define FF_GPU_CORE_UTILIZATION_RATE_UNSET -1
1010
#define FF_GPU_INDEX_UNSET ((uint8_t)-1)
11+
#define FF_GPU_BUS_UNSET ((uint32_t)-1)
1112

1213
extern const char* FF_GPU_VENDOR_NAME_APPLE;
1314
extern const char* FF_GPU_VENDOR_NAME_AMD;
@@ -43,6 +44,15 @@ typedef struct FFGPUResult
4344
FFstrbuf uuid; // Identifier for the GPU
4445
} FFGPUResult;
4546

47+
typedef struct FFWindowGPUPci
48+
{
49+
FFstrbuf deviceId;
50+
FFlist buses;
51+
FFlist usedBuses;
52+
uint32_t busNumber;
53+
} FFWindowGPUPci;
54+
55+
4656
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result);
4757
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus);
4858

src/detection/gpu/gpu_driver_specific.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ typedef struct FFGpuDriverPciDeviceId
2323
uint32_t vendorId;
2424
uint32_t subSystemId;
2525
uint32_t revId;
26+
uint32_t bus;
2627
} FFGpuDriverPciDeviceId;
2728

2829
// Use pciBusId if not NULL; use pciDeviceId otherwise

src/detection/gpu/gpu_nvidia.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR
8585
continue;
8686

8787
if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) ||
88-
pciInfo.pciSubSystemId != cond->pciDeviceId.subSystemId)
88+
pciInfo.pciSubSystemId != cond->pciDeviceId.subSystemId || (cond->pciDeviceId.bus != FF_GPU_BUS_UNSET && (uint32_t)pciInfo.bus != cond->pciDeviceId.bus))
8989
continue;
9090

9191
break;

src/detection/gpu/gpu_windows.c

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
1323
static 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
},

src/util/windows/unicode.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "unicode.h"
2-
2+
#include <stdlib.h>
33
#include <windows.h>
44

55
void ffStrbufSetNWS(FFstrbuf* result, uint32_t length, const wchar_t* source)
@@ -31,3 +31,36 @@ void ffStrbufInitNWS(FFstrbuf* result, uint32_t length, const wchar_t* source)
3131
result->length = (uint32_t)size_needed;
3232
result->chars[size_needed] = '\0';
3333
}
34+
35+
wchar_t* ffStrbufToWideChar(const FFstrbuf* strbuf)
36+
{
37+
if(strbuf->length == 0)
38+
{
39+
wchar_t* emptyStr = (wchar_t*)malloc(sizeof(wchar_t));
40+
emptyStr[0] = L'\0';
41+
return emptyStr;
42+
}
43+
44+
int wcharCount = MultiByteToWideChar(CP_UTF8, 0, strbuf->chars, (int)strbuf->length, NULL, 0);
45+
if(wcharCount == 0)
46+
{
47+
return NULL;
48+
}
49+
50+
wchar_t* wideStr = (wchar_t*)malloc((uint32_t)(wcharCount + 1) * sizeof(wchar_t));
51+
if(wideStr == NULL)
52+
{
53+
return NULL;
54+
}
55+
56+
int32_t result = MultiByteToWideChar(CP_UTF8, 0, strbuf->chars, (int)strbuf->length, wideStr, wcharCount);
57+
if(result == 0)
58+
{
59+
free(wideStr);
60+
return NULL;
61+
}
62+
63+
wideStr[wcharCount] = L'\0';
64+
65+
return wideStr;
66+
}

src/util/windows/unicode.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ static inline void ffStrbufSetWS(FFstrbuf* result, const wchar_t* source)
1616

1717
void ffStrbufInitNWS(FFstrbuf* result, uint32_t length, const wchar_t* source);
1818

19+
wchar_t* ffStrbufToWideChar(const FFstrbuf* strbuf);
20+
1921
static inline void ffStrbufInitWS(FFstrbuf* result, const wchar_t* source)
2022
{
2123
if (!source) return ffStrbufInit(result);

0 commit comments

Comments
 (0)