?renderAudit (debug only): prove the render-on-change scheduler skips
only frames that would have drawn the same pixels.
Under the audit the loop renders EVERY tick. On a tick the scheduler would
have skipped it reads the frame back (a 64x64 downsample, drawn from the
canvas in the same task as the render so the drawing buffer is still
valid) and compares it against the readback of the last frame the
scheduler really did render. A difference is a state change nobody
reported — a "missed dirty": the counter render.missedDirty goes up and
the last render requests are logged so the silent source can be found.
The mismatching frame then becomes the reference, so one missed change
counts once, not on every tick after it.
A pixel counts as different when any channel moved by more than
CHANNEL_TOLERANCE (of 255): an identical state renders identical
pixels, and the tolerance only absorbs readback rounding, never a real
change a user could see.
?renderAudit(debug only): prove the render-on-change scheduler skips only frames that would have drawn the same pixels.Under the audit the loop renders EVERY tick. On a tick the scheduler would have skipped it reads the frame back (a 64x64 downsample, drawn from the canvas in the same task as the render so the drawing buffer is still valid) and compares it against the readback of the last frame the scheduler really did render. A difference is a state change nobody reported — a "missed dirty": the counter
render.missedDirtygoes up and the last render requests are logged so the silent source can be found. The mismatching frame then becomes the reference, so one missed change counts once, not on every tick after it.A pixel counts as different when any channel moved by more than CHANNEL_TOLERANCE (of 255): an identical state renders identical pixels, and the tolerance only absorbs readback rounding, never a real change a user could see.