From 620f017d9a649e1840e7a16e272751080b63a090 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sun, 9 Aug 2026 21:23:57 +0200 Subject: [PATCH] fix(validation): tell the CAPTURE it is a PyroWave session, or NVIDIA hands it a CUDA buffer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `--codec pyrowave` selects the ENCODER. The capture pipeline picks its consumer from `ZeroCopyPolicy::pyrowave_session`, which on the spike path is fed only by the global `PUNKTFUNK_ENCODER=pyrowave` lab lever (punktfunk-host/src/capture.rs). Without it, .21 resolved capture pipeline resolved: cuda-import -> nvenc capture_arm="cuda-import" consumer="nvenc" zero-copy: dmabuf imported to CUDA (no CPU copy) nv12=true and the wavelet encoder refused the payload on its first submit: "unsupported FramePayload (need Dmabuf or Cpu RGB)". That is not a worker bug — the arm that failed was the pure in-process one. It reproduces only where the A/B actually lives. An AMD box has no CUDA arm to pick, so .25 resolved straight to dmabuf-passthrough and the kit looked correct there. With the lever set, .21 resolves `dmabuf-passthrough -> pyrowave` and both arms encode 2700/2700 frames. V3b then passes on .21 (RTX 5070 Ti, GRID 2 at ~100% GPU, 5120x1440 — the portal captures the real monitor, --width/--height being synthetic-only): in-process, refused p50 2.85 ms p99 8.39 ms (10 windows) capped worker, granted p50 2.65 ms p99 4.10 ms (11 windows) p99 delta -4.29 ms The worker reports `priority=Granted(Realtime)` with `ext=VK_KHR_global_priority` on the FIRST attempt and logs no fallback line; the refused arm logs "every global queue priority class was refused". So the capability still buys the lever from a SEPARATE process, with the IPC hop in the loop — 8.39 -> 4.10 ms is a 51% p99 cut, against PW1's in-host 6.4 -> 4.4 at 1080p. Different resolution and a harder load, so treat the class as confirmed and the absolute numbers as not comparable to PW1's. --- scripts/validate-encode-worker.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/validate-encode-worker.sh b/scripts/validate-encode-worker.sh index 115c9b3a..e28068ba 100755 --- a/scripts/validate-encode-worker.sh +++ b/scripts/validate-encode-worker.sh @@ -527,7 +527,15 @@ run_spike() { # NO_COLOR: keep the captured log plain at the source. `log_cat` strips SGR escapes anyway, but a # plain log is also the one a human greps by hand when a leg goes red, and `p99_us\e[0m\e[2m=…` # defeats the obvious grep just as thoroughly as it defeated this kit's parser. - local -a envs=(PUNKTFUNK_PERF=1 NO_COLOR=1) + # + # PUNKTFUNK_ENCODER=pyrowave is NOT redundant with `--codec pyrowave`, and leaving it out cost a + # real V3b run on .21. `--codec` selects the ENCODER; the capture pipeline picks its consumer from + # `ZeroCopyPolicy::pyrowave_session`, which on the spike path is fed only by this env (see + # punktfunk-host/src/capture.rs — "the global PUNKTFUNK_ENCODER=pyrowave lab lever"). Without it an + # NVIDIA host resolves `cuda-import -> nvenc`, imports the dmabuf to CUDA as NV12, and hands the + # wavelet encoder a payload it rejects: "unsupported FramePayload (need Dmabuf or Cpu RGB)". AMD + # boxes hide this — they have no CUDA arm to pick — so it reproduces only where the A/B lives. + local -a envs=(PUNKTFUNK_PERF=1 NO_COLOR=1 PUNKTFUNK_ENCODER=pyrowave) for kv in "$@"; do envs+=("$kv"); done local -a cmd=("$HOST_BIN" spike --codec pyrowave --source "$SPIKE_SOURCE" --width "$OPT_WIDTH" --height "$OPT_HEIGHT" --fps "$OPT_FPS"