-
-
- {device.name ??
- t("settings.resources.gpu.unknownDevice")}
-
-
- {ordinal === undefined
- ? backendLabel
- : `${t("settings.resources.gpu.deviceWithIndex", {
- index: ordinal,
- })}, ${backendLabel}`}
-
-
-
+ {hasGpu ? (
+ metrics.devices.map((device, index) => {
+ const ordinal = deviceOrdinal(device);
+ // Preserve null (unknown, e.g. Windows ROCm perf counter); coercing
+ // to 0 would render a fabricated 0 used / full free.
+ const total = device.memory_total_gb ?? null;
+ const used = device.vram_used_gb ?? null;
+ const free =
+ device.vram_free_gb ??
+ (isFiniteNumber(total) && isFiniteNumber(used)
+ ? Math.max(0, total - used)
+ : null);
+ const percent =
+ device.vram_utilization_pct ??
+ (isFiniteNumber(total) && total > 0 && isFiniteNumber(used)
+ ? (used / total) * 100
+ : null);
+ const safePercent = clampPercent(percent);
+ const usedText = isFiniteNumber(used)
+ ? formatGiB(used)
+ : unknownLabel;
+ const freeText = isFiniteNumber(free)
+ ? formatGiB(free)
+ : unknownLabel;
+ const totalText = isFiniteNumber(total)
+ ? formatGiB(total)
+ : unknownLabel;
+ const percentText = isFiniteNumber(percent)
+ ? formatPercent(safePercent)
+ : unknownLabel;
+ return (
+ // Name over backend on the left, figures and meter beside them.
+ // The meter is deliberately short: at full width it read as a
+ // rule across the pane rather than a reading for one device.
+
+
+
+ {device.name ?? t("settings.resources.gpu.unknownDevice")}
+
+
+
+ {ordinal === undefined
+ ? backendLabel
+ : `${t("settings.resources.gpu.deviceWithIndex", {
+ index: ordinal,
+ })}, ${backendLabel}`}
+
+
{percentText}{" "}
{t("settings.resources.gpu.vramUtilization")}
-
-
- {/* Wraps rather than overflows once the pane gets narrow. */}
-
-
-
- {t("settings.resources.gpu.used", { value: usedText })}
-
-
- {t("settings.resources.gpu.free", { value: freeText })}
-
-
- {t("settings.resources.gpu.total", {
- value: totalText,
- })}
-
-
-
+
- );
- })
- ) : (
-
- {t("settings.resources.gpu.noGpu")}
-
- )}
-
+
+
+
+ {t("settings.resources.gpu.used", { value: usedText })}
+
+
+ {t("settings.resources.gpu.free", { value: freeText })}
+
+
+ {t("settings.resources.gpu.total", {
+ value: totalText,
+ })}
+
+
+
+
+