Reports whether (startNs, endNs) is a monotonicity violation (endNs < startNs) — the only case the module's own doc calls out as reachable:
GPU timestamps "are not guaranteed monotonic across a device reset".
This is the guard's true origin point: nsToMs alone cannot both return a
single honest millisecond number for every downstream summation (see
frameTotalMs/passDurationsMs in frame-timing.ts, which add its
output directly into a running total and never pass through
computeDurationStats) AND separately expose "this one was bad" — a
plain number return has no second channel for that. Callers that want
to surface an invalid-sample count (rather than let a clamped-to-0 value
pass as an unremarkable real zero) call this predicate on the same raw
pair alongside nsToMs. computeDurationStats is deliberately NOT where
this lives: by the time a caller has an array of plain millisecond
numbers, it has no way to tell a clamped GPU-reset zero apart from a
genuine fast pass or a CPU-fallback delta (which is never negative — it
comes from performance.now(), spec-guaranteed non-decreasing) — see
that function's doc.
Reports whether
(startNs, endNs)is a monotonicity violation (endNs < startNs) — the only case the module's own doc calls out as reachable: GPU timestamps "are not guaranteed monotonic across a device reset".This is the guard's true origin point:
nsToMsalone cannot both return a single honest millisecond number for every downstream summation (seeframeTotalMs/passDurationsMsinframe-timing.ts, which add its output directly into a running total and never pass throughcomputeDurationStats) AND separately expose "this one was bad" — a plainnumberreturn has no second channel for that. Callers that want to surface an invalid-sample count (rather than let a clamped-to-0 value pass as an unremarkable real zero) call this predicate on the same raw pair alongsidensToMs.computeDurationStatsis deliberately NOT where this lives: by the time a caller has an array of plain millisecond numbers, it has no way to tell a clamped GPU-reset zero apart from a genuine fast pass or a CPU-fallback delta (which is never negative — it comes fromperformance.now(), spec-guaranteed non-decreasing) — see that function's doc.