Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
6c94c58
feat(text): canonical scene typography controls timeline insertion; r…
AIEraDev Aug 28, 2026
5c5a563
test(text): add canonical scene typography regression coverage
AIEraDev Aug 28, 2026
0347906
fix(render): textRasterizer reads font/size from canonical scene, not…
AIEraDev Aug 28, 2026
2f92d51
feat(render): add source/program geometry diagnostics to textRenderTrace
AIEraDev Aug 28, 2026
dce1d77
fix(evaluation): prevent disabled layers from being reactivated by fa…
AIEraDev Aug 28, 2026
62ce6b9
feat(preview): nativeTextPreview uses authored effect canvas from can…
AIEraDev Aug 28, 2026
027ccec
fix(preview): TextSourcePreview and Program Preview share same author…
AIEraDev Aug 28, 2026
747d927
fix(preview): SourcePreview passes canonical scene geometry to progra…
AIEraDev Aug 28, 2026
d91bfa1
refactor(editor): remove redundant font/stroke/shadow fields from Tex…
AIEraDev Aug 28, 2026
3e3b6af
fix(timeline): useAddToTimeline reads geometry exclusively from canon…
AIEraDev Aug 28, 2026
bef4401
refactor(text-effects): clean up EffectGrid, remove stale plate/strok…
AIEraDev Aug 28, 2026
e8da218
perf(preview): apply quality tiers to native output resolution
AIEraDev Aug 28, 2026
e6ad98f
perf(preview): remove duplicate look-ahead rendering, cache gradient …
AIEraDev Aug 28, 2026
df42866
perf(render): reduce smart-overlay rasterization to active output dim…
AIEraDev Aug 28, 2026
2c0dc0b
test(preview): add quality regression tests for preview tiers and sta…
AIEraDev Aug 28, 2026
be9ae2c
docs(preview): update program-preview-performance-runbook with perman…
AIEraDev Aug 28, 2026
654745e
chore(deps): pin @clypra-studio/engine to 1.4.0; exempt from minimumR…
AIEraDev Aug 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions docs/program-preview-performance-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Timeline input
-> SeekController (requestId + generation + mode)
-> PlaybackClock / NativeProgramPreview render loop
|
| playback / lookahead
| playback / bounded prefetch
v
queue_native_frame
-> decoder + decoder mutex
Expand All @@ -53,7 +53,7 @@ Timeline input
-> native compositor
-> native surface acquire
-> queue submit / surface present
-> retained native surface
-> retained native surface

|
| paused seek / scrub / frame step
Expand Down Expand Up @@ -221,6 +221,56 @@ Permanent rule:
- A missed diagnostic sample is preferable to delaying frame presentation.
- Never stream one JSON log line per frame during a benchmark.

### 11. The playback loop must not render the same timeline twice

The mixed timeline in the incident exposed a compounded frontend cost: the
quality manager selected a tier but the native request still used the full
sequence dimensions; every playback tick awaited WebView rasterization for
text, images, masks, and smart overlays; and the loop could then build a second
look-ahead scene before presenting anything. When one frame fell behind, the
second scene increased the backlog instead of helping it. This also explains
why pause/play felt blocked: the control was responsive, but the render loop
continued expensive work before the next visible state settled.

The permanent playback contract is:

- `PreviewQualityManager` is the single policy for native output dimensions.
Playback uses the selected Full/High/Med/Proxy tier; interaction uses the
lower interaction tier; export keeps its own export profile. Output width,
height, and quality are part of the native request identity.
- Playback is a latest-frame stream. After each awaited WebView raster stage,
compare project, epoch, transport state, and frame index. If the clock moved,
abandon the obsolete work and schedule the current frame.
- The visible playback loop builds one scene and one request per tick. It does
not render a second look-ahead scene. Native queue/prefetch is the only
bounded decode warm-up mechanism.
- Static raster inputs use content/configuration-based asset identities and
may be reused across frames. Time-dependent inputs, such as shaders, remain
frame-addressed until they have a native procedural implementation.
- The retained native surface is the playback target. RGBA readback and canvas
painting are for paused seek/scrub fallback only.

The 2026-08-28 fix applied these rules in `NativeProgramPreview` and
`NativeRasterBridge`. It does not claim a hardware frame-rate result by itself;
the benchmark below must be run on representative mixed timelines to establish
the baseline.

### 12. Regression acceptance criteria for future integrations

Before merging a new clip type, renderer, effect, or preview integration:

- [ ] A 60-second mixed timeline remains responsive while playing, scrubbing,
and pausing; controls must not await preview completion.
- [ ] A slow frame cannot present after a newer frame, seek generation, or
project epoch becomes current.
- [ ] Playback requests report the selected output dimensions and quality;
they do not silently fall back to sequence-sized full output.
- [ ] The integration has an explicit static/time-dependent cache policy and a
bounded byte/entry budget.
- [ ] The benchmark table below includes warm/cold state, output dimensions,
quality, native-surface readiness, and stale/dropped counts.
- [ ] The focused scheduler/quality tests and the native Rust checks pass.

## Required investigation procedure

Before changing React scheduling, UI rendering, or native policy:
Expand Down
Loading
Loading