From 2dc2a44115911ef88e088c964cac0abf4cfd2fd2 Mon Sep 17 00:00:00 2001 From: angelrenefm <17342133+angelrenefm@users.noreply.github.com> Date: Thu, 22 Oct 2026 17:35:05 +0200 Subject: [PATCH 1/2] fix: the performance overlay shows the GPU load on Adreno phones whose kgsl busy percentage is unreadable GpuStatsComponent read kgsl's gpubusy once per feed, so the msm reader path (perf_now), read second, got the empty read and showed 0 %. Feeds that share a reader now share one read, and one empty read between gpubusy windows keeps the last load. --- .../launcher/session/GpuStatsComponent.kt | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt b/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt index fb6efe09f..08cc2beeb 100644 --- a/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt +++ b/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt @@ -37,7 +37,7 @@ class GpuStatsComponent(val dir: File) : SessionPart() { feeds.add(Feed(File(dir, "cur_freq"), clock.source, { clock.read()?.times(1_000_000) }, "%-10d\n")) } pick("temp", tempSources(), "%6d\n") { milliCelsius(it) }?.let { feeds.add(it) } - feeds.forEach { feed -> feed.read()?.let { write(feed, it) } } + refresh() Log.i(TAG, "hud: kgsl stats from the session's own: " + MANGOHUD_FILES.joinToString { name -> "$name " + (feeds.firstOrNull { it.file.name == name }?.source ?: "none") }) @@ -55,11 +55,17 @@ class GpuStatsComponent(val dir: File) : SessionPart() { while (running) { try { Thread.sleep(PERIOD_MS) } catch (e: InterruptedException) { break } if (!running) break - for (feed in feeds) feed.read()?.let { write(feed, it) } + refresh() } }, "gpu-stats").apply { isDaemon = true; start() } } + // kgsl's gpubusy can read 0 0 straight after a read, so feeds that share a reader share one read. + private fun refresh() { + val values = HashMap<() -> Long?, Long?>() + for (feed in feeds) values.getOrPut(feed.read) { feed.read() }?.let { write(feed, it) } + } + override fun stop() { running = false thread?.interrupt() @@ -69,11 +75,18 @@ class GpuStatsComponent(val dir: File) : SessionPart() { private fun loadFeed(): Feed? { pick("gpu_busy_percentage", LOAD_SOURCES, "%3d %%\n") { it.coerceIn(0, 100) }?.let { return it } val gpubusy = "$KGSL/gpubusy" + // gpubusy reads 0 0 between its windows, so one empty read keeps the last load; two in a row mean an idle GPU. + var last = 0L + var held = false val read = { runCatching { val parts = File(gpubusy).readText().trim().split(Regex("\\s+")) val total = parts[1].toLong() - if (total > 0) (parts[0].toLong() * 100 / total).coerceIn(0, 100) else 0L + when { + total > 0 -> (parts[0].toLong() * 100 / total).coerceIn(0, 100).also { last = it; held = false } + !held -> last.also { held = true } + else -> 0L + } }.getOrNull() } return if (read() != null) Feed(File(dir, "gpu_busy_percentage"), gpubusy, read, "%3d %%\n") else null From 6c22248d77f27bdc975d63349c3b24da656963fc Mon Sep 17 00:00:00 2001 From: angelrenefm <17342133+angelrenefm@users.noreply.github.com> Date: Thu, 22 Oct 2026 17:44:34 +0200 Subject: [PATCH 2/2] fix: feeds that share a reader also share a failed read --- .../java/com/droiddeck/launcher/session/GpuStatsComponent.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt b/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt index 08cc2beeb..4cd2b067f 100644 --- a/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt +++ b/app/src/main/java/com/droiddeck/launcher/session/GpuStatsComponent.kt @@ -63,7 +63,10 @@ class GpuStatsComponent(val dir: File) : SessionPart() { // kgsl's gpubusy can read 0 0 straight after a read, so feeds that share a reader share one read. private fun refresh() { val values = HashMap<() -> Long?, Long?>() - for (feed in feeds) values.getOrPut(feed.read) { feed.read() }?.let { write(feed, it) } + for (feed in feeds) { + if (feed.read !in values) values[feed.read] = feed.read() + values[feed.read]?.let { write(feed, it) } + } } override fun stop() {