From 562770595f1f254e5430ea9fc6b2cab8c3bccfc3 Mon Sep 17 00:00:00 2001 From: zach Date: Fri, 3 Jul 2026 12:28:54 +0200 Subject: [PATCH] fix: add generic gpu vram support --- Config/DashboardConfig.qml | 1 + Helpers/NetworkUsage.qml | 8 +- Modules/Resources/Cards/MemoryCard.qml | 1 + Modules/Resources/Cards/NetworkCard.qml | 3 - Modules/Resources/Cards/VramCard.qml | 89 +++++++++++++++++++ Modules/Resources/Content.qml | 25 +++++- .../Settings/Pages/Panels/ResourcesPanel.qml | 8 ++ Plugins/ZShell/Services/gpu.cpp | 41 +++++++++ Plugins/ZShell/Services/gpu.hpp | 1 + 9 files changed, 163 insertions(+), 14 deletions(-) create mode 100644 Modules/Resources/Cards/VramCard.qml diff --git a/Config/DashboardConfig.qml b/Config/DashboardConfig.qml index 6f2e38e..7bd7fe4 100644 --- a/Config/DashboardConfig.qml +++ b/Config/DashboardConfig.qml @@ -17,6 +17,7 @@ JsonObject { property bool showMemory: true property bool showNetwork: true property bool showStorage: true + property bool showVram: true } component Sizes: JsonObject { readonly property int dateTimeWidth: 110 diff --git a/Helpers/NetworkUsage.qml b/Helpers/NetworkUsage.qml index f206d2c..49be574 100644 --- a/Helpers/NetworkUsage.qml +++ b/Helpers/NetworkUsage.qml @@ -9,31 +9,25 @@ import qs.Config Singleton { id: root - // Private properties property real _downloadSpeed: 0 property real _downloadTotal: 0 - // Initial readings for calculating totals property real _initialRxBytes: 0 property real _initialTxBytes: 0 property bool _initialized: false - // Previous readings for calculating speed property real _prevRxBytes: 0 property real _prevTimestamp: 0 property real _prevTxBytes: 0 property real _uploadSpeed: 0 property real _uploadTotal: 0 - // History buffers for sparkline readonly property CircularBuffer downloadBuffer: _downloadBuffer - // Current speeds in bytes per second readonly property real downloadSpeed: _downloadSpeed - // Total bytes transferred since tracking started readonly property real downloadTotal: _downloadTotal - readonly property int historyLength: 30 + readonly property int historyLength: Config.dashboard.performance.showVram ? 70 : 30 property int refCount: 0 readonly property CircularBuffer uploadBuffer: _uploadBuffer readonly property real uploadSpeed: _uploadSpeed diff --git a/Modules/Resources/Cards/MemoryCard.qml b/Modules/Resources/Cards/MemoryCard.qml index 1f8c2fd..3130d51 100644 --- a/Modules/Resources/Cards/MemoryCard.qml +++ b/Modules/Resources/Cards/MemoryCard.qml @@ -9,6 +9,7 @@ CustomRect { readonly property color accent: DynamicColors.palette.m3tertiary + Layout.fillWidth: true color: DynamicColors.tPalette.m3surfaceContainer implicitHeight: layout.implicitHeight + Appearance.padding.large * 2 implicitWidth: layout.implicitWidth + Appearance.padding.extraLargeIncreased * 2 diff --git a/Modules/Resources/Cards/NetworkCard.qml b/Modules/Resources/Cards/NetworkCard.qml index b3bbebc..7ddb26b 100644 --- a/Modules/Resources/Cards/NetworkCard.qml +++ b/Modules/Resources/Cards/NetworkCard.qml @@ -1,7 +1,6 @@ import QtQuick import QtQuick.Layouts import ZShell.Internal -import qs.Modules.Resources import qs.Helpers import qs.Components import qs.Config @@ -9,8 +8,6 @@ import qs.Config CustomRect { id: root - required property Wrapper wrapper - color: DynamicColors.tPalette.m3surfaceContainer implicitHeight: 220 implicitWidth: 300 diff --git a/Modules/Resources/Cards/VramCard.qml b/Modules/Resources/Cards/VramCard.qml new file mode 100644 index 0000000..4cee29e --- /dev/null +++ b/Modules/Resources/Cards/VramCard.qml @@ -0,0 +1,89 @@ +import QtQuick +import QtQuick.Layouts +import ZShell.Services +import qs.Components +import qs.Config + +CustomRect { + id: root + + readonly property color accent: DynamicColors.palette.m3tertiary + + Layout.fillWidth: true + color: DynamicColors.tPalette.m3surfaceContainer + implicitHeight: layout.implicitHeight + Appearance.padding.large * 2 + implicitWidth: layout.implicitWidth + Appearance.padding.extraLargeIncreased + radius: Appearance.rounding.medium + + ServiceRef { + service: Gpu + } + + ColumnLayout { + id: layout + + anchors.centerIn: parent + spacing: Appearance.spacing.extraSmall + + RowLayout { + Layout.leftMargin: -Appearance.padding.extraSmall + spacing: Appearance.spacing.small + + MaterialIcon { + color: root.accent + fill: 1 + text: "memory_alt" + } + + CustomText { + text: qsTr("Video memory") + } + } + + CircularProgress { + id: circularIndicator + + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: Appearance.spacing.large + fgColor: root.accent + implicitSize: usageColumn.implicitHeight + thickness + Appearance.padding.largeIncreased * 2 + startAngle: -225 + sweepAngle: 270 + value: Gpu.memoryUsed / Gpu.memoryTotal + + Behavior on clampedVal { + Anim { + } + } + + ColumnLayout { + id: usageColumn + + anchors.centerIn: parent + anchors.verticalCenterOffset: Appearance.padding.extraSmall + spacing: 0 + + CustomText { + Layout.alignment: Qt.AlignHCenter + color: root.accent + font.pointSize: Appearance.font.size.large + text: Math.round(circularIndicator.value * 100) + "%" + } + + CustomText { + Layout.alignment: Qt.AlignHCenter + color: DynamicColors.palette.m3onSurfaceVariant + text: qsTr("Used") + } + } + } + + CustomText { + Layout.alignment: Qt.AlignHCenter + text: { + const fmt = UsageFmt.formatKib(Gpu.memoryUsed, Gpu.memoryTotal); + return `${fmt.value.toFixed(1)} / ${Math.floor(fmt.total)} ${fmt.unit}`; + } + } + } +} diff --git a/Modules/Resources/Content.qml b/Modules/Resources/Content.qml index 55bcff1..359f1c4 100644 --- a/Modules/Resources/Content.qml +++ b/Modules/Resources/Content.qml @@ -74,7 +74,7 @@ Item { RowLayout { spacing: Appearance.spacing.normal - visible: storageCard.active || networkCard.active || memoryCard.active + visible: storageCard.active || memoryCard.active || vramCard.active || networkCard1.active WrappedLoader { id: storageCard @@ -95,15 +95,32 @@ Item { } WrappedLoader { - id: networkCard + id: vramCard - active: Config.dashboard.performance.showNetwork + active: Config.dashboard.performance.showVram + + sourceComponent: VramCard { + } + } + + WrappedLoader { + id: networkCard1 + + active: Config.dashboard.performance.showNetwork && !vramCard.active sourceComponent: NetworkCard { - wrapper: root.wrapper } } } + + WrappedLoader { + id: networkCard2 + + active: Config.dashboard.performance.showNetwork && vramCard.active + + sourceComponent: NetworkCard { + } + } } WrappedLoader { diff --git a/Modules/Settings/Pages/Panels/ResourcesPanel.qml b/Modules/Settings/Pages/Panels/ResourcesPanel.qml index 11e9f5b..9e41e3a 100644 --- a/Modules/Settings/Pages/Panels/ResourcesPanel.qml +++ b/Modules/Settings/Pages/Panels/ResourcesPanel.qml @@ -56,6 +56,14 @@ PageBase { onToggled: Config.dashboard.performance.showGpu = checked } + ToggleRow { + checked: Config.dashboard.performance.showVram + settingAnchor: "resources-vram" + text: qsTr("Video memory") + + onToggled: Config.dashboard.performance.showVram = checked + } + ToggleRow { checked: Config.dashboard.performance.showCpu settingAnchor: "resources-cpu" diff --git a/Plugins/ZShell/Services/gpu.cpp b/Plugins/ZShell/Services/gpu.cpp index f1bcf94..a742e8c 100644 --- a/Plugins/ZShell/Services/gpu.cpp +++ b/Plugins/ZShell/Services/gpu.cpp @@ -3,8 +3,10 @@ #include "sensorslib.hpp" #include +#include #include #include +#include #include #include #include @@ -243,6 +245,45 @@ void Gpu::detectNameOnce() { {QStringLiteral("-c"), QString::fromLatin1(kNameDetectScript)}); } +void Gpu::readGenericMemory() { + const QStringList paths = QDir(QStringLiteral("/sys/class/drm")) + .entryList( + QStringList() << QStringLiteral("card*"), + QDir::Dirs | QDir::NoDotAndDotDot); + + qreal totalMem = 0.0; + qreal usedMem = 0.0; + for (const QString& card : paths) { + QFile total( + QStringLiteral("/sys/class/drm/%1/device/mem_info_vram_total") + .arg(card)); + if (!total.open(QIODevice::ReadOnly | QIODevice::Text)) { + continue; + } + bool ok = false; + const qreal v = total.readAll().trimmed().toDouble(&ok); + total.close(); + if (ok) { + totalMem += v; + } + + QFile used(QStringLiteral("/sys/class/drm/%1/device/mem_info_vram_used") + .arg(card)); + if (!used.open(QIODevice::ReadOnly | QIODevice::Text)) { + continue; + } + bool ok1 = false; + const qreal v1 = used.readAll().trimmed().toDouble(&ok1); + used.close(); + if (ok1) { + usedMem += v1; + } + } + + setMemoryTotal(totalMem); + setMemoryUsed(usedMem); +} + void Gpu::readGenericUsage() { const QStringList paths = QDir(QStringLiteral("/sys/class/drm")) .entryList( diff --git a/Plugins/ZShell/Services/gpu.hpp b/Plugins/ZShell/Services/gpu.hpp index 4b91122..dbe567c 100644 --- a/Plugins/ZShell/Services/gpu.hpp +++ b/Plugins/ZShell/Services/gpu.hpp @@ -62,6 +62,7 @@ class Gpu : public TickingService { void readGenericUsage(); void startNvidiaUsage(); void readGpuTemperature(); + void readGenericMemory(); void setUserType(Type value); void setAutoType(Type value);