mirror of
https://github.com/FeralInteractive/gamemode.git
synced 2025-09-17 17:49:41 +02:00
gpu: Fix NVIDIA GPU index detection when card0 is missing
On systems without /sys/class/drm/card0, gamemode fails to detect the correct NVIDIA GPU index when the GPU device is explicitly set in gamemode.ini. This patch adjusts get_gpu_index_id_nv() to skip over non-NVIDIA devices without prematurely failing, correctly mapping the configured DRM device index to the NVML index. Fixes: #486 Tested on: RTX 3070 (driver 575.64.03) on Ubuntu 25.04, cards 0-2 and some other random numbers were tested
This commit is contained in:
@@ -67,6 +67,14 @@ static void print_usage_and_exit(void)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return 1 if /sys/class/drm/card<idx>/device/vendor exists and is readable, else 0 */
|
||||||
|
static int drm_card_exists(int idx)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
snprintf(path, PATH_MAX, "/sys/class/drm/card%d/device/vendor", idx);
|
||||||
|
return access(path, R_OK) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *get_nv_attr(const char *attr)
|
static const char *get_nv_attr(const char *attr)
|
||||||
{
|
{
|
||||||
static char out[EXTERNAL_BUFFER_MAX];
|
static char out[EXTERNAL_BUFFER_MAX];
|
||||||
@@ -91,37 +99,41 @@ static int set_nv_attr(const char *attr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the nvidia driver index for the current GPU */
|
/* Get the nvidia driver index for the current GPU
|
||||||
|
* Map DRM card index (info->device) -> nvidia-settings GPU index.
|
||||||
|
* We only count *existing* DRM cards and only increment on NVIDIA vendors.
|
||||||
|
*/
|
||||||
static long get_gpu_index_id_nv(struct GameModeGPUInfo *info)
|
static long get_gpu_index_id_nv(struct GameModeGPUInfo *info)
|
||||||
{
|
{
|
||||||
if (info->vendor != Vendor_NVIDIA)
|
if (info->vendor != Vendor_NVIDIA)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* NOTE: This is currently based off of a best guess of how the NVidia gpu index works
|
|
||||||
* ie. that the index is simply the index into available NV gpus in the same order as drm
|
|
||||||
* If that is not the case then this may fail to discern the correct GPU
|
|
||||||
*/
|
|
||||||
|
|
||||||
int device = 0;
|
|
||||||
int nv_device = -1;
|
int nv_device = -1;
|
||||||
while (device <= info->device) {
|
|
||||||
/* Get the vendor for each gpu sequentially */
|
|
||||||
enum GPUVendor vendor = gamemode_get_gpu_vendor(device++);
|
|
||||||
|
|
||||||
switch (vendor) {
|
/* Iterate over DRM card numbers up to the requested one,
|
||||||
case Vendor_NVIDIA:
|
* but skip holes like a missing card0.
|
||||||
/* If we've found an nvidia device, increment our counter */
|
*/
|
||||||
|
for (int device = 0; device <= info->device; device++) {
|
||||||
|
/* Skip non-existent DRM indices to avoid noisy /sys errors */
|
||||||
|
if (!drm_card_exists(device))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Probe vendor only for existing cards */
|
||||||
|
enum GPUVendor vendor = gamemode_get_gpu_vendor(device);
|
||||||
|
|
||||||
|
if (vendor == Vendor_NVIDIA) {
|
||||||
|
/* Each NVIDIA DRM card before/at info->device bumps the NV index */
|
||||||
nv_device++;
|
nv_device++;
|
||||||
break;
|
} else {
|
||||||
case Vendor_Invalid:
|
/* Non-NVIDIA or unreadable -> just ignore */
|
||||||
/* Bail out, we've gone too far */
|
continue;
|
||||||
LOG_ERROR("Failed to find Nvidia GPU with expected index!\n");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Non-NV gpu, continue */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
if (nv_device < 0) {
|
||||||
|
LOG_ERROR("Could not resolve NVIDIA index for DRM card%ld (no NVIDIA cards found up to that index)\n",
|
||||||
|
info->device);
|
||||||
|
}
|
||||||
|
|
||||||
return nv_device;
|
return nv_device;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user