GPU: adds debug logs

Thanks Github Copilot
This commit is contained in:
李通洲
2026-02-12 18:30:02 +08:00
parent 0f4bb47c2f
commit 4038ed2656
3 changed files with 193 additions and 3 deletions
+50 -2
View File
@@ -1,4 +1,5 @@
#include "gpu.h"
#include "common/debug.h"
#include "detection/vulkan/vulkan.h"
#include "detection/opencl/opencl.h"
#include "detection/opengl/opengl.h"
@@ -50,6 +51,8 @@ const char* ffGPUGetVendorString(unsigned vendorId)
const char* detectByOpenGL(FFlist* gpus)
{
FF_DEBUG("Starting OpenGL GPU detection fallback");
FFOpenGLResult result;
ffStrbufInit(&result.version);
ffStrbufInit(&result.renderer);
@@ -60,6 +63,7 @@ const char* detectByOpenGL(FFlist* gpus)
__attribute__((__cleanup__(ffDestroyOpenGLOptions))) FFOpenGLOptions options;
ffInitOpenGLOptions(&options);
const char* error = ffDetectOpenGL(&options, &result);
FF_DEBUG("OpenGL detection returns: %s", error ?: "success");
if (!error)
{
@@ -78,6 +82,11 @@ const char* detectByOpenGL(FFlist* gpus)
gpu->dedicated = gpu->shared = (FFGPUMemory){0, 0};
gpu->deviceId = 0;
FF_DEBUG("OpenGL reported renderer='%s', vendor='%s', version='%s'",
gpu->name.chars,
gpu->vendor.chars,
result.version.chars);
if (ffStrbufContainS(&gpu->name, "Apple"))
{
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
@@ -92,6 +101,11 @@ const char* detectByOpenGL(FFlist* gpus)
else if (ffStrbufContainS(&gpu->name, "MTT"))
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_MTHREADS);
FF_DEBUG("OpenGL fallback produced GPU: name='%s', vendor='%s', type=%u",
gpu->name.chars,
gpu->vendor.chars,
gpu->type);
}
ffStrbufDestroy(&result.version);
@@ -104,43 +118,77 @@ const char* detectByOpenGL(FFlist* gpus)
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
{
FF_DEBUG("Starting GPU detection with method=%d", (int) options->detectionMethod);
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_PCI)
{
FF_DEBUG("Trying PCI/native GPU detection");
const char* error = ffDetectGPUImpl(options, result);
if (!error && result->length > 0) return NULL;
if (!error && result->length > 0)
{
FF_DEBUG("PCI/native GPU detection succeeded with %u GPU(s)", result->length);
return NULL;
}
FF_DEBUG("PCI/native GPU detection did not produce results (error=%s, gpuCount=%u)",
error ?: "none",
result->length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_VULKAN)
{
FF_DEBUG("Trying Vulkan GPU detection fallback");
FFVulkanResult* vulkan = ffDetectVulkan();
if (!vulkan->error && vulkan->gpus.length > 0)
{
FF_DEBUG("Vulkan detection succeeded with %u GPU(s)", vulkan->gpus.length);
ffListDestroy(result);
ffListInitMove(result, &vulkan->gpus);
#ifdef __ANDROID__
double ffGPUDetectTempFromTZ(void);
if (options->temp && result->length == 1)
{
FF_DEBUG("Applying Android thermal-zone temperature to single Vulkan GPU");
FF_LIST_GET(FFGPUResult, *result, 0)->temperature = ffGPUDetectTempFromTZ();
}
#endif
return NULL;
}
FF_DEBUG("Vulkan detection did not produce results (error=%s, gpuCount=%u)",
vulkan->error ?: "none",
vulkan->gpus.length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENCL)
{
FF_DEBUG("Trying OpenCL GPU detection fallback");
FFOpenCLResult* opencl = ffDetectOpenCL();
if (!opencl->error && opencl->gpus.length > 0)
{
FF_DEBUG("OpenCL detection succeeded with %u GPU(s)", opencl->gpus.length);
ffListDestroy(result);
ffListInitMove(result, &opencl->gpus);
return NULL;
}
FF_DEBUG("OpenCL detection did not produce results (error=%s, gpuCount=%u)",
opencl->error ?: "none",
opencl->gpus.length);
}
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENGL)
{
if (detectByOpenGL(result) == NULL)
FF_DEBUG("Trying OpenGL GPU detection fallback");
const char* error = detectByOpenGL(result);
if (error == NULL)
{
FF_DEBUG("OpenGL fallback succeeded with %u GPU(s)", result->length);
return NULL;
}
FF_DEBUG("OpenGL fallback failed: %s", error);
}
FF_DEBUG("GPU detection failed in all enabled backends");
return "GPU detection failed";
}
+72 -1
View File
@@ -1,4 +1,5 @@
#include "opengl.h"
#include "common/debug.h"
#include "common/library.h"
#if __has_include(<GL/gl.h>)
@@ -56,26 +57,48 @@ typedef struct EGLData
static const char* eglHandleContext(FFOpenGLResult* result, EGLData* data)
{
FF_DEBUG("Making EGL context current");
if(data->ffeglMakeCurrent(data->display, data->surface, data->surface, data->context) != EGL_TRUE)
{
FF_DEBUG("eglMakeCurrent() returned EGL_FALSE");
return "eglMakeCurrent returned EGL_FALSE";
}
ffOpenGLHandleResult(result, data->ffglGetString);
ffStrbufSetF(&result->library, "EGL %s", data->ffeglQueryString(data->display, EGL_VERSION));
FF_DEBUG("OpenGL via EGL detected: version='%s', renderer='%s', vendor='%s', slv='%s', library='%s'",
result->version.chars,
result->renderer.chars,
result->vendor.chars,
result->slv.chars,
result->library.chars);
return NULL;
}
static const char* eglHandleSurface(FFOpenGLResult* result, EGLData* data, bool gles)
{
FF_DEBUG("Creating EGL context (preferred API=%s, client version=%d)", gles ? "OpenGL ES" : "OpenGL", gles ? 2 : 1);
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){
EGL_CONTEXT_CLIENT_VERSION, gles ? 2 : 1, // Try GLES 2.0+ first
EGL_NONE
});
if(data->context == EGL_NO_CONTEXT && gles) // Some ANGLE builds support GLES 1.1 only
{
FF_DEBUG("EGL context creation with GLES 2.x failed, retrying with default attributes (GLES 1.1 fallback)");
data->context = data->ffeglCreateContext(data->display, data->config, EGL_NO_CONTEXT, (EGLint[]){EGL_NONE});
}
if(data->context == EGL_NO_CONTEXT)
{
FF_DEBUG("eglCreateContext() returned EGL_NO_CONTEXT");
return "eglCreateContext returned EGL_NO_CONTEXT";
}
FF_DEBUG("EGL context created successfully");
const char* error = eglHandleContext(result, data);
FF_DEBUG("eglHandleContext() returns: %s", error ?: "success");
FF_DEBUG("Destroying EGL context");
data->ffeglDestroyContext(data->display, data->context);
return error;
}
@@ -84,13 +107,21 @@ static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
{
// try use OpenGL API. If failed, use the default API (usually OpenGL ES)
bool gles = !data->ffeglBindAPI(EGL_OPENGL_API);
FF_DEBUG("eglBindAPI(EGL_OPENGL_API) %s, effective API=%s",
gles ? "failed" : "succeeded",
gles ? "default (usually OpenGL ES)" : "OpenGL");
EGLint eglConfigCount;
data->ffeglGetConfigs(data->display, &data->config, 1, &eglConfigCount);
FF_DEBUG("eglGetConfigs() returned %d config(s)", eglConfigCount);
if(eglConfigCount == 0)
{
FF_DEBUG("No EGL config is available");
return "eglGetConfigs returned 0 configs";
}
FF_DEBUG("Creating EGL pbuffer surface (%dx%d)", FF_OPENGL_BUFFER_WIDTH, FF_OPENGL_BUFFER_HEIGHT);
data->surface = data->ffeglCreatePbufferSurface(data->display, data->config, (EGLint[]){
EGL_WIDTH, FF_OPENGL_BUFFER_WIDTH,
EGL_HEIGHT, FF_OPENGL_BUFFER_HEIGHT,
@@ -98,39 +129,71 @@ static const char* eglHandleDisplay(FFOpenGLResult* result, EGLData* data)
});
if(data->surface == EGL_NO_SURFACE)
{
FF_DEBUG("eglCreatePbufferSurface() returned EGL_NO_SURFACE");
return "eglCreatePbufferSurface returned EGL_NO_SURFACE";
}
FF_DEBUG("EGL pbuffer surface created successfully");
const char* error = eglHandleSurface(result, data, gles);
FF_DEBUG("eglHandleSurface() returns: %s", error ?: "success");
FF_DEBUG("Destroying EGL surface");
data->ffeglDestroySurface(data->display, data->surface);
return error;
}
static const char* eglHandleData(FFOpenGLResult* result, EGLData* data)
{
FF_DEBUG("Resolving glGetString via eglGetProcAddress()");
data->ffglGetString = (__typeof__(&glGetString)) data->ffeglGetProcAddress("glGetString");
if(!data->ffglGetString)
{
FF_DEBUG("eglGetProcAddress('glGetString') returned NULL");
return "eglGetProcAddress(glGetString) returned NULL";
}
#if EGL_VERSION_1_5
PFNEGLGETPLATFORMDISPLAYEXTPROC ffeglGetPlatformDisplay = (PFNEGLGETPLATFORMDISPLAYEXTPROC) data->ffeglGetProcAddress("eglGetPlatformDisplay");
if (ffeglGetPlatformDisplay)
{
FF_DEBUG("Trying eglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA)");
data->display = ffeglGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, NULL, NULL);
FF_DEBUG("eglGetPlatformDisplay() %s", data->display == EGL_NO_DISPLAY ? "failed" : "succeeded");
}
else
FF_DEBUG("eglGetPlatformDisplay is unavailable, falling back to eglGetDisplay");
if(!ffeglGetPlatformDisplay || data->display == EGL_NO_DISPLAY)
#endif
{
FF_DEBUG("Trying eglGetDisplay(EGL_DEFAULT_DISPLAY)");
data->display = data->ffeglGetDisplay(EGL_DEFAULT_DISPLAY);
if(data->display == EGL_NO_DISPLAY)
{
FF_DEBUG("eglGetDisplay() returned EGL_NO_DISPLAY");
return "eglGetDisplay returned EGL_NO_DISPLAY";
}
FF_DEBUG("eglGetDisplay() succeeded");
}
EGLint major, minor;
if(data->ffeglInitialize(data->display, &major, &minor) == EGL_FALSE)
{
FF_DEBUG("eglInitialize() returned EGL_FALSE");
return "eglInitialize returned EGL_FALSE";
}
FF_DEBUG("EGL initialized successfully: %d.%d", major, minor);
const char* error = eglHandleDisplay(result, data);
FF_DEBUG("eglHandleDisplay() returns: %s", error ?: "success");
FF_DEBUG("Terminating EGL display connection");
data->ffeglTerminate(data->display);
return error;
}
@@ -138,6 +201,7 @@ static const char* eglHandleData(FFOpenGLResult* result, EGLData* data)
const char* ffOpenGLDetectByEGL(FFOpenGLResult* result)
{
FF_DEBUG("Starting OpenGL detection via EGL");
EGLData eglData;
FF_LIBRARY_LOAD_MESSAGE(egl, "libEGL" FF_LIBRARY_EXTENSION, 1);
@@ -154,8 +218,15 @@ const char* ffOpenGLDetectByEGL(FFOpenGLResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglDestroySurface);
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(egl, eglData, eglTerminate);
FF_DEBUG("Loaded EGL library and required symbols");
FF_SUPPRESS_IO();
return eglHandleData(result, &eglData);
FF_DEBUG("Suppressed stdout/stderr during EGL probing");
const char* error = eglHandleData(result, &eglData);
FF_DEBUG("OpenGL detection via EGL returns: %s", error ?: "success");
return error;
}
#endif //FF_HAVE_EGL
+71
View File
@@ -1,4 +1,5 @@
#include "fastfetch.h"
#include "common/debug.h"
#include "detection/gpu/gpu.h"
#include "detection/vulkan/vulkan.h"
@@ -39,6 +40,8 @@ static void applyDriverName(VkPhysicalDeviceDriverPropertiesKHR* properties, FFs
static const char* detectVulkan(FFVulkanResult* result)
{
FF_DEBUG("Starting Vulkan detection");
FF_LIBRARY_LOAD_MESSAGE(vulkan,
#if __APPLE__
"libMoltenVK" FF_LIBRARY_EXTENSION, -1
@@ -56,6 +59,7 @@ static const char* detectVulkan(FFVulkanResult* result)
//Some drivers (nvdc) print messages to stdout
//and that is the best way I found to disable that
FF_SUPPRESS_IO();
FF_DEBUG("Suppressed stdout/stderr during Vulkan probing to avoid noisy drivers");
FFVersion instanceVersion = FF_VERSION_INIT;
@@ -66,8 +70,15 @@ static const char* detectVulkan(FFVulkanResult* result)
{
uint32_t version;
if(ffvkEnumerateInstanceVersion(&version) == VK_SUCCESS)
{
applyVulkanVersion(version, &instanceVersion);
FF_DEBUG("Detected Vulkan instance version: %u.%u.%u", instanceVersion.major, instanceVersion.minor, instanceVersion.patch);
}
else
FF_DEBUG("vkEnumerateInstanceVersion() is available but returned a non-success status");
}
else
FF_DEBUG("vkEnumerateInstanceVersion() is unavailable (likely Vulkan 1.0 runtime)");
const uint32_t projectVersion = VK_MAKE_VERSION(
FASTFETCH_PROJECT_VERSION_MAJOR,
@@ -76,6 +87,7 @@ static const char* detectVulkan(FFVulkanResult* result)
);
VkInstance vkInstance;
FF_DEBUG("Creating Vulkan instance with requested API version %s", instanceVersion.minor >= 1 ? "1.1" : "1.0");
VkResult res = ffvkCreateInstance(&(VkInstanceCreateInfo) {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = NULL,
@@ -98,6 +110,7 @@ static const char* detectVulkan(FFVulkanResult* result)
}, NULL, &vkInstance);
if(res != VK_SUCCESS)
{
FF_DEBUG("ffvkCreateInstance() failed with VkResult=%d", res);
switch (res)
{
case VK_ERROR_OUT_OF_HOST_MEMORY:
@@ -116,17 +129,22 @@ static const char* detectVulkan(FFVulkanResult* result)
return "ffvkCreateInstance() failed: unknown error";
}
}
FF_DEBUG("Vulkan instance created successfully");
//if instance creation succeeded, but vkEnumerateInstanceVersion didn't, this means we are running against a vulkan 1.0 implementation
//explicitly set this version, if no device is found, so we still have at least this info
if(instanceVersion.major == 0 && instanceVersion.minor == 0 && instanceVersion.patch == 0)
{
instanceVersion.major = 1;
FF_DEBUG("Falling back to Vulkan instance version 1.0 due to unavailable enumerate call");
}
VkPhysicalDevice physicalDevices[128];
uint32_t physicalDeviceCount = (uint32_t) ARRAY_SIZE(physicalDevices);
res = ffvkEnumeratePhysicalDevices(vkInstance, &physicalDeviceCount, physicalDevices);
if(res != VK_SUCCESS)
{
FF_DEBUG("ffvkEnumeratePhysicalDevices() failed with VkResult=%d", res);
ffvkDestroyInstance(vkInstance, NULL);
switch (res)
{
@@ -142,13 +160,22 @@ static const char* detectVulkan(FFVulkanResult* result)
return "ffvkEnumeratePhysicalDevices() failed";
}
}
FF_DEBUG("Enumerated %u Vulkan physical device(s)", physicalDeviceCount);
PFN_vkGetPhysicalDeviceProperties ffvkGetPhysicalDeviceProperties = NULL;
PFN_vkGetPhysicalDeviceProperties2 ffvkGetPhysicalDeviceProperties2 = (PFN_vkGetPhysicalDeviceProperties2) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties2"); // 1.1
if(!ffvkGetPhysicalDeviceProperties2)
ffvkGetPhysicalDeviceProperties = (PFN_vkGetPhysicalDeviceProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceProperties");
FF_DEBUG("Using %s for querying physical device properties", ffvkGetPhysicalDeviceProperties2 ? "vkGetPhysicalDeviceProperties2" : "vkGetPhysicalDeviceProperties");
PFN_vkGetPhysicalDeviceMemoryProperties ffvkGetPhysicalDeviceMemoryProperties = (PFN_vkGetPhysicalDeviceMemoryProperties) ffvkGetInstanceProcAddr(vkInstance, "vkGetPhysicalDeviceMemoryProperties");
if(!ffvkGetPhysicalDeviceMemoryProperties)
{
FF_DEBUG("vkGetPhysicalDeviceMemoryProperties is unavailable");
ffvkDestroyInstance(vkInstance, NULL);
return "vkGetPhysicalDeviceMemoryProperties is not available";
}
FFVersion maxDeviceApiVersion = FF_VERSION_INIT;
FFVersion maxDeviceConformanceVersion = FF_VERSION_INIT;
@@ -172,10 +199,19 @@ static const char* detectVulkan(FFVulkanResult* result)
else
ffvkGetPhysicalDeviceProperties(physicalDevices[i], &physicalDeviceProperties.properties);
FF_DEBUG("Processing Vulkan device #%u: name='%s', vendorId=0x%04X, deviceId=0x%04X, type=%u", i,
physicalDeviceProperties.properties.deviceName,
physicalDeviceProperties.properties.vendorID,
physicalDeviceProperties.properties.deviceID,
physicalDeviceProperties.properties.deviceType);
//We don't want software rasterizers to show up as physical gpu
if(physicalDeviceProperties.properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU)
{
FF_DEBUG("Skipping CPU Vulkan device '%s'", physicalDeviceProperties.properties.deviceName);
continue;
}
//If the device api version is higher than the current highest device api version, overwrite it
//In this case, also use the current device driver name as the shown driver name
@@ -186,6 +222,11 @@ static const char* detectVulkan(FFVulkanResult* result)
{
maxDeviceApiVersion = deviceAPIVersion;
applyDriverName(&driverProperties, &result->driver);
FF_DEBUG("Updated max Vulkan device API version to %u.%u.%u (driver='%s')",
maxDeviceApiVersion.major,
maxDeviceApiVersion.minor,
maxDeviceApiVersion.patch,
result->driver.chars);
}
//If the device conformance version is higher than the current highest device conformance version, overwrite it
@@ -198,7 +239,13 @@ static const char* detectVulkan(FFVulkanResult* result)
};
if(ffVersionCompare(&deviceConformanceVersion, &maxDeviceConformanceVersion) > 0)
{
maxDeviceConformanceVersion = deviceConformanceVersion;
FF_DEBUG("Updated max Vulkan conformance version to %u.%u.%u",
maxDeviceConformanceVersion.major,
maxDeviceConformanceVersion.minor,
maxDeviceConformanceVersion.patch);
}
}
//Add the device to the list of devices shown by the GPU module
@@ -207,7 +254,10 @@ static const char* detectVulkan(FFVulkanResult* result)
FF_LIST_FOR_EACH(FFGPUResult, gpu, result->gpus)
{
if (gpu->deviceId == physicalDeviceProperties.properties.deviceID)
{
FF_DEBUG("Skipping duplicate Vulkan GPU entry for deviceId=0x%04X", physicalDeviceProperties.properties.deviceID);
goto next;
}
}
FFGPUResult* gpu = ffListAdd(&result->gpus);
@@ -221,6 +271,10 @@ static const char* detectVulkan(FFVulkanResult* result)
ffStrbufInitS(&gpu->vendor, ffGPUGetVendorString(physicalDeviceProperties.properties.vendorID));
ffStrbufInitS(&gpu->driver, driverProperties.driverInfo);
ffStrbufInit(&gpu->memoryType);
FF_DEBUG("Added Vulkan GPU '%s' (vendor='%s', type=%s)",
gpu->name.chars,
gpu->vendor.chars,
gpu->type == FF_GPU_TYPE_DISCRETE ? "discrete" : "integrated");
VkPhysicalDeviceMemoryProperties memoryProperties = {};
ffvkGetPhysicalDeviceMemoryProperties(physicalDevices[i], &memoryProperties);
@@ -233,6 +287,10 @@ static const char* detectVulkan(FFVulkanResult* result)
FFGPUMemory* vmem = gpu->type == FF_GPU_TYPE_DISCRETE && (heap->flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? &gpu->dedicated : &gpu->shared;
vmem->total += heap->size;
}
FF_DEBUG("Computed memory for '%s': dedicatedTotal=%llu, sharedTotal=%llu",
gpu->name.chars,
(unsigned long long) gpu->dedicated.total,
(unsigned long long) gpu->shared.total);
//No way to detect those using vulkan
gpu->index = FF_GPU_INDEX_UNSET;
@@ -249,7 +307,14 @@ static const char* detectVulkan(FFVulkanResult* result)
ffVersionToPretty(&maxDeviceApiVersion, &result->apiVersion);
ffVersionToPretty(&maxDeviceConformanceVersion, &result->conformanceVersion);
FF_DEBUG("Vulkan detection finished: instanceVersion=%s, apiVersion=%s, conformanceVersion=%s, gpuCount=%u",
result->instanceVersion.chars,
result->apiVersion.chars,
result->conformanceVersion.chars,
result->gpus.length);
ffvkDestroyInstance(vkInstance, NULL);
FF_DEBUG("Destroyed Vulkan instance");
return NULL;
}
@@ -261,6 +326,7 @@ FFVulkanResult* ffDetectVulkan(void)
if (result.gpus.elementSize == 0)
{
FF_DEBUG("Initializing Vulkan detection cache");
ffStrbufInit(&result.driver);
ffStrbufInit(&result.apiVersion);
ffStrbufInit(&result.conformanceVersion);
@@ -269,10 +335,15 @@ FFVulkanResult* ffDetectVulkan(void)
#ifdef FF_HAVE_VULKAN
result.error = detectVulkan(&result);
if (result.error)
FF_DEBUG("Vulkan detection returned error: %s", result.error);
#else
result.error = "fastfetch was compiled without vulkan support";
FF_DEBUG("Vulkan support is disabled at compile time");
#endif
}
else
FF_DEBUG("Reusing cached Vulkan detection result");
return &result;
}