core: log gpu information in debuginfo

This commit is contained in:
outfoxxed 2026-03-14 02:31:47 -07:00
parent 1123d5ab4f
commit 1b2519d9f3
No known key found for this signature in database
GPG key ID: 4C88A185FB89301E
7 changed files with 82 additions and 3 deletions

View file

@ -20,6 +20,7 @@ Checks: >
-cppcoreguidelines-avoid-do-while, -cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-pro-type-reinterpret-cast, -cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-type-vararg, -cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-pro-type-union-access,
-cppcoreguidelines-use-enum-class, -cppcoreguidelines-use-enum-class,
google-global-names-in-headers, google-global-names-in-headers,
google-readability-casting, google-readability-casting,

View file

@ -33,6 +33,7 @@ Quickshell has a set of base dependencies you will always need, names vary by di
- `cmake` - `cmake`
- `qt6base` - `qt6base`
- `qt6declarative` - `qt6declarative`
- `libdrm`
- `qtshadertools` (build-time) - `qtshadertools` (build-time)
- `spirv-tools` (build-time) - `spirv-tools` (build-time)
- `pkg-config` (build-time) - `pkg-config` (build-time)
@ -146,7 +147,6 @@ Enables streaming video from monitors and toplevel windows through various proto
To disable: `-DSCREENCOPY=OFF` To disable: `-DSCREENCOPY=OFF`
Dependencies: Dependencies:
- `libdrm`
- `libgbm` - `libgbm`
- `vulkan-headers` (build-time) - `vulkan-headers` (build-time)

View file

@ -64,3 +64,4 @@ set shell id.
- `vulkan-headers` has been added as a build-time dependency for screencopy (Vulkan backend support). - `vulkan-headers` has been added as a build-time dependency for screencopy (Vulkan backend support).
- `breakpad` has been replaced by `cpptrace`, which is far easier to package, and the `CRASH_REPORTER` cmake variable has been replaced with `CRASH_HANDLER` to stop this from being easy to ignore. - `breakpad` has been replaced by `cpptrace`, which is far easier to package, and the `CRASH_REPORTER` cmake variable has been replaced with `CRASH_HANDLER` to stop this from being easy to ignore.
- `DISTRIBUTOR_DEBUGINFO_AVAILABLE` was removed as it is no longer important without breakpad. - `DISTRIBUTOR_DEBUGINFO_AVAILABLE` was removed as it is no longer important without breakpad.
- `libdrm` is now unconditionally required as a direct dependency.

View file

@ -76,6 +76,7 @@
buildInputs = [ buildInputs = [
qt6.qtbase qt6.qtbase
qt6.qtdeclarative qt6.qtdeclarative
libdrm
cli11 cli11
] ]
++ lib.optional withQtSvg qt6.qtsvg ++ lib.optional withQtSvg qt6.qtsvg
@ -88,7 +89,7 @@
++ lib.optional withJemalloc jemalloc ++ lib.optional withJemalloc jemalloc
++ lib.optional (withWayland && lib.strings.compareVersions qt6.qtbase.version "6.10.0" == -1) qt6.qtwayland ++ lib.optional (withWayland && lib.strings.compareVersions qt6.qtbase.version "6.10.0" == -1) qt6.qtwayland
++ lib.optionals withWayland [ wayland wayland-protocols ] ++ lib.optionals withWayland [ wayland wayland-protocols ]
++ lib.optionals (withWayland && libgbm != null) [ libdrm libgbm vulkan-headers ] ++ lib.optionals (withWayland && libgbm != null) [ libgbm vulkan-headers ]
++ lib.optional withX11 libxcb ++ lib.optional withX11 libxcb
++ lib.optional withPam pam ++ lib.optional withPam pam
++ lib.optional withPipewire pipewire ++ lib.optional withPipewire pipewire

View file

@ -1,3 +1,4 @@
pkg_check_modules(libdrm REQUIRED IMPORTED_TARGET libdrm)
qt_add_library(quickshell-core STATIC qt_add_library(quickshell-core STATIC
plugin.cpp plugin.cpp
shell.cpp shell.cpp
@ -54,7 +55,7 @@ qt_add_qml_module(quickshell-core
install_qml_module(quickshell-core) install_qml_module(quickshell-core)
target_link_libraries(quickshell-core PRIVATE Qt::Quick Qt::QuickPrivate Qt::Widgets quickshell-build) target_link_libraries(quickshell-core PRIVATE Qt::Quick Qt::QuickPrivate Qt::Widgets quickshell-build PkgConfig::libdrm)
qs_module_pch(quickshell-core SET large) qs_module_pch(quickshell-core SET large)

View file

@ -7,8 +7,10 @@
#include <qfile.h> #include <qfile.h>
#include <qfloat16.h> #include <qfloat16.h>
#include <qhashfunctions.h> #include <qhashfunctions.h>
#include <qscopeguard.h>
#include <qtversion.h> #include <qtversion.h>
#include <unistd.h> #include <unistd.h>
#include <xf86drm.h>
#include "build.hpp" #include "build.hpp"
@ -20,10 +22,82 @@ QString qsVersion() {
QString qtVersion() { return qVersion() % QStringLiteral(" (built against " QT_VERSION_STR ")"); } QString qtVersion() { return qVersion() % QStringLiteral(" (built against " QT_VERSION_STR ")"); }
QString gpuInfo() {
auto deviceCount = drmGetDevices2(0, nullptr, 0);
if (deviceCount < 0) return "Failed to get DRM device count: " % QString::number(deviceCount);
auto* devices = new drmDevicePtr[deviceCount];
auto devicesArrayGuard = qScopeGuard([&] { delete[] devices; });
auto r = drmGetDevices2(0, devices, deviceCount);
if (deviceCount < 0) return "Failed to get DRM devices: " % QString::number(r);
auto devicesGuard = qScopeGuard([&] {
for (auto i = 0; i != deviceCount; ++i) drmFreeDevice(&devices[i]); // NOLINT
});
QString info;
auto stream = QTextStream(&info);
for (auto i = 0; i != deviceCount; ++i) {
auto* device = devices[i]; // NOLINT
int deviceNodeType = -1;
if (device->available_nodes & (1 << DRM_NODE_RENDER)) deviceNodeType = DRM_NODE_RENDER;
else if (device->available_nodes & (1 << DRM_NODE_PRIMARY)) deviceNodeType = DRM_NODE_PRIMARY;
if (deviceNodeType == -1) continue;
auto* deviceNode = device->nodes[DRM_NODE_RENDER]; // NOLINT
auto driver = [&]() -> QString {
auto fd = open(deviceNode, O_RDWR | O_CLOEXEC);
if (fd == -1) return "<failed to open device node>";
auto fdGuard = qScopeGuard([&] { close(fd); });
auto* ver = drmGetVersion(fd);
if (!ver) return "<drmGetVersion failed>";
auto verGuard = qScopeGuard([&] { drmFreeVersion(ver); });
// clang-format off
return QString(ver->name)
% ' ' % QString::number(ver->version_major)
% '.' % QString::number(ver->version_minor)
% '.' % QString::number(ver->version_patchlevel)
% " (" % ver->desc % ')';
// clang-format on
}();
QString product = "unknown";
QString address = "unknown";
auto hex = [](int num, int pad) { return QString::number(num, 16).rightJustified(pad, '0'); };
switch (device->bustype) {
case DRM_BUS_PCI: {
auto* b = device->businfo.pci;
auto* d = device->deviceinfo.pci;
address = "PCI " % hex(b->bus, 2) % ':' % hex(b->dev, 2) % '.' % hex(b->func, 1);
product = hex(d->vendor_id, 4) % ':' % hex(d->device_id, 4);
} break;
case DRM_BUS_USB: {
auto* b = device->businfo.usb;
auto* d = device->deviceinfo.usb;
address = "USB " % QString::number(b->bus) % ':' % QString::number(b->dev);
product = hex(d->vendor, 4) % ':' % hex(d->product, 4);
} break;
default: break;
}
stream << "GPU " << deviceNode << "\n Driver: " << driver << "\n Model: " << product
<< "\n Address: " << address << '\n';
}
return info;
}
QString systemInfo() { QString systemInfo() {
QString info; QString info;
auto stream = QTextStream(&info); auto stream = QTextStream(&info);
stream << gpuInfo() << '\n';
stream << "/etc/os-release:"; stream << "/etc/os-release:";
auto osReleaseFile = QFile("/etc/os-release"); auto osReleaseFile = QFile("/etc/os-release");
if (osReleaseFile.open(QFile::ReadOnly)) { if (osReleaseFile.open(QFile::ReadOnly)) {

View file

@ -6,6 +6,7 @@ namespace qs::debuginfo {
QString qsVersion(); QString qsVersion();
QString qtVersion(); QString qtVersion();
QString gpuInfo();
QString systemInfo(); QString systemInfo();
QString combinedInfo(); QString combinedInfo();