Merge branch 'main' into worktree-agent-a139f16b3a4130998

This commit is contained in:
Brandon Thomas committed 2026-10-04 00:15:57 -04:00
commit 299fe09efe
32 files changed
+3565 -174

No files matched your search

+24 -10
View File
@@ -199,21 +199,35 @@ runs render on the GPU end to end (`gpu::adv3d`, `Renderer::prepare_adv_run` /
then compute kernels (`adv3d.wgsl`) resolve the 2×2 supersampling, average the sub-samples
(nearest depth), apply the depth-based iris depth of field with the Classic 3D bokeh spans
(`three_d::bokeh::kernel_spans`, highlight boost, progressive blur levels) and composite over the
GPU canvas; only the depth of field reads back its 8-byte radius range. Advanced 3D layers with
blend modes, track mattes or Preserve Transparency and environment backgrounds take the CPU's
2D compositing path (their scenes still render through `render_3d`). Wireframe outlines draw on
the GPU from the CPU's pixel list (`Renderer::wireframe_pixels`). GPU
effects (`effects::GPU_EFFECTS`, 166 of them: blurs, colour correction, keying incl. Key Light,
mattes, channel, stylize, distortion and warps (Warp, Bezier Warp, Smear, Reshape, CC Bend It, CC
Page Turn), Cartoon, bevels, shapes, transitions, generators, noise, grain and time; see
GPU canvas; only the depth of field reads back its 8-byte radius range. Runs whose layers need
the 2D compositing path (blend modes, track mattes, Preserve Transparency) come to the GPU as a
`three_d::adv::SplitRun` (`Renderer::split_adv_run`, `draw_run`'s steps as data): the plain
layers render as one scene over the canvas, then each special layer, farthest first, renders on
its own, is hidden where the main scene is nearer (`occlude`), and goes through the 2D matte /
Preserve Transparency / blend kernels (a 3D track matte renders solo through the camera).
Environment Light Background layers draw their sky in a kernel (`adv_sky`, from
`Renderer::sky_draw`) before the rest of the run, in Classic and Advanced 3D comps. Wireframe
outlines draw on the GPU from the CPU's pixel list (`Renderer::wireframe_pixels`). GPU effects
(`effects::GPU_EFFECTS`, 196 of them: blurs, colour correction, keying incl. Key Light, mattes,
channel, stylize, distortion and warps (Warp, Bezier Warp, Smear, Reshape, CC Bend It, CC Page
Turn, CC Bender, CC Blobbylize), Cartoon, bevels, shapes, the transitions (CC light family, CC
transitions, Block Dissolve), perspective (Radial Shadow, CC Cylinder / Sphere / Spotlight /
Environment, 3D Glasses), generators, noise, grain, text (Numbers, Timecode) and time; see
[effects.md](effects.md)) repeat the CPU effect's steps (padding, box radii, parameters, hashes)
as kernels, in one module per family (`gpu::fx_*` with `shaders/fx_*.wgsl`); consecutive GPU
effects run as one chain with one upload and one readback. Statistics that need the whole frame
(Auto Levels / Contrast / Color, Equalize, Shadow/Highlight, Color Stabilizer, Remove Grain's
noise level) are measured on the CPU from one readback and applied on the GPU; effects reading
other frames (Echo, Posterize Time) upload the frames the host renders. Settings a kernel cannot
match render on the CPU (`effects::catalog::gpu_supported`; e.g. Warp's Fisheye and Twist past
50 % or with a distortion, whose Newton inverse wanders chaotically near the crease). Tests render
other frames (Echo, Posterize Time, Time Difference, Time Displacement, CC Force Motion Blur, CC
Wide Time, Pixel Motion Blur, Timewarp) upload the frames the host renders (`time_frames`) and
combine them on the GPU; Time Displacement's per-pixel times and Timewarp's motion vectors
(`time_fx::timewarp_plan`) are computed on the CPU. Numbers and Timecode rasterise their glyph
coverage on the CPU (`textfx::text_layer`) and composite it on the GPU. Other layers an effect
reads (gradients, reveals, environments) are fitted on the CPU (`util::fit_layer`) and uploaded.
Settings a kernel cannot match render on the CPU (`effects::catalog::gpu_supported`; e.g. Warp's
Fisheye and Twist past 50 % or with a distortion, whose Newton inverse wanders chaotically near
the crease, and Timewarp with a Matte Layer); Card Wipe (the 3D card renderer of Card Dance and
Shatter) stays on the CPU. Tests render
scenes on both paths and compare them (≤ 1/255 at 8 bpc, ≤ 1e-3 at 32 bpc); they skip without an
adapter. Working textures (premultiplied RGBA f32) come from a pool: a released texture is reused
once every encoder that could still read it has been submitted, transparent inputs share one
+31 -31
View File
@@ -5,7 +5,7 @@
EffectCraft ships 306 effects with 3009 parameters in total, grouped into the same categories as the Effects & Presets panel. Every effect is our own implementation, written from public behaviour descriptions and standard image-processing literature. Parameter names, order, popup options, units, defaults and ranges follow the reference application so that projects, expressions and muscle memory carry over.
- **GPU**: 166 effects also run on the GPU compositor with identical results.
- **GPU**: 196 effects also run on the GPU compositor with identical results.
- **32**: 306 effects process 32-bit float (HDR, overbright) pixels without clamping.
- **Status**: 306 implemented in full, 0 partial (what is missing is listed).
@@ -133,8 +133,8 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
| Bezier Warp | `ec.distort.bezierwarp` | 13 | GPU | 32 | Implemented |
| Bulge | `ec.distort.bulge` | 6 | GPU | 32 | Implemented |
| CC Bend It | `ec.distort.ccbendit` | 4 | GPU | 32 | Implemented |
| CC Bender | `ec.distort.ccbender` | 5 | | 32 | Implemented |
| CC Blobbylize | `ec.distort.ccblobbylize` | 15 | | 32 | Implemented |
| CC Bender | `ec.distort.ccbender` | 5 | GPU | 32 | Implemented |
| CC Blobbylize | `ec.distort.ccblobbylize` | 15 | GPU | 32 | Implemented |
| CC Flo Motion | `ec.distort.ccflomotion` | 7 | GPU | 32 | Implemented |
| CC Griddler | `ec.distort.ccgriddler` | 5 | GPU | 32 | Implemented |
| CC Lens | `ec.distort.cclens` | 3 | GPU | 32 | Implemented |
@@ -194,9 +194,9 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
| Audio Waveform | `ec.generate.audiowaveform` | 17 | | 32 | Implemented |
| Beam | `ec.generate.beam` | 11 | | 32 | Implemented |
| CC Glue Gun | `ec.generate.ccgluegun` | 7 | | 32 | Implemented |
| CC Light Burst 2.5 | `ec.generate.cclightburst` | 6 | | 32 | Implemented |
| CC Light Rays | `ec.generate.cclightrays` | 8 | | 32 | Implemented |
| CC Light Sweep | `ec.generate.cclightsweep` | 9 | | 32 | Implemented |
| CC Light Burst 2.5 | `ec.generate.cclightburst` | 6 | GPU | 32 | Implemented |
| CC Light Rays | `ec.generate.cclightrays` | 8 | GPU | 32 | Implemented |
| CC Light Sweep | `ec.generate.cclightsweep` | 9 | GPU | 32 | Implemented |
| CC Threads | `ec.generate.ccthreads` | 8 | | 32 | Implemented |
| Cell Pattern | `ec.generate.cellpattern` | 14 | GPU | 32 | Implemented |
| Checkerboard | `ec.generate.checkerboard` | 10 | GPU | 32 | Implemented |
@@ -303,15 +303,15 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
| Effect | Id | Params | GPU | 32 | Status |
|---|---|---:|:-:|:-:|---|
| 3D Camera Tracker | `ec.perspective.cameratracker` | 12 | | 32 | Implemented |
| 3D Glasses | `ec.perspective.3dglasses` | 8 | | 32 | Implemented |
| 3D Glasses | `ec.perspective.3dglasses` | 8 | GPU | 32 | Implemented |
| Bevel Alpha | `ec.perspective.bevelalpha` | 4 | GPU | 32 | Implemented |
| Bevel Edges | `ec.perspective.beveledges` | 4 | GPU | 32 | Implemented |
| CC Cylinder | `ec.perspective.cccylinder` | 12 | | 32 | Implemented |
| CC Environment | `ec.perspective.ccenvironment` | 4 | | 32 | Implemented |
| CC Sphere | `ec.perspective.ccsphere` | 14 | | 32 | Implemented |
| CC Spotlight | `ec.perspective.ccspotlight` | 8 | | 32 | Implemented |
| CC Cylinder | `ec.perspective.cccylinder` | 12 | GPU | 32 | Implemented |
| CC Environment | `ec.perspective.ccenvironment` | 4 | GPU | 32 | Implemented |
| CC Sphere | `ec.perspective.ccsphere` | 14 | GPU | 32 | Implemented |
| CC Spotlight | `ec.perspective.ccspotlight` | 8 | GPU | 32 | Implemented |
| Drop Shadow | `ec.perspective.dropshadow` | 6 | GPU | 32 | Implemented |
| Radial Shadow | `ec.perspective.radialshadow` | 9 | | 32 | Implemented |
| Radial Shadow | `ec.perspective.radialshadow` | 9 | GPU | 32 | Implemented |
## Simulation
@@ -370,37 +370,37 @@ Effects are addressed by id (`ec.<category>.<name>`) or display name in commands
| Effect | Id | Params | GPU | 32 | Status |
|---|---|---:|:-:|:-:|---|
| Numbers | `ec.text.numbers` | 14 | | 32 | Implemented |
| Timecode | `ec.text.timecode` | 12 | | 32 | Implemented |
| Numbers | `ec.text.numbers` | 14 | GPU | 32 | Implemented |
| Timecode | `ec.text.timecode` | 12 | GPU | 32 | Implemented |
## Time
| Effect | Id | Params | GPU | 32 | Status |
|---|---|---:|:-:|:-:|---|
| CC Force Motion Blur | `ec.time.ccforcemotionblur` | 4 | | 32 | Implemented |
| CC Wide Time | `ec.time.ccwidetime` | 3 | | 32 | Implemented |
| CC Force Motion Blur | `ec.time.ccforcemotionblur` | 4 | GPU | 32 | Implemented |
| CC Wide Time | `ec.time.ccwidetime` | 3 | GPU | 32 | Implemented |
| Echo | `ec.time.echo` | 5 | GPU | 32 | Implemented |
| Pixel Motion Blur | `ec.time.pixelmotionblur` | 4 | | 32 | Implemented |
| Pixel Motion Blur | `ec.time.pixelmotionblur` | 4 | GPU | 32 | Implemented |
| Posterize Time | `ec.time.posterizetime` | 1 | GPU | 32 | Implemented |
| Time Difference | `ec.time.timedifference` | 5 | | 32 | Implemented |
| Time Displacement | `ec.time.timedisplacement` | 4 | | 32 | Implemented |
| Timewarp | `ec.time.timewarp` | 28 | | 32 | Implemented |
| Time Difference | `ec.time.timedifference` | 5 | GPU | 32 | Implemented |
| Time Displacement | `ec.time.timedisplacement` | 4 | GPU | 32 | Implemented |
| Timewarp | `ec.time.timewarp` | 28 | GPU | 32 | Implemented |
## Transition
| Effect | Id | Params | GPU | 32 | Status |
|---|---|---:|:-:|:-:|---|
| Block Dissolve | `ec.transition.blockdissolve` | 5 | | 32 | Implemented |
| CC Glass Wipe | `ec.transition.ccglasswipe` | 5 | | 32 | Implemented |
| CC Grid Wipe | `ec.transition.ccgridwipe` | 7 | | 32 | Implemented |
| CC Image Wipe | `ec.transition.ccimagewipe` | 7 | | 32 | Implemented |
| CC Jaws | `ec.transition.ccjaws` | 6 | | 32 | Implemented |
| CC Light Wipe | `ec.transition.cclightwipe` | 8 | | 32 | Implemented |
| CC Line Sweep | `ec.transition.cclinesweep` | 5 | | 32 | Implemented |
| CC Radial ScaleWipe | `ec.transition.ccradialscalewipe` | 3 | | 32 | Implemented |
| CC Scale Wipe | `ec.transition.ccscalewipe` | 3 | | 32 | Implemented |
| CC Twister | `ec.transition.cctwister` | 5 | | 32 | Implemented |
| CC WarpoMatic | `ec.transition.ccwarpomatic` | 8 | | 32 | Implemented |
| Block Dissolve | `ec.transition.blockdissolve` | 5 | GPU | 32 | Implemented |
| CC Glass Wipe | `ec.transition.ccglasswipe` | 5 | GPU | 32 | Implemented |
| CC Grid Wipe | `ec.transition.ccgridwipe` | 7 | GPU | 32 | Implemented |
| CC Image Wipe | `ec.transition.ccimagewipe` | 7 | GPU | 32 | Implemented |
| CC Jaws | `ec.transition.ccjaws` | 6 | GPU | 32 | Implemented |
| CC Light Wipe | `ec.transition.cclightwipe` | 8 | GPU | 32 | Implemented |
| CC Line Sweep | `ec.transition.cclinesweep` | 5 | GPU | 32 | Implemented |
| CC Radial ScaleWipe | `ec.transition.ccradialscalewipe` | 3 | GPU | 32 | Implemented |
| CC Scale Wipe | `ec.transition.ccscalewipe` | 3 | GPU | 32 | Implemented |
| CC Twister | `ec.transition.cctwister` | 5 | GPU | 32 | Implemented |
| CC WarpoMatic | `ec.transition.ccwarpomatic` | 8 | GPU | 32 | Implemented |
| Card Wipe | `ec.transition.cardwipe` | 44 | | 32 | Implemented |
| Gradient Wipe | `ec.transition.gradientwipe` | 5 | GPU | 32 | Implemented |
| Iris Wipe | `ec.transition.iriswipe` | 7 | GPU | 32 | Implemented |
+40 -3
View File
@@ -10,7 +10,7 @@ How close EffectCraft is to After Effects 2026, feature by feature, and how much
| Unweighted | ≈ 97% (half-credit) / 99% (fractions) |
| P0 / P1 / P2 | ≈ 99% / 96% / 90% (half-credit); 99.8% / 99.2% / 97.5% (fractions) |
| Features done / partial / missing | 87 / 5 / 0 of 92 |
| **Effects** | **306** effects (all After Effects 2026 effects), every one implemented in full ([effects.md](effects.md)); 166 run on the GPU |
| **Effects** | **306** effects (all After Effects 2026 effects), every one implemented in full ([effects.md](effects.md)); 196 run on the GPU |
| Disabled menu entries left | 1, on purpose: Import ▸ Vanishing Point (.vpe), whose format has no public specification |
| Remaining work | ≈ 9–11 agent-hours at the pace measured so far (≈ 29 on the conservative audit scale); ≈ 6–7 without the learned-model items |
| **Wall-clock estimate** | **≈ 2–2.5 hours** with five agents in parallel; ≈ 1.5 hours for 100% of P0 + P1 |
@@ -156,11 +156,11 @@ the disk cache in the formats wave; the 3D Camera Tracker in M12.6.)
| Text | ≈ 96% | 0.3 | no extruded strokes (M13.12: the Variable Font Axes animator re-spaces the text — advances follow the animated axes; M13.6: variable font axes in the character style — `layer.setText variations`, the Character panel's Variable Font Axes fields — shape with HVAR / gvar advances and draw at that design-space position; OpenType features — stylistic sets, discretionary ligatures, contextual / stylistic alternates, swash, titling, ordinals, fractions, figure styles, true small caps / all small caps and superior / inferior glyphs with faux fallback — per character with the Character panel's OpenType popup and `text.fontFeatures` landed in M13.2; vertical Roman / Tate-Chu-Yoko, forced LTR paragraphs, caret on animated and path text, Variable Font Axes and Lottie style runs landed in M13.5; extruded, bevelled text in M7.6; per-character styles, paragraph settings, on-canvas editing and the `sourceText` style API in M9.9–M9.10) |
| Web | 97% | 0.2 | GPU effects in Render Queue / analysis workers (job workers render on their CPU), layer buffers in the browser's disk cache (frames only), no shared-memory threads inside one engine instance (the decided design is one engine instance per worker; a threaded build needs nightly `build-std`) (browser storage, Web Audio, Web Worker renders/analyses, WebGPU viewer and offline install landed in M15.2; viewer frames in frame workers fed by project diffs, Roto Brush propagation in a worker, non-blocking `wait: true` jobs and a browser Media Browser (File System Access folders, browser storage) in M13.10; WEB-1 in M13.24: GPU effects and the GPU compositor in the frame workers on their own WebGPU devices with deferred readbacks (frames render in passes; Backend Auto per comp), the disk cache in the Origin Private File System (written by the workers with sync access handles, LRU under the settings' limit, served after a reload), the storage manager (Settings ▸ Disk ▸ Browser Storage, `storage.info` / `storage.persist` / `storage.clear`), and a WGSL constant Chrome rejected (it disabled every GPU kernel in Chrome) fixed) |
| 3D | 88% | 5.5 | multi-view layouts, the Extended Viewer for Advanced 3D comps (Classic 3D Extended Viewer landed in M13.5 UI completion); collapsed precomps of another size seen through the parent's camera render (fixed in M13.2); stereo rigs, orbit nulls, lights controlled by the camera, cameras/lights from glTF models, environment backgrounds, Advanced 3D motion blur, blend modes and track mattes landed in M7.7; Classic 3D iris-shaped bokeh with highlights, progressive depth of field on tilted layers and the focus-link commands landed in M13.5; Advanced 3D depth of field with the iris and highlight options, collapsed precomps as real Advanced 3D geometry and extruded text/shape strokes landed in M13.8; Advanced 3D (glTF/OBJ models, primitives, extruded text and shapes, PBR, image-based light, shadow maps, GPU rasteriser) in M7.4–M7.6; Advanced 3D end to end on the GPU (motion blur, iris depth of field, compositing) in M13.11 |
| Effects | ≈ 85% | 3.0 | GPU versions of the remaining effects (166 run on the GPU since M13.13, EFF-5: Warp, Bezier Warp, Reshape, Smear, CC Bend It, CC Page Turn, Cartoon, Color Emboss, Circle, Ellipse, Iris Wipe, Bevel Alpha / Edges and Gaussian Blur (Legacy) joined the 152 of M13.9; simulations, 3D channel, VR, audio-driven, OCIO, text and the CC light / transition families still render on the CPU) and the missing controls listed as partial in [effects.md](effects.md) (every After Effects effect exists since M9.11, M12.5 and M12.6; parameter names, order, twirl-downs, popups, units and defaults were aligned in M9.12) |
| Effects | ≈ 85% | 3.0 | GPU versions of the remaining effects (196 run on the GPU since M13.22, EFF-5: the CC light family, the CC transitions, Block Dissolve, Radial Shadow, CC Bender / Blobbylize / Cylinder / Sphere / Spotlight / Environment, 3D Glasses, Numbers, Timecode and the time effects joined the 166 of M13.13; simulations, 3D channel, VR, audio-driven, OCIO and Card Wipe still render on the CPU) and the missing controls listed as partial in [effects.md](effects.md) (every After Effects effect exists since M9.11, M12.5 and M12.6; parameter names, order, twirl-downs, popups, units and defaults were aligned in M9.12) |
| Interface | 75% | 5.0 | more Learn tutorials and pixel-level fidelity of dialogs (the Home ▸ Templates gallery (eight original built-in templates, user templates from File ▸ Save as Template…) and View ▸ Simulate Output ▸ My Custom RGB… landed in M13.25; Timeline layer reordering by drag, a non-snapping viewer pan, a working rename field and twirl arrows, and the full set of property reveal shortcuts — double presses, Alt+Shift keyframes, Ctrl+` — landed in M13.17–M13.20; the Home ▸ Learn tab with interactive tutorials and a UI fidelity pass landed in M13.5 UI completion; visual editors for Lumetri RGB / hue-saturation curves, Colorama's output cycle wheel, Glow's colour map and Reshape's correspondence points (viewer handles), a scrolling Preview panel and AE-style Composition / Timeline tabs (close, label swatch, viewer lock) landed in M13.10; Timeline outline and Project panel columns scroll horizontally, the Layer Style dialog, ROI resize handles, Pan Behind snapping and 3D Reference Axes landed in M13.5; native macOS menu bar, Timeline columns/search/reveal-add, Home screen with recent projects and all AE workspaces landed; viewer rulers/snapping/channels/snapshots landed in M0.13) |
| Project | ≈ 68% | 5.5 | auto-save, folder moves, OCIO displays beyond the built-in tone map (Color Engine with OCIO/ACES working spaces, HDR compand/tone mapping, Rec. 2100 PQ/HLG output, Feet + Frames, display colour management, Simulate Output and the locked viewer landed in M7.7; proxies and Interpret Footage fields / pixel aspect / alpha guess landed: PRJ-8, PRJ-3) |
| Masks & roto | 74% | 5.0 | Roto Brush's learned (3.0) segmentation model (variable-width mask feather points with the Mask Feather tool landed in M13.5; mask tracking and Mask Interpolation landed in M6.6; Roto Brush & Refine Edge with graph-cut segmentation, flow propagation, edge matting, decontamination and Freeze in M6.7) |
| Preview | 77% | 2.8 | GPU compositing of Advanced 3D layers with blend modes / track mattes and of environment backgrounds (pooled GPU textures and fused quantisation since M13.13: Lower Third GPU warm 21 → 4 ms/frame, and Auto now picks the CPU or the GPU per comp from measured frame times; Advanced 3D runs — raster, motion blur, iris depth of field, compositing — and wireframes run on the GPU since M13.11: CPU warm 3394 → GPU warm 290 ms/frame at 1920×1080 (11.7×; Half 968 → 85 ms), GPU ≠ CPU on 0.005 % of pixels, on an M4 Pro under load; Classic 3D bokeh depth of field — iris shapes, highlights, fringe, progressive blur on tilted planes — runs in WGSL since M13.6: 3D Showcase GPU warm 205 → 54 ms/frame at full size on an M4 Pro; the Preview panel's five shortcuts with their own Include / Loop / Cache Before Playback / Range / Play From / Frame Rate / Skip / Resolution / Full Screen / stop options and `playback.settings.get/set` landed in M13.8; Classic 3D runs and adjustment layers composite on the GPU since M12.7; persistent disk cache with the blue cache bar landed; region of interest, snapshots, exposure and Fast Previews landed in M0.13) |
| Preview | 77% | 2.8 | GPU effects for simulations, 3D channel, VR, OCIO and Card Wipe (Advanced 3D layers with blend modes / track mattes / Preserve Transparency and environment backgrounds composite on the GPU since M13.22; pooled GPU textures and fused quantisation since M13.13: Lower Third GPU warm 21 → 4 ms/frame, and Auto now picks the CPU or the GPU per comp from measured frame times; Advanced 3D runs — raster, motion blur, iris depth of field, compositing — and wireframes run on the GPU since M13.11: CPU warm 3394 → GPU warm 290 ms/frame at 1920×1080 (11.7×; Half 968 → 85 ms), GPU ≠ CPU on 0.005 % of pixels, on an M4 Pro under load; Classic 3D bokeh depth of field — iris shapes, highlights, fringe, progressive blur on tilted planes — runs in WGSL since M13.6: 3D Showcase GPU warm 205 → 54 ms/frame at full size on an M4 Pro; the Preview panel's five shortcuts with their own Include / Loop / Cache Before Playback / Range / Play From / Frame Rate / Skip / Resolution / Full Screen / stop options and `playback.settings.get/set` landed in M13.8; Classic 3D runs and adjustment layers composite on the GPU since M12.7; persistent disk cache with the blue cache bar landed; region of interest, snapshots, exposure and Fast Previews landed in M0.13) |
| Tracking | ≈ 96% | 0.3 | face tracking is a classical (skin model + feature components + shape model) fitter, not a learned detector: profile views and occluded faces are weak; Rolling Shutter Ripple is approximated by Subspace Warp's mesh density (face tracking (Outline Only / Detailed Features with Face Track Points and Extract & Copy Face Measurements), Subspace Warp's content-preserving mesh warp on subspace-smoothed trajectories, and radial lens distortion (k1, k2) in the camera bundle adjustment with Undistort Footage landed in M13.3; Rolling Shutter Repair in M9.11; point tracker, mask tracking, Warp Stabilizer and the 3D Camera Tracker in M6.x / M12.5 / M12.6) |
| Paint | 0% | 4.0 | Brush, Clone Stamp, Eraser |
@@ -224,6 +224,43 @@ axes since M13.6; Advanced 3D's DOF has iris shapes since M13.8).
as real geometry lit by the parent (2D collapsed precomps draw nested 3D layers with the
parent's renderer); text and shape strokes extrude as bevelled meshes in paint order.
## Update: M13.22 GPU effects, part A
- **GPU ports (EFF-5)**: 30 more effects run on the GPU (196 GPU effects), each matching the
CPU oracle within 1/255 (8 bpc) / 1e-3 (32 bpc) on every tested pixel, directly on a buffer
(full and half resolution, as adjustment) and composited at 8 and 32 bpc:
- the CC light family: CC Light Rays, CC Light Burst 2.5, CC Light Sweep, CC Light Wipe
(`gpu::fx_light`);
- transitions and perspective (`gpu::fx_transition`): Block Dissolve (block indices computed
on the CPU per column / row sub-sample, so the hash sees the CPU's integers), CC Glass Wipe,
CC Grid Wipe, CC Image Wipe, CC Jaws, CC Line Sweep, CC Radial ScaleWipe, CC Scale Wipe, CC
Twister, CC WarpoMatic, Radial Shadow, CC Bender, CC Blobbylize, CC Cylinder, CC Sphere, CC
Spotlight, CC Environment, 3D Glasses; other layers they read (gradient, reveal, backside,
environment, stereo views) are fitted on the CPU and uploaded;
- Numbers and Timecode (`gpu::fx_text`): the glyph coverage (fill and stroke ring) is
rasterised on the CPU with the effect's own stroke font and composited on the GPU with the
box, fill and stroke;
- time (`gpu::fx_time`): Time Difference, Time Displacement, CC Force Motion Blur, CC Wide
Time, Pixel Motion Blur and Timewarp fetch their frames through the host as Echo does and
combine them on the GPU (weighted sums one frame per pass, in the CPU's order); Time
Displacement's per-pixel times and Timewarp's motion vectors (block matching and smoothing)
are computed on the CPU, Timewarp's Whole Frames / Frame Mix / Pixel Motion frame building
and shutter average on the GPU.
- **Fallbacks and deviations**: Timewarp with a Matte Layer renders on the CPU
(`gpu_supported`); Card Wipe (the 3D card renderer shared with Card Dance and Shatter) and the
3D Camera Tracker stay on the CPU. CC Environment now fades nearly transparent environment
texels to black continuously (colour / max(alpha, 1e-3), on both paths) instead of a hard
1e-6 un-premultiply cut-off, which turned the filtered map's float noise into colour. CC
Sphere / CC Environment keep their longitude on the side of the ±180° seam the ray's sign
puts it (a GPU's approximate `atan2` can land across it).
- **Advanced 3D compositing on the GPU (3D-3, PRV-3)**: runs with blend modes, track mattes
(2D, or 3D mattes drawn through the camera) or Preserve Transparency no longer read back:
`Renderer::split_adv_run` hands `draw_run`'s split path to the GPU (main scene, then each
special layer far to near, hidden behind the nearer main scene and composited through the 2D
kernels), and Environment Light Background skies draw in a kernel in Classic and Advanced 3D
comps. The GPU walk matches the CPU compositor on the same rasters exactly at 8 and 32 bpc,
with only the frame's own readback.
## Update: M13.13 GPU performance and the remaining GPU ports
- **Small comps on the GPU (PRV-3)**: the GPU frame allocated (and zero-initialised) several