GPU: adds egl-ext detection method

This commit is contained in:
Carter Li
2026-06-18 19:49:21 +08:00
committed by 李通洲
parent 508a50f803
commit 240928138e
4 changed files with 137 additions and 12 deletions
+4
View File
@@ -2850,6 +2850,10 @@
"const": "opencl",
"description": "Use OpenCL API.\nSlow and requires proper OpenCL drivers to be installed"
},
{
"const": "egl-ext",
"description": "Use EGL_EXT_device_enumeration and EGL_EXT_device_query APIs.\nSlow and only detects GPUs that support these extensions"
},
{
"const": "opengl",
"description": "Use OpenGL API.\nSlow and only detects one GPU.\nUsed for OpenBSD"
+128 -12
View File
@@ -77,6 +77,25 @@ const char* ffGPUGetVendorString(unsigned vendorId) {
}
}
static bool normalizeVendorName(FFGPUResult* gpu) {
if (ffStrbufContainS(&gpu->name, "Apple")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
gpu->type = FF_GPU_TYPE_INTEGRATED;
} else if (ffStrbufContainS(&gpu->name, "Intel")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
} else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
} else if (ffStrbufContainS(&gpu->name, "NVIDIA")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
} else if (ffStrbufContainS(&gpu->name, "MTT")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
} else {
return false;
}
return true;
}
const char* detectByOpenGL(FFlist* gpus) {
FF_DEBUG("Starting OpenGL GPU detection fallback");
@@ -114,18 +133,7 @@ const char* detectByOpenGL(FFlist* gpus) {
gpu->vendor.chars,
result.version.chars);
if (ffStrbufContainS(&gpu->name, "Apple")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
gpu->type = FF_GPU_TYPE_INTEGRATED;
} else if (ffStrbufContainS(&gpu->name, "Intel")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
} else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
} else if (ffStrbufContainS(&gpu->name, "NVIDIA")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
} else if (ffStrbufContainS(&gpu->name, "MTT")) {
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
}
normalizeVendorName(gpu);
FF_DEBUG("OpenGL fallback produced GPU: name='%s', vendor='%s', type=%u",
gpu->name.chars,
@@ -141,6 +149,98 @@ const char* detectByOpenGL(FFlist* gpus) {
return error;
}
#if defined(FF_HAVE_EGL) || __has_include(<EGL/egl.h>)
#include <EGL/egl.h>
#include <EGL/eglext.h>
#if EGL_EXT_device_base && EGL_EXT_device_persistent_id && EGL_EXT_device_query_name
#define FF_HAVE_EGL_EXT 1
#include <inttypes.h>
#include "common/library.h"
#include "common/strutil.h"
#include "common/io.h"
const char* detectByEglext(FFlist* result) {
FF_LIBRARY_LOAD_MESSAGE(egl, "libEGL" FF_LIBRARY_EXTENSION, 1);
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(egl, eglGetProcAddress);
PFNEGLQUERYDEVICESEXTPROC ffeglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC) ffeglGetProcAddress("eglQueryDevicesEXT");
if (!ffeglQueryDevicesEXT) {
return "eglQueryDevicesEXT is unavailable";
}
PFNEGLQUERYDEVICESTRINGEXTPROC ffeglQueryDeviceStringEXT = (PFNEGLQUERYDEVICESTRINGEXTPROC) ffeglGetProcAddress("eglQueryDeviceStringEXT");
if (!ffeglQueryDeviceStringEXT) {
return "eglQueryDeviceStringEXT is unavailable";
}
PFNEGLQUERYDEVICEBINARYEXTPROC ffeglQueryDeviceBinaryEXT = (PFNEGLQUERYDEVICEBINARYEXTPROC) ffeglGetProcAddress("eglQueryDeviceBinaryEXT");
if (!ffeglQueryDeviceBinaryEXT) {
return "eglQueryDeviceBinaryEXT is unavailable";
}
FF_DEBUG("Loaded EGL library and required symbols");
FF_SUPPRESS_IO();
EGLDeviceEXT devices[16];
EGLint numDevices;
if (ffeglQueryDevicesEXT(ARRAY_SIZE(devices), devices, &numDevices) == EGL_TRUE) {
FF_DEBUG("eglQueryDevicesEXT() returned %d device(s)", numDevices);
for (EGLint i = 0; i < numDevices; i++) {
const EGLDeviceEXT device = &devices[i];
if (device == (EGLDeviceEXT) EGL_NO_DEVICE_EXT || device == (EGLDeviceEXT) EGL_BAD_DEVICE_EXT) {
FF_DEBUG("eglQueryDevicesEXT() returned invalid device at index %d", i);
continue;
}
const char* exts = (const char*) ffeglQueryDeviceStringEXT(devices[i], EGL_EXTENSIONS);
FF_DEBUG("eglQueryDeviceStringEXT() returned extensions for device %d: %s", i, exts);
if (exts && ffStrContains(exts, "EGL_MESA_device_software")) {
FF_DEBUG("eglQueryDeviceStringEXT() returned software device at index %d, skipping", i);
continue;
}
const char* name = ffeglQueryDeviceStringEXT(devices[i], EGL_RENDERER_EXT);
if (!name) {
FF_DEBUG("eglQueryDeviceStringEXT() returned NULL name for device %d, skipping", i);
continue;
}
FFGPUResult* gpu = FF_LIST_ADD(FFGPUResult, *result);
ffStrbufInitS(&gpu->name, name);
ffStrbufInit(&gpu->vendor);
ffStrbufInitS(&gpu->driver, ffeglQueryDeviceStringEXT(devices[i], EGL_DRIVER_NAME_EXT));
ffStrbufInitF(&gpu->platformApi, "egl-ext");
ffStrbufInit(&gpu->memoryType);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->temperature = FF_GPU_TEMP_UNSET;
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
gpu->coreUsage = FF_GPU_CORE_USAGE_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 = 0;
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
gpu->pcieSpeed = FF_GPU_PCIE_SPEED_UNSET;
ffeglQueryDeviceBinaryEXT(devices[i], EGL_DEVICE_UUID_EXT, sizeof(gpu->deviceId), &gpu->deviceId, NULL);
if (!normalizeVendorName(gpu)) {
ffStrbufSetS(&gpu->vendor, ffeglQueryDeviceStringEXT(devices[i], EGL_VENDOR));
}
FF_DEBUG("Detected GPU %d: vendor='%s', name='%s', driver='%s', id='%16" PRIX64 "'", i, gpu->vendor.chars, gpu->name.chars, gpu->driver.chars, gpu->deviceId);
}
} else {
FF_DEBUG("eglQueryDevicesEXT() returned EGL_FALSE");
}
return NULL;
}
#endif
#endif
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) {
FF_DEBUG("Starting GPU detection with method=%d", (int) options->detectionMethod);
@@ -193,6 +293,22 @@ const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result) {
opencl->error ?: "none",
opencl->gpus.length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_EGL_EXT) {
#if FF_HAVE_EGL_EXT
FF_DEBUG("Trying EGL_EXT GPU detection fallback");
const char* error = detectByEglext(result);
if (!error && result->length > 0) {
FF_DEBUG("EGL_EXT GPU detection succeeded with %u GPU(s)", result->length);
return NULL;
}
FF_DEBUG("EGL_EXT GPU detection did not produce results (error=%s, gpuCount=%u)",
error ?: "none",
result->length);
#else
FF_DEBUG("EGL_EXT GPU detection is unavailable");
#endif
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENGL) {
FF_DEBUG("Trying OpenGL GPU detection fallback");
const char* error = detectByOpenGL(result);
+4
View File
@@ -244,6 +244,7 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module) {
{ "pci", FF_GPU_DETECTION_METHOD_PCI },
{ "vulkan", FF_GPU_DETECTION_METHOD_VULKAN },
{ "opencl", FF_GPU_DETECTION_METHOD_OPENCL },
{ "egl-ext", FF_GPU_DETECTION_METHOD_EGL_EXT },
{ "opengl", FF_GPU_DETECTION_METHOD_OPENGL },
{},
});
@@ -302,6 +303,9 @@ void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_
case FF_GPU_DETECTION_METHOD_OPENCL:
yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opencl");
break;
case FF_GPU_DETECTION_METHOD_EGL_EXT:
yyjson_mut_obj_add_str(doc, module, "detectionMethod", "egl-ext");
break;
case FF_GPU_DETECTION_METHOD_OPENGL:
yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opengl");
break;
+1
View File
@@ -15,6 +15,7 @@ typedef enum FF_A_PACKED FFGPUDetectionMethod {
FF_GPU_DETECTION_METHOD_PCI,
FF_GPU_DETECTION_METHOD_VULKAN,
FF_GPU_DETECTION_METHOD_OPENCL,
FF_GPU_DETECTION_METHOD_EGL_EXT,
FF_GPU_DETECTION_METHOD_OPENGL,
} FFGPUDetectionMethod;