perf(compositor): slice 5 — paste cache for non-opaque layers (take-7/8 data)
The stamped build settled what slices 3-4 could not: chat cache works (resolve ~0.0ms) but render stayed 26-27ms -> 124-135/300. The cost was the compositor re-rasterizing EVERY layer every tick: this Live scene re-samples chat (159k) + web widget (271k) + image (95k) + cam (156k) ~ 680k px @ ~38ns — for layers whose pixels do not change between chat/web/cam updates. OBS shape: cache the surface, paste per tick. BlitCachedLayer rasterizes a non-opaque layer ONCE into an element-space, transparent-based frame keyed by (source-array identity, src W/H, ceil'd dst rect, round, mirror), then pastes: integer position, row alpha-blend, opacity applied at paste. Producers hand out fresh immutable arrays -> array-identity keys cannot serve stale content; dict bounded (48, clears whole). Drag/opacity live in paste params, not keys, so editing stops triggering resamples too. Opaque backdrop keeps the memcpy path; the webcam keeps the direct path via its IsOpaque flag (revisit if take 9 is borderline). ONE integration test: PasteCache_RepeatRender_IsByteIdentical_And_ContentChange- Propagates (byte-exact raster-vs-paste incl. round-clip margins, new-array propagation); existing pixel suite guards sampler semantics. 85/85 across compositor/pump/chat/capture/session classes, clean build 0 warnings. Also: BuildStampTests.cs was written last commit but never staged — its own scope-check slip, added here (the run had used the on-disk file; tracked now). Docs same commit: ai.md slice 5 + stale 'general path only 130k' claim corrected, TASKS.md take-9 gate, MyMistakes recipe (prove the stage; a fix that doesn't move the stat wasn't the bottleneck), HANDOFF. take 9 expectation: 300/300, render <= ~8ms -> saga closes, Unit B starts.
This commit is contained in:
+12
-11
@@ -44,17 +44,18 @@ RealApp boot-smoke. Scope-check passed.
|
||||
raster on message/config change, blit the cached frame every tick (OBS text-source pattern).
|
||||
Tests: `ChatOverlayLayerCacheTests` (the ONE, RealApp) + full regression green (62 across
|
||||
touched classes), clean build 0 warnings.
|
||||
2. **BUILD STAMP shipped (slice 4, same day):** take 6 came back 35-41ms — WORSE than take 5 —
|
||||
and attribution was impossible (exe timestamp ≠ binary contents; incremental builds served
|
||||
unverified exes). Every build now stamps a fresh GUID (`ytLive.csproj GenerateBuildStamp` →
|
||||
`Helpers/BuildStamp`), shown as the wordmark superscript (build id) + `Build xxxxxxxx (compiled
|
||||
...)` in startup.log; stats report `avg render Xms (resolve Y)` so the hot half of the tick is
|
||||
named. Tests `BuildStampTests` + `BuildStampDisplayTests` (real window, namescoped FindName).
|
||||
3. **Take 7 (user, ~30s record-only):** FIRST read the superscript + startup.log Build line — the
|
||||
take is meaningless without it. Expect slice 3 in any post-stamp build: `avg render ≤ ~10ms
|
||||
(resolve ≪ render), ≈300/300`. If resolve dominates → resolver-side surprise (chat config thrash
|
||||
/ web frame); if blit dominates → measure the general-path element sizes. If chat-burst sags
|
||||
`n/300`: debounced off-tick re-render slice. If clean → recording saga CLOSED, Unit B.
|
||||
2. **Takes 7/8 + slice 5 (2026-09-04):** the stamp (f190587b) settled attribution — chat cache REAL
|
||||
(`resolve ≈ 0`) but render stayed 26-27ms: the compositor re-rasterized every non-opaque layer
|
||||
per tick (his Live scene: chat+web+image+cam ≈ 680k samples @ ~38ns). Slice 5: `BlitCachedLayer`
|
||||
— one raster per (source-array, rect, round/mirror), paste at integer pos with opacity; static
|
||||
layers now cost row-blends, only content changes resample; drag/opacity changes are paste params,
|
||||
not cache keys. Tests: `PasteCache_...` + 85/85 across compositor/pump/chat/capture/session
|
||||
classes; clean build 0 warnings. (Cam bypasses the cache via IsOpaque; revisit if take 9 is
|
||||
borderline. Follow-ups unchanged: vertical-tier alloc, debounced chat re-render on bursts.)
|
||||
3. **Take 9 (user, ~30s record-only):** confirm the wordmark superscript matches the startup.log
|
||||
Build line, then stats must show `≈300/300, avg render ≤ ~8ms` and playback 1x. If yes →
|
||||
**recording saga CLOSED**, Unit B starts. If render ~10-15 → cam-resample cache (drop the
|
||||
IsOpaque bypass); if n/300 sags only during chat bursts → debounced off-tick raster slice.
|
||||
4. **Unit B — the top bar + session logic (user spec 2026-09-04 re-sent twice + decisions settled in Q&A):**
|
||||
- Two-line top bar. Line 1: center = REC + **LIVE** pills (text renamed from ON-AIR; pills become
|
||||
mutually-exclusive RADIOS — record-OR-stream ruling), right = avatar + **Login/Logout** button
|
||||
|
||||
Reference in New Issue
Block a user