2023-02-14 17:50:53 +08:00
|
|
|
#include "detection/gpu/gpu.h"
|
|
|
|
|
#include "detection/vulkan/vulkan.h"
|
2022-09-25 15:23:00 +08:00
|
|
|
#include "detection/temps/temps_linux.h"
|
2024-01-31 10:20:49 +08:00
|
|
|
#include "common/io/io.h"
|
2024-02-12 00:43:06 +08:00
|
|
|
#include "common/properties.h"
|
2023-02-01 15:56:25 +01:00
|
|
|
#include "util/stringUtils.h"
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
|
|
|
|
#include "detection/gpu/gpu_driver_specific.h"
|
2023-06-24 19:38:12 +08:00
|
|
|
#endif
|
|
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
#include <inttypes.h>
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
FF_MAYBE_UNUSED static void pciDetectTemp(FFGPUResult* gpu, uint32_t deviceClass)
|
2022-09-05 17:42:42 +02:00
|
|
|
{
|
2023-11-06 19:08:17 +08:00
|
|
|
const FFlist* tempsResult = ffDetectTemps();
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2023-11-06 19:08:17 +08:00
|
|
|
FF_LIST_FOR_EACH(FFTempValue, tempValue, *tempsResult)
|
2022-09-05 17:42:42 +02:00
|
|
|
{
|
2024-01-31 10:20:49 +08:00
|
|
|
// FIXME: this code doesn't take multiGPUs into count
|
2022-09-05 17:42:42 +02:00
|
|
|
//The kernel exposes the device class multiplied by 256 for some reason
|
2024-01-31 10:20:49 +08:00
|
|
|
if(tempValue->deviceClass == deviceClass * 256)
|
2022-09-05 17:42:42 +02:00
|
|
|
{
|
|
|
|
|
gpu->temperature = tempValue->value;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
2023-01-12 11:41:07 +01:00
|
|
|
{
|
2024-01-31 10:20:49 +08:00
|
|
|
ffStrbufAppendS(pciDir, "/driver");
|
|
|
|
|
char pathBuf[PATH_MAX];
|
|
|
|
|
ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf));
|
|
|
|
|
if(resultLength > 0)
|
2023-01-12 12:54:04 +01:00
|
|
|
{
|
2024-01-31 10:20:49 +08:00
|
|
|
const char* slash = memrchr(pathBuf, '/', (size_t) resultLength);
|
|
|
|
|
if (slash)
|
|
|
|
|
{
|
|
|
|
|
slash++;
|
|
|
|
|
ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash);
|
|
|
|
|
}
|
2023-06-24 19:38:12 +08:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
ffStrbufAppendS(pciDir, "/module/version");
|
|
|
|
|
if (ffReadFileBuffer(pciDir->chars, buffer))
|
|
|
|
|
{
|
|
|
|
|
ffStrbufTrimRightSpace(buffer);
|
|
|
|
|
ffStrbufAppendC(&gpu->driver, ' ');
|
|
|
|
|
ffStrbufAppend(&gpu->driver, buffer);
|
|
|
|
|
}
|
2023-06-24 19:38:12 +08:00
|
|
|
}
|
2023-01-12 11:41:07 +01:00
|
|
|
}
|
|
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
static bool loadPciIds(FFstrbuf* pciids)
|
2022-09-05 17:42:42 +02:00
|
|
|
{
|
2024-01-31 10:20:49 +08:00
|
|
|
ffReadFileBuffer("/usr/share/hwdata/pci.ids", pciids);
|
|
|
|
|
if (pciids->length > 0) return true;
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
ffReadFileBuffer("/usr/share/misc/pci.ids", pciids); // debian?
|
|
|
|
|
if (pciids->length > 0) return true;
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
ffReadFileBuffer("/usr/local/share/hwdata/pci.ids", pciids);
|
|
|
|
|
if (pciids->length > 0) return true;
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
return false;
|
|
|
|
|
}
|
2023-12-29 15:12:41 +08:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
|
|
|
|
{
|
|
|
|
|
//https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-pci
|
|
|
|
|
const char* pciDirPath = "/sys/bus/pci/devices/";
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
DIR* dirp = opendir(pciDirPath);
|
|
|
|
|
if(dirp == NULL)
|
|
|
|
|
return "Failed to open `/sys/bus/pci/devices/`";
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY pciDir = ffStrbufCreateA(64);
|
|
|
|
|
ffStrbufAppendS(&pciDir, pciDirPath);
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
const uint32_t pciBaseDirLength = pciDir.length;
|
2023-01-12 11:41:07 +01:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
|
|
|
|
FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate();
|
2023-06-22 04:06:08 +00:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
struct dirent* entry;
|
|
|
|
|
while((entry = readdir(dirp)) != NULL)
|
2023-10-27 21:05:03 +08:00
|
|
|
{
|
2024-01-31 10:20:49 +08:00
|
|
|
if(entry->d_name[0] == '.')
|
|
|
|
|
continue;
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 18:58:48 +08:00
|
|
|
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
2024-01-31 10:20:49 +08:00
|
|
|
ffStrbufAppendS(&pciDir, entry->d_name);
|
2023-03-13 17:45:36 +08:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
const uint32_t pciDevDirLength = pciDir.length;
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
ffStrbufAppendS(&pciDir, "/modalias");
|
|
|
|
|
if (!ffReadFileBuffer(pciDir.chars, &buffer))
|
|
|
|
|
continue;
|
|
|
|
|
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
|
|
|
|
|
2024-02-11 23:01:14 +08:00
|
|
|
uint32_t vendorId, deviceId, subVendorId, subDeviceId;
|
2024-01-31 10:20:49 +08:00
|
|
|
uint8_t classId, subclassId;
|
2024-02-11 23:01:14 +08:00
|
|
|
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)
|
2024-01-31 10:20:49 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
|
|
|
|
|
if (sscanf(entry->d_name, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus);
|
|
|
|
|
ffStrbufInitStatic(&gpu->vendor, ffGetGPUVendorString((uint16_t) vendorId));
|
|
|
|
|
ffStrbufInit(&gpu->name);
|
|
|
|
|
ffStrbufInit(&gpu->driver);
|
|
|
|
|
ffStrbufInit(&gpu->platformApi);
|
|
|
|
|
gpu->temperature = FF_GPU_TEMP_UNSET;
|
|
|
|
|
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
|
|
|
|
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
|
|
|
|
gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET;
|
|
|
|
|
gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc;
|
|
|
|
|
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
2022-09-21 12:02:14 +02:00
|
|
|
|
2024-02-12 00:43:06 +08:00
|
|
|
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
|
|
|
|
{
|
|
|
|
|
ffStrbufAppendS(&pciDir, "/revision");
|
|
|
|
|
if (ffReadFileBuffer(pciDir.chars, &buffer))
|
|
|
|
|
{
|
|
|
|
|
char* pend;
|
|
|
|
|
uint64_t revision = strtoul(buffer.chars, &pend, 16);
|
|
|
|
|
if (pend != buffer.chars)
|
|
|
|
|
{
|
|
|
|
|
char query[32];
|
|
|
|
|
snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision);
|
|
|
|
|
ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (gpu->name.length == 0)
|
2024-02-12 10:12:22 +08:00
|
|
|
{
|
|
|
|
|
if (!pciids.length)
|
|
|
|
|
loadPciIds(&pciids);
|
2024-02-24 12:50:21 +08:00
|
|
|
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
2024-02-12 10:12:22 +08:00
|
|
|
}
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
pciDetectDriver(gpu, &pciDir, &buffer);
|
|
|
|
|
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
2023-03-13 17:45:36 +08:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
#ifdef FF_USE_PROPRIETARY_GPU_DRIVER_API
|
|
|
|
|
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific))
|
|
|
|
|
{
|
|
|
|
|
ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) {
|
|
|
|
|
.type = FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID,
|
|
|
|
|
.pciBusId = {
|
|
|
|
|
.domain = pciDomain,
|
|
|
|
|
.bus = pciBus,
|
|
|
|
|
.device = pciDevice,
|
|
|
|
|
.func = pciFunc,
|
|
|
|
|
},
|
|
|
|
|
}, (FFGpuDriverResult) {
|
|
|
|
|
.temp = options->temp ? &gpu->temperature : NULL,
|
|
|
|
|
.memory = options->driverSpecific ? &gpu->dedicated : NULL,
|
|
|
|
|
.coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL,
|
|
|
|
|
.type = &gpu->type,
|
|
|
|
|
.frequency = &gpu->frequency,
|
|
|
|
|
}, "libnvidia-ml.so");
|
|
|
|
|
|
|
|
|
|
if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET)
|
|
|
|
|
gpu->type = gpu->dedicated.total > (uint64_t)1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
|
|
|
|
}
|
|
|
|
|
#endif // FF_USE_PROPRIETARY_GPU_DRIVER_API
|
2022-09-05 17:42:42 +02:00
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
#ifdef __linux__
|
|
|
|
|
if(options->temp && gpu->temperature != gpu->temperature)
|
|
|
|
|
pciDetectTemp(gpu, ((uint32_t) classId << 8) + subclassId);
|
|
|
|
|
#endif
|
2022-09-05 17:42:42 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-16 18:11:39 +08:00
|
|
|
return NULL;
|
2022-09-05 17:42:42 +02:00
|
|
|
}
|
|
|
|
|
|
2023-06-24 10:59:53 +08:00
|
|
|
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
2022-09-05 17:42:42 +02:00
|
|
|
{
|
2023-09-20 23:55:36 +08:00
|
|
|
#ifdef FF_HAVE_DIRECTX_HEADERS
|
|
|
|
|
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
|
|
|
|
|
if (!ffGPUDetectByDirectX(options, gpus))
|
|
|
|
|
return NULL;
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-01-31 10:20:49 +08:00
|
|
|
return pciDetectGPUs(options, gpus);
|
2022-09-05 17:42:42 +02:00
|
|
|
}
|