Skip to content

Regression (#3668): waterfall pan choppy on wide displays — unconditional kiwi reproject deep-copies the image each pan step #3700

Description

@svabi79

What happened?

Dragging the waterfall to pan (horizontal frequency scroll) is choppy again on high-resolution / wide displays, with the UI thread stalling ~60–80 ms per pan step. By inspection this traces to #3668 (clean-room KiwiSDR integration), merged 2026-06-20 — the same day. It re-introduces, by a different mechanism, the per-pan-step waterfall cost that #3578 had removed (which itself fixed the same class of choppiness, #3575, on wide displays).

Root cause

#3578 made per-pan reproject cheap: the waterfall history image is no longer globally reprojected — each history row records its own capture frame and only the visible viewport is remapped.

#3668 changed SpectrumWidget::handleWaterfallFrequencyFrameChange() from a single reprojectWaterfall() into an unconditional native + kiwi double reproject, each wrapped in a waterfall-stream-state save/restore:

reprojectStream(false);   // native
reprojectStream(true);    // kiwi — runs every pan step even with no KiwiSDR receiver

On every pan mouse-move, even when KiwiSDR is inactive, this costs two things:

  1. A second, wasted reproject pass for a stream with no on-screen data.
  2. saveCurrentWaterfallStreamState() does state.waterfall = m_waterfall — a QImage assignment, so the buffer is now shared (copy-on-write). The next m_waterfall.fill(Qt::black) inside rebuildWaterfallViewportForFrame() therefore detaches = deep-copies the entire waterfall image (large on wide/high-DPI displays) on every pan step. That deep-copy is exactly the per-step cost perf(spectrum): per-row waterfall-history frequency frames (no per-pan reproject) #3578 had eliminated.

Measured (aether.perf, same telemetry as #3578)

i9-13900K / RTX 4090, FLEX-6600, wide high-resolution panadapter, D3D11/GPU path. Same binary; one env var (AETHER_WF_KIWI_ALWAYS) toggles only the second pass. During a continuous hand pan:

metric with #3668 double pass active-stream only
wfUpdateP95Ms 63–68 ms 0.1 ms
panAgeP95Ms (display lag) 150–174 ms 22–32 ms
inputP95Ms 19–24 ms 0.2–3.6 ms
uiLagMaxMs 75–85 ms 23–41 ms
total PerfStall (comparable pan) 931 15

fftRestarts/wfRestarts = 0 and packet loss = 0 in both runs — the radio/stream is not involved. renderP95 ~7 ms in both — the GPU render is not the bottleneck. The cost is purely the second pass + the deep-copy.

What did you expect?

Pan to stay smooth (as after #3578), regardless of whether a KiwiSDR receiver is connected.

Steps to reproduce

  1. Connect to a FLEX radio; open a panadapter with a waterfall on a wide / high-resolution display.
  2. Grab the waterfall and pan (drag horizontally) continuously for a few seconds.
  3. Panning is choppy/laggy. With aether.perf enabled (Help → Support → "Performance"), wfUpdateP95Ms spikes to ~60–80 ms and panAgeP95Ms to ~150–170 ms during the drag.

A/B from one binary: launch with AETHER_WF_KIWI_ALWAYS=1 → stall reproduces; without it (active-stream-only) → stall gone.

AetherSDR version

26.6.3

Radio model & firmware

FLEX-6600

Operating system

Windows

OS version and hardware

Windows 11 (build 26200), Qt 6.8.3 msvc2022_64; i9-13900K / RTX 4090, wide high-resolution panadapter.


Fix PR incoming (reproject only the active stream; remap the other on stream-switch). Couldn't self-assign — this account has no triage permission here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfacebugSomething isn't workingmaintainer-reviewRequires maintainer review before any action is takenpriority: mediumMedium priorityspectrumPanadapter and waterfall

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions