From 33729a703b708c97133d5c3832243752f2597f75 Mon Sep 17 00:00:00 2001 From: Toby Date: Tue, 28 Jul 2026 19:45:36 -0700 Subject: [PATCH] fix(apu-memory-tuner): detect GPU when rocminfo lists Name before Device Type _gfx_target_from_rocminfo() only captured the agent's `Name:` and `Marketing Name:` after it had already seen a `Device Type: GPU` line. But rocminfo prints those two lines *before* `Device Type:` within each agent block, so the capture guard was never satisfied and the function returned ("", ""). The knock-on effect: detect_platform.py then classified the machine as "No AMD APU detected" and exited 2 on hardware that is squarely in scope -- reproduced on a Ryzen AI MAX+ 395 (Strix Halo, gfx1151), the exact RDNA3.5 target this skill is written for. Fix: buffer the current agent block's candidate gfx target + marketing name and commit them the moment a `Device Type: GPU` line confirms the block is a GPU; reset the buffer on each `Agent N` header. The startswith("gfx") guard still skips the ISA sub-block Names ("amdgcn-amd-amdhsa--gfx1151"). Before: GFX target: unknown / APU: False / Supported: NO (exit 2) After: GFX target: gfx1151 / APU: True / Supported: YES (exit 0) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../scripts/detect_platform.py | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/staging/apu-memory-tuner/scripts/detect_platform.py b/staging/apu-memory-tuner/scripts/detect_platform.py index 11de61a..4c4675a 100644 --- a/staging/apu-memory-tuner/scripts/detect_platform.py +++ b/staging/apu-memory-tuner/scripts/detect_platform.py @@ -182,28 +182,39 @@ def _cpu_info_windows() -> tuple[str, str]: def _gfx_target_from_rocminfo() -> tuple[str, str]: - """Return (gfx_target, gpu_name) from rocminfo if available.""" + """Return (gfx_target, gpu_name) from rocminfo if available. + + rocminfo prints one block per agent, and WITHIN a block the ``Name:`` and + ``Marketing Name:`` lines appear *before* the ``Device Type:`` line. So we + can't wait until we've seen ``Device Type: GPU`` to start capturing -- by + then those lines are already behind us. Instead we buffer the current + block's candidate gfx target + marketing name and commit them the moment we + confirm the block is a GPU. A new ``Agent N`` header resets the buffer. + """ if shutil.which("rocminfo") is None: return "", "" rc, out, _ = _run(["rocminfo"], timeout=10) if rc != 0: return "", "" - gfx = "" - name = "" - in_gpu_agent = False + cand_gfx = "" + cand_name = "" for line in out.splitlines(): s = line.strip() - if s.startswith("Device Type:"): - in_gpu_agent = "GPU" in s - if in_gpu_agent and s.startswith("Marketing Name:") and not name: - name = s.split(":", 1)[1].strip() - if in_gpu_agent and s.startswith("Name:") and s.endswith("gfx") is False: + if s.startswith("Agent ") and s[len("Agent "):].strip().isdigit(): + cand_gfx = "" + cand_name = "" + elif s.startswith("Name:"): val = s.split(":", 1)[1].strip() - if val.startswith("gfx") and not gfx: - gfx = val - if gfx and name: - break - return gfx, name + # The agent's own Name is the bare gfx target (e.g. "gfx1151"). + # ISA sub-blocks report "amdgcn-amd-amdhsa--gfx1151" -- skip those + # via the startswith("gfx") guard. + if val.startswith("gfx") and not cand_gfx: + cand_gfx = val + elif s.startswith("Marketing Name:") and not cand_name: + cand_name = s.split(":", 1)[1].strip() + elif s.startswith("Device Type:") and "GPU" in s and cand_gfx: + return cand_gfx, cand_name + return "", "" def _gfx_target_from_sysfs() -> tuple[str, str]: