fix: a dense trace is drawn one pixel column at a time, so it cannot moiré
At a high rate, a high frequency or on noise the plots banded visibly and the bands crawled under a pan. Three things compound to produce it, none a bug alone: a pyramid bucket spans one to two pixel columns, Envelope emits two points per bucket so each contributes a near-vertical hairline and a near-vertical connector, and every one lands at a fractional x because a trace is deliberately not snapped -- so a column's brightness beats against the pixel grid, and a pan sweeps the beat. The cure is upstream (deps/plotter, pin moved): draw_traces reduces such a window onto the pixel grid, one snapped vertical segment per column from that column's lowest to its highest value. One sub-pixel phase for the whole trace, so there is nothing left to beat, and the geometry is bounded by axes.w rather than by the buckets. frame path: gains a columns= field, which is what separates "the segment count collapsed because the reduction ran" from "the window got narrower". On the fast mock at 3 kHz over 20 s: columns=1200, segments 2041/2237 over 1201 painted frames, against columns=0, segments 10960/216093 over 263 before -- the same run at 4.6x the frame rate, with trace ink: clean either way. Also corrects the documented mock invocation: --batch 20000 exceeds the datagram limit and the mock dies with Errno 90. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
62df049f53
commit
5f5b87ca60
5 files changed
+94
-8
No files matched your search
+9
-2
@@ -411,6 +411,12 @@ struct App {
|
||||
std::uint64_t dbg_visible_max = 0;
|
||||
int dbg_raw_frames = 0;
|
||||
int dbg_lod_frames = 0;
|
||||
/// Frames on which at least one trace's geometry was reduced onto the pixel grid (one
|
||||
/// vertical segment per column). It is orthogonal to `raw`/`lod` on purpose -- the
|
||||
/// reduction is gated on the *density* of the gathered points, not on which level
|
||||
/// produced them -- and it is the only reading that distinguishes "the segment count
|
||||
/// collapsed because the reduction ran" from "the window got narrower".
|
||||
int dbg_column_frames = 0;
|
||||
/// Painted frames on which `draw_traces` drew **no trace at all**, and the last one's index.
|
||||
/// This is the observable for "the plot flickers as if there were no data": `staged_segments`
|
||||
/// cannot see it, because the grid and the instruments stage geometry of their own, so a frame
|
||||
@@ -1247,6 +1253,7 @@ int on_render_probe(GtkGLArea*, GdkGLContext*, gpointer user) {
|
||||
app->dbg_seg_last = s.staged_segments;
|
||||
if (s.raw_traces > 0) ++app->dbg_raw_frames;
|
||||
if (s.lod_traces > 0) ++app->dbg_lod_frames;
|
||||
if (s.column_traces > 0) ++app->dbg_column_frames;
|
||||
if (s.raw_traces > 0 || s.lod_traces > 0) check_frame_ink(*app);
|
||||
if (s.raw_traces == 0 && s.lod_traces == 0) {
|
||||
++app->dbg_notrace_frames;
|
||||
@@ -8212,9 +8219,9 @@ int run_ui(int argc, char** argv, const Config& cfg, ScopeModel& model, Acquisit
|
||||
app.dbg_draw_ms_max, app.dbg_draw_max_frame,
|
||||
app.dbg_paint_n > 0 ? app.dbg_paint_ms_sum / app.dbg_paint_n : 0.0,
|
||||
app.dbg_paint_ms_max, app.dbg_paint_n);
|
||||
std::printf("[udpscope] frame path: raw=%d lod=%d frames, segments %llu/%u "
|
||||
std::printf("[udpscope] frame path: raw=%d lod=%d columns=%d frames, segments %llu/%u "
|
||||
"(mean/max), visible max %llu samples\n",
|
||||
app.dbg_raw_frames, app.dbg_lod_frames,
|
||||
app.dbg_raw_frames, app.dbg_lod_frames, app.dbg_column_frames,
|
||||
static_cast<unsigned long long>(app.dbg_paint_n > 0
|
||||
? app.dbg_seg_sum / app.dbg_paint_n
|
||||
: 0),
|
||||
|
||||
Reference in new issue
Block a user