perf(pump): slice 6 — break the 15.6ms sleep quantum (the REAL ceiling behind takes 7-9)
Take 9's numbers were decisive: paste cache moved work to ~25ms/frame but the period stayed ~37ms. The missing ~12ms per tick is Task.Delay rounding every sub-tick request up to the Windows system-clock tick (~15.6ms default — documented: learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.delay). A frame finishing 3ms early requested 3ms and slept 15.6. Producer capped at ~27fps no matter how fast the compositor got — which is why two real render fixes read as 'zero change' in playback. Game-loop/OBS canon for this (stackoverflow.com/questions/5441464; learn.microsoft.com/en-us/windows/win32/ api/timeapi/nf-timeapi-timebeginperiod): raise the timer resolution for the session, sleep only the bulk of the remainder, and SPIN the last ~2ms across the deadline. - FramePump: timeBeginPeriod(1) on entering the pump loop, timeEndPeriod(1) in the finally; pacing = bulk _pacingDelay(ahead - 2ms) + bounded Thread.SpinWait tail; blown deadlines rebase unchanged (never burst). - Stats now report avg wait: render+submit+wait must equal the period — the accounting is closed, no stage can hide in an unmeasured gap again. - Webcam dropped its IsOpaque paste-cache bypass: it re-sampled ~156k px every tick even between identical device frames; cached paste beats the sampler on hits, costs the same on misses. 52/52 per-class green (pacing + pixel suites unchanged — output byte-stable), clean build 0 warnings. Docs same commit (ai.md slice 6, TASKS.md take-10 gate, MyMistakes #3 + renumber, HANDOFF). User's top-bar spec remains next in queue (Unit B) — re-sent many times, captured, no open questions.
This commit is contained in:
@@ -253,15 +253,12 @@ public sealed class SceneCompositor
|
||||
var ew = (float)element.Width;
|
||||
var eh = (float)element.Height;
|
||||
var isRound = element.ClipShape == ClipShape.Round;
|
||||
if (frame.IsOpaque && element.Opacity >= 1f)
|
||||
{
|
||||
// Opaque full-strength layer (the live backdrop): raster it straight, no alpha path.
|
||||
BlitContent(buffer, cropW, cropH, ex, ey, ew, eh, frame, 1f, isRound, element.IsMirrored);
|
||||
}
|
||||
else
|
||||
{
|
||||
BlitCachedLayer(buffer, cropW, cropH, ex, ey, ew, eh, frame, element, isRound);
|
||||
}
|
||||
// All rect-placed elements route through the paste cache (take-9 lesson): the
|
||||
// IsOpaque bypass kept re-sampling the webcam (~156k px) EVERY tick even when
|
||||
// the device frame had not changed; an opaque source rasterizes to an opaque
|
||||
// raster whose paste is a per-pixel copy branch, so hits beat the sampler and
|
||||
// misses cost exactly what the bypass cost.
|
||||
BlitCachedLayer(buffer, cropW, cropH, ex, ey, ew, eh, frame, element, isRound);
|
||||
if (element.HasBorder)
|
||||
DrawBorder(buffer, cropW, cropH, ex, ey, ew, eh, element, isRound);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user