From 330eb9fa21f0c372154fe7e6e1690096bd99afae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 11 Feb 2024 23:01:14 +0800 Subject: [PATCH] GPU: show sub-device if available Try fixing #713 --- CMakeLists.txt | 2 + src/detection/gpu/gpu.c | 72 ------------------------------- src/detection/gpu/gpu.h | 4 +- src/detection/gpu/gpu_bsd.c | 2 +- src/detection/gpu/gpu_linux.c | 6 +-- src/detection/gpu/gpu_pci.c | 81 +++++++++++++++++++++++++++++++++++ 6 files changed, 89 insertions(+), 78 deletions(-) create mode 100644 src/detection/gpu/gpu_pci.c diff --git a/CMakeLists.txt b/CMakeLists.txt index dcb829ad4..3cb9a60eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -401,6 +401,7 @@ if(LINUX) src/detection/displayserver/linux/xlib.c src/detection/font/font_linux.c src/detection/gpu/gpu_linux.c + src/detection/gpu/gpu_pci.c src/detection/gtk_qt/gtk.c src/detection/host/host_linux.c src/detection/icons/icons_linux.c @@ -518,6 +519,7 @@ elseif(BSD) src/detection/displayserver/linux/xlib.c src/detection/font/font_linux.c src/detection/gpu/gpu_bsd.c + src/detection/gpu/gpu_pci.c src/detection/gtk_qt/gtk.c src/detection/host/host_bsd.c src/detection/lm/lm_linux.c diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index 7368d3039..3f65e1791 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -118,75 +118,3 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) return "GPU detection failed"; } - -#ifndef _WIN32 -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) -{ - if (content->length) - { - char buffer[32]; - uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor); - char* start = (char*) memmem(content->chars, content->length, buffer, len); - char* end = content->chars + content->length; - if (start) - { - start += len; - end = memchr(start, '\n', (uint32_t) (end - start)); - if (!end) - end = content->chars + content->length; - if (!gpu->vendor.length) - ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start); - - start = end; // point to '\n' of vendor - end = start + 1; // point to start of devices - // find the start of next vendor - while (end[0] == '\t' || end[0] == '#') - { - end = strchr(end, '\n'); - if (!end) - { - end = content->chars + content->length; - break; - } - else - end++; - } - - len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device); - start = memmem(start, (size_t) (end - start), buffer, len); - if (start) - { - start += len; - end = memchr(start, '\n', (uint32_t) (end - start)); - if (!end) - end = content->chars + content->length; - - char* openingBracket = memchr(start, '[', (uint32_t) (end - start)); - if (openingBracket) - { - openingBracket++; - char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket)); - if (closingBracket) - ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); - } - if (!gpu->name.length) - ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start); - } - } - } - - if (!gpu->name.length) - { - const char* subclassStr; - switch (subclass) - { - case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break; - case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break; - case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break; - default: subclassStr = ""; break; - } - - ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr); - } -} -#endif diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index b3d6b035f..8f404f243 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -43,6 +43,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffGetGPUVendorString(unsigned vendorId); -#ifndef _WIN32 -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); +#if defined(__linux__) || defined(__FreeBSD__) +void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, uint16_t subVendor, uint16_t subDevice, FFGPUResult* gpu); #endif diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index c51ef7ffb..cb9f39c54 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -64,7 +64,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); + ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, pc->pc_subvendor, pc->pc_subdevice, gpu); #ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 979e25d7c..789f9b6dd 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -98,9 +98,9 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus) continue; ffStrbufSubstrBefore(&pciDir, pciDevDirLength); - uint32_t vendorId, deviceId; + uint32_t vendorId, deviceId, subVendorId, subDeviceId; uint8_t classId, subclassId; - if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%*8ssd%*8sbc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &classId, &subclassId) != 4) + if (sscanf(buffer.chars, "pci:v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6) continue; if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) @@ -122,7 +122,7 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus) gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, (uint16_t) subVendorId, (uint16_t) subDeviceId, gpu); pciDetectDriver(gpu, &pciDir, &buffer); ffStrbufSubstrBefore(&pciDir, pciDevDirLength); diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c new file mode 100644 index 000000000..e8d454aec --- /dev/null +++ b/src/detection/gpu/gpu_pci.c @@ -0,0 +1,81 @@ +#include "gpu.h" + +void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, uint16_t subVendor, uint16_t subDevice, FFGPUResult* gpu) +{ + if (content->length) + { + char buffer[32]; + + // Search for vendor + uint32_t len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n%04x ", vendor); + char* start = (char*) memmem(content->chars, content->length, buffer, len); + char* end = content->chars + content->length; + if (start) + { + start += len; + end = memchr(start, '\n', (uint32_t) (end - start)); + if (!end) + end = content->chars + content->length; + if (!gpu->vendor.length) + ffStrbufSetNS(&gpu->vendor, (uint32_t) (end - start), start); + + start = end; // point to '\n' of vendor + end = start + 1; // point to start of devices + // find the start of next vendor + while (end[0] == '\t' || end[0] == '#') + { + end = strchr(end, '\n'); + if (!end) + { + end = content->chars + content->length; + break; + } + else + end++; + } + + // Search for device + len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t%04x ", device); + start = memmem(start, (size_t) (end - start), buffer, len); + if (start) + { + start += len; + + // Search for subvendor and subdevice + len = (uint32_t) snprintf(buffer, sizeof(buffer), "\n\t\t%04x %04x ", subVendor, subDevice); + char* subStart = memmem(start, (size_t) (end - start), buffer, len); + if (subStart) + start = subStart + len; + + end = memchr(start, '\n', (uint32_t) (end - start)); + if (!end) + end = content->chars + content->length; + + char* openingBracket = memchr(start, '[', (uint32_t) (end - start)); + if (openingBracket) + { + openingBracket++; + char* closingBracket = memchr(openingBracket, ']', (uint32_t) (end - openingBracket)); + if (closingBracket) + ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); + } + if (!gpu->name.length) + ffStrbufSetNS(&gpu->name, (uint32_t) (end - start), start); + } + } + } + + if (!gpu->name.length) + { + const char* subclassStr; + switch (subclass) + { + case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break; + case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break; + case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break; + default: subclassStr = ""; break; + } + + ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr); + } +}