fix: bound the density grid, and make [notrace] a reading instead of a flood
The plotter caps a density grid at kDensityCellCap now (deps/plotter), so a 2 s window with persistence on no longer scales the image with the window: the probe's four one-signal rows read 1 044 714 cells / 4 178 856 bytes where they read 2 226 150 / 8 904 600, and a moved frame uploads 1 044 714 bytes where it uploaded 2 226 150. The probe's own legs are unchanged (on peak=1.0000, step-acquisitions peak=1.5000, step-time ratio=0.367879). The paint probe no longer counts a frame the density is drawing as *traceless*. `Renderer::draw_traces()` returns while the ink is the image, so every frame of a persistence display stages no trace: the dump read `traceless paints: 653 (637 after the first bind)` for a run whose real figure is 4 (0), and the `[notrace]` line printed for each of those frames. It is now behind UDPSCOPE_PROBE_NOTRACE -- a per-paint line is a log flood and not a reading -- while the counters it details stay in every build, and the line stays reachable for the state it was written for (a bound row that draws nothing). Docs corrected where they stated the old rule: the README, the trigger invariants, the density probe's readings, the verification list (the new variable) and the manual page behind the panel's tooltip.
This commit is contained in:
1 parent
da826f2cb5
commit
ac054a30c9
11 files changed
+131
-76
No files matched your search
+39
-19
@@ -40,26 +40,46 @@ int on_render_probe(GtkGLArea*, GdkGLContext*, gpointer user) {
|
||||
if (s.graded_traces > 0) ++app->dbg_graded_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;
|
||||
app->dbg_notrace_last = app->dbg_paint_n;
|
||||
if (app->dbg_ever_bound) {
|
||||
++app->dbg_notrace_after_bound;
|
||||
// What the frame was asked to draw, beside what there was to draw it from: an axis
|
||||
// that left the data and a trace that had nothing bound are the same picture and
|
||||
// different bugs, so both are named here rather than inferred from the count.
|
||||
if (app->dbg_notrace_after_bound <= 40) {
|
||||
const RowSet::Row& r = app->rows->row(0);
|
||||
const plot::Range ax = r.plot != nullptr ? r.plot->x_range(r.axis_x) : plot::Range{};
|
||||
std::fprintf(stderr, "[notrace] paint %d mode=%s axis=[%.6f..%.6f] segments=%u",
|
||||
app->dbg_paint_n, display_mode_name(app->dbg_display), ax.min, ax.max,
|
||||
s.staged_segments);
|
||||
for (int sl = 0; sl < RowSet::kSlotsPerRow; ++sl) {
|
||||
if (r.channel[static_cast<std::size_t>(sl)] < 0) continue;
|
||||
const plot::Range b = r.slots[static_cast<std::size_t>(sl)].x_bounds();
|
||||
std::fprintf(stderr, " slot%d n=%zu x=[%.6f..%.6f]", sl,
|
||||
r.slots[static_cast<std::size_t>(sl)].size(), b.min, b.max);
|
||||
// **A frame the density is drawing is not a traceless one.** `Renderer::draw_traces()`
|
||||
// returns while a plot's phosphor density is on -- the trace ink *is* the image -- so every
|
||||
// frame of a persistence display stages no trace and would be counted here, which inflates
|
||||
// the dump's reading and (with `UDPSCOPE_PROBE_NOTRACE` set below) prints a line per frame.
|
||||
// That is the display working, not "what the frame was asked to draw" with nothing to draw
|
||||
// it from. Read off the plots, because the frame's own stats can only say no trace was
|
||||
// drawn and not why.
|
||||
bool density_on = false;
|
||||
for (int i = 0; i < app->rows->row_count() && !density_on; ++i) {
|
||||
const plot::Plot* p = app->rows->row(i).plot;
|
||||
density_on = p != nullptr && p->density().enabled;
|
||||
}
|
||||
if (!density_on) {
|
||||
++app->dbg_notrace_frames;
|
||||
app->dbg_notrace_last = app->dbg_paint_n;
|
||||
if (app->dbg_ever_bound) {
|
||||
++app->dbg_notrace_after_bound;
|
||||
// What the frame was asked to draw, beside what there was to draw it from: an axis
|
||||
// that left the data and a trace that had nothing bound are the same picture and
|
||||
// different bugs, so both are named here rather than inferred from the count.
|
||||
//
|
||||
// **A per-paint line, so it is behind a variable** (`UDPSCOPE_PROBE_NOTRACE`), unlike
|
||||
// the counters beside it: a state that draws nothing lasts as long as it lasts -- a
|
||||
// `Waiting` tail, a bound row with no data -- and the line would be one per frame the
|
||||
// whole time. The count in the dump is the reading; this is the detail behind it.
|
||||
static const bool notrace_print = g_getenv("UDPSCOPE_PROBE_NOTRACE") != nullptr;
|
||||
if (notrace_print && app->dbg_notrace_after_bound <= 40) {
|
||||
const RowSet::Row& r = app->rows->row(0);
|
||||
const plot::Range ax = r.plot != nullptr ? r.plot->x_range(r.axis_x) : plot::Range{};
|
||||
std::fprintf(stderr, "[notrace] paint %d mode=%s axis=[%.6f..%.6f] segments=%u",
|
||||
app->dbg_paint_n, display_mode_name(app->dbg_display), ax.min, ax.max,
|
||||
s.staged_segments);
|
||||
for (int sl = 0; sl < RowSet::kSlotsPerRow; ++sl) {
|
||||
if (r.channel[static_cast<std::size_t>(sl)] < 0) continue;
|
||||
const plot::Range b = r.slots[static_cast<std::size_t>(sl)].x_bounds();
|
||||
std::fprintf(stderr, " slot%d n=%zu x=[%.6f..%.6f]", sl,
|
||||
r.slots[static_cast<std::size_t>(sl)].size(), b.min, b.max);
|
||||
}
|
||||
std::fprintf(stderr, "\n");
|
||||
}
|
||||
std::fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user