Files
filmcraft/docs/hardware-parity.md
Eduardo Andrade Machado fc0e73e342 render, gpu: adjustment layers composited on the GPU (#3032)
* render, gpu: adjustment layers composited on the GPU

An adjustment layer anywhere at a time sent the whole frame to the CPU
renderer, so GPU rendering did nothing for the frames under one. A
full-frame adjustment layer at 100 % opacity, Normal, unmasked and with
only effects the GPU stage runs is now a PlanStep::Adjust: its effects
run in the effect stage on the accumulator (the composite of the tracks
below) and the result replaces it before the tracks above are drawn.
Every other adjustment layer keeps the whole-frame CPU fallback.

The export renderer takes Composite plans without transitions; frames
with a Push still go to the CPU there, as before. perf.stats gpu gains
adjustments / cpuAdjustments.

* docs: adjustment layers on the GPU compositor in parity and performance

hardware-parity.md gains an Adjustment layers row; performance.md gains
the main-against-branch export timings with an adjustment layer.

* render, gpu: adjustment layer review fixes

- is_cpu_frame and plan_frame now ask the same adjustment_ops (evaluated
  at the render scale, which is_cpu_frame takes from the RenderOptions):
  a Transform that shrinks the frame no longer takes a pooled export
  renderer only to be rendered on the CPU and counted as a GPU frame.
- FxOp::eval leaves a Transform with its shutter angle on (motion blur)
  to the CPU; the GPU drew it sharp, on clips and adjustment layers.
- The effect stage's texture pool spans the whole composite frame, so an
  adjustment step's working textures are reused instead of made again
  every frame. Composite plans honour resolve = false (export).
- ExportRenderer::render hands frames with an adjustment layer back to
  the CPU when the device has no effect stage, instead of compositing
  them on the CPU and uploading the result to read it back.
- adjustment_covers_output checks the full-frame geometry without
  building the coverage image.
- The GPU adjustment test also runs without an effect stage.

* render, gpu, export, ui: plan adjustment layers for the device's caps

plan_frame and is_cpu_frame take plan::DeviceCaps (how large a frame
the device runs adjustment layers on; none without an effect stage), so
a frame the compositing device can't adjust becomes a CPU image on the
thread that plans it, never on the UI thread or inside a renderer slot.

- Monitor: the caps are part of the frame key
  (Target::SequencePlan(seq, caps)), so a plan made for another device
  is never reused.
- Export: FrameRenderer::caps is required; the renderer pool plans with
  the smallest caps of its renderers before it takes one.
- The compositor's own CPU fallback stays as a safety net for a plan
  made for other caps; the tests check that nothing reaches it.
- Main's own-shutter Transform check replaces the duplicate guard in
  gpufx.

Tests: a Push under an adjustment layer exported on the GPU against
render_sequence (forward and reversed, scales 1 and 0.5); routing
without an effect stage in the export pipeline and in the monitor's
frame server; GPU parity against render_sequence with colour and alpha
for a partly transparent canvas, stacked adjustment layers, an empty
canvas, a nested sequence below and one inside a nest, at scales 1 and
0.5; caps boundaries and is_cpu_frame agreeing with plan_frame.

* gpu: end a refused effect image's frame; count steps once drawn

effect_image began an effect stage frame and returned without ending it
when the stage refused the job, so the stage stayed mid-frame and kept
its working images. The compositor's step counters are added once the
whole frame is drawn on the GPU, so a frame that falls back half way
no longer counts the steps it threw away.
2026-11-06 10:57:26 +01:00

6.4 KiB
Raw Permalink Blame History

Hardware parity

Last reviewed: 2026-10-10 · Last updated: 2026-10-23 · Change: minor (adjustment layers on the GPU compositor) · Target: Adobe Premiere Pro 2026 (26.5.2)

Each hardware feature Premiere uses, per platform, against ours. Implementation detail lives in crates/platform/README.md (decode / encode backends, the one crate allowed unsafe, ADR 0001), the GPU compositor in architecture.md, and timings in performance.md. Hardware paths are always optional: our software codecs are the tested fallback, and a hardware decoder that fails mid-stream hands over to software (HybridDecoder).

Premiere's side is from Adobe's published GPU and hardware-acceleration documentation and release notes (Premiere does not run on Linux).

Hardware decode

Codec / profile Premiere macOS Ours macOS (VideoToolbox) Premiere Windows Ours Windows (Media Foundation / D3D11) Ours Linux (NVDEC, VA-API)
H.264 8-bit 4:2:0 yes yes Intel, NVIDIA, AMD yes (Baseline / Main / High) yes (NVDEC; VA-API Intel / AMD / Mesa)
H.264 10-bit / 4:2:2 Apple silicon yes where the chip decodes it Intel; NVIDIA Blackwell (MXF too) no (declined; no software fallback, G3) no
HEVC Main / Main 10 4:2:0 yes yes yes yes yes (NVDEC 8/10; VA-API Main / Main 10)
HEVC 4:2:2 10-bit Apple silicon yes where supported Intel; NVIDIA Blackwell no no
VP9 profile 0 / 2 — software — yes software (VA-API VP9 not yet)
AV1 main 8 / 10 — software yes yes software
ProRes Apple silicon (M1 Pro / Max and later) software (fast: 318 fps) software software software
Field-coded H.264 yes no yes no no

Measured (cargo xtask bench --hw off|auto): M4 Pro, CPU per 2160p frame H.264 119 → 4.2 ms, HEVC 86 → 3.7 ms, 4K plays with no dropped frames at Full; Intel Iris Xe VA-API H.264 2160p 417 → 11.4 ms, HEVC Main 10 2160p 212 → 18.4 ms. Every decoded picture is read back to the CPU and re-uploaded to wgpu (no zero-copy yet), which Premiere avoids.

Hardware encode

Codec Premiere macOS Ours macOS Premiere Windows Ours Windows Ours Linux
H.264 8-bit yes yes (VideoToolbox, opt-in, no B-frames; takes the RGBA pictures and converts them itself) Intel QSV, NVENC, AMD NVENC only (opt-in) NVENC only
H.264 10-bit / 4:2:2 yes (Apple silicon) no Intel no no
HEVC Main 8-bit yes yes (hardware-only format) QSV, NVENC, AMD NVENC only no
HEVC Main 10 / HDR (PQ, HLG) yes no (tone-mapped to 8-bit SDR) yes NVENC yes (HDR10 SEI, mdcv / clli) no
ProRes Apple silicon software only software software software
AV1 — no via plug-ins / newer GPUs no no

Measured: VideoToolbox H.264 1080p25 encode 200 fps on M1; a 9:29 timeline exported in 311 s against 793 s with our software encoder (SSIM 0.990). NVENC HEVC round trip 48.9 dB luma PSNR (8-bit), 71.1 dB (10-bit) on an RTX 5060.

GPU rendering

Feature Premiere (Mercury Playback Engine: Metal, CUDA, OpenCL) Ours (wgpu: Metal, D3D12, Vulkan) %
Compositing, blend modes, transforms GPU GPU (#32), CPU compositor is the oracle 90%
Accelerated video effects ~82 of ~92 effects marked Accelerated (reference list plan/premiere/10-effects-list.md) 35 effect ids (render::gpufx::GPU_EFFECTS): colour, levels, blurs (Bokeh Blur included), sharpen, crop, transform, flips, vignette, video limiter, ASC CDL, channel mix, Lumetri basic / creative / vignette ~40%
Lumetri curves, wheels, HSL secondary GPU CPU 0%
Keys (Ultra Key), masks, distortions, transitions GPU CPU (masks have WGSL parity tests, not in the live path) 10%
Adjustment layers GPU when every effect on them is accelerated GPU for a full-frame one at 100 % opacity, Normal, unmasked, with only GPU effects (PlanStep::Adjust): 4.0–5.0× faster GPU exports under one; any other one renders the whole frame on the CPU 60%
Export rendering on the GPU yes yes (#421; Export ▸ GPU Rendering, Auto): 2.4× (1080p) to 3.2× (4K) faster on effects-heavy timelines 80%
Thumbnails on the GPU (26.0) yes CPU 0%
Software adapter fallback warns silently renders everything on the CPU (#632) —
Intel integrated graphics supported start-up crash on Intel UHD (#512) —

Devices and I/O

Hardware Premiere Ours %
Audio interfaces CoreAudio, ASIO, WASAPI; multichannel mapping cpal (CoreAudio, WASAPI, ALSA); no ASIO; device reports #605, #602 60%
Voice-over microphone yes yes (punch-in); macOS privacy declaration missing (#659) 80%
External video monitoring (Mercury Transmit, Blackmagic DeckLink, AJA) yes no 0%
Second computer monitor full-screen playback yes full screen inside the app window; no separate-display output or floating windows on other screens (#466) 40%
HDR / EDR display macOS EDR, Windows HDR no (SDR display of HDR sequences) 0%
Control surfaces (EUCON, Mackie HUI / MCU) yes no 0%
LTC timecode input yes no 0%
Tape / deck control legacy no n/a

Summary

Hardware dimension: ~45%, 120–200 h. Ahead of Premiere: hardware decode on Linux (VA-API, NVDEC) and FreeBSD builds. Behind, by user impact: zero-copy upload; GPU effects beyond 35 (Lumetri curves / wheels / HSL, keys, masks, transitions); Quick Sync and AMD encoders on Windows; VideoToolbox Main 10 HDR encode; 10-bit / 4:2:2 decode off macOS; HDR display; external video I/O and control surfaces (need hardware we don't own). Calibration: one decode backend ~3–5 h, one encoder ~4–8 h (target-app-parity.md).

Revision history

Date Change Summary
2026-10-23 minor Adjustment layers row: full-frame, opaque, Normal ones with GPU effects run on the GPU compositor
2026-10-10 major Created from ROADMAP.md's performance-and-hardware row and crates/platform/README.md; added Linux NVDEC (#549), GPU export and Lumetri on the GPU (#421), Premiere's per-platform hardware list, devices and I/O