Commit Graph

4 Commits

Author SHA1 Message Date
Skyler Lehmkuhl 2bce5e93a6 gpu-video-encoder: VAAPI driver retry, Vello-capable device, Send
Three fixes found while running the zero-copy export on real Intel hardware:

- vaapi::create_device() retries LIBVA_DRIVER_NAME in order iHD -> auto ->
  i965 -> radeonsi. libva was auto-selecting the legacy i965 driver, which
  fails on newer Intel GPUs; the modern iHD (intel-media-driver) is needed.
  encoder.rs now builds its hwdevice through this helper.
- vk_device: request the adapter's full limits instead of downlevel_defaults.
  Vello's compute pipelines need max_storage_buffers_per_shader_stage >= 5
  (downlevel caps at 4), which panicked Vello's shader init on the export
  device. This device only ever runs on a real VAAPI GPU.
- ZeroCopyEncoder: unsafe impl Send. It owns its FFmpeg/Vulkan handles
  exclusively and is only moved (onto the export thread), never shared.
2026-06-25 18:15:05 -04:00
Skyler Lehmkuhl a00e73c4b3 gpu-video-encoder: mux the zero-copy encode into a container file
ZeroCopyEncoder::new now takes an output path and writes a real container
(format inferred from the extension, e.g. .mp4): create an output format
context, add the h264 stream from the encoder, write header; encode_rgba
rescales each packet's ts and av_interleaved_write_frame's it; finish
flushes + writes the trailer + closes. Sets AV_CODEC_FLAG_GLOBAL_HEADER for
mp4/mov so SPS/PPS land in extradata. This lets the editor's existing
mux_video_and_audio consume the temp video file unchanged.

The zerocopy_encode test now writes a .mp4 and ffprobe-verifies the codec,
dimensions, and frame count. Also let wgpu own the imported plane-image
destruction via texture_from_raw drop callbacks (clears two warnings).
2026-06-25 15:43:39 -04:00
Skyler Lehmkuhl ba897eaea2 gpu-video-encoder: complete zero-copy H.264 encode pipeline
Build the full end-to-end zero-copy encoder, validated on Intel/VAAPI:

- render_nv12: fragment-shader RGBA->NV12 that renders luma/chroma into
  the imported R8/RG8 plane render targets (compute storage can't write
  the DMA-BUF-backed planes; render attachments can).
- dmabuf: import_raw imports an NV12 DMA-BUF by explicit layout; the two
  plane images + shared memory are now destroyed by wgpu via texture_from_raw
  drop callbacks (Arc MemoryGuard frees the memory once both images are
  gone, in wgpu's wait-idle'd deferred pass) -- fixes the teardown segfault.
- encoder::ZeroCopyEncoder: renders an RGBA texture straight into a pooled
  VAAPI surface (imports cached by VASurface id) and encodes with h264_vaapi.
  encode_rgba + finish; the caller renders on device().

Tests: real-frame render into the surface matches the CPU NV12 reference,
and a 30-frame encode produces valid H.264 (ffprobe-verified) with clean
teardown. Not yet wired into the editor.
2026-06-23 19:28:57 -04:00
Skyler Lehmkuhl 5917ce7921 Add gpu-video-encoder crate: zero-copy VAAPI encode (validated)
New workspace crate isolating the unsafe GPU<->encoder interop for
zero-copy hardware video encoding. Every link is validated by a test on
real Intel/Mesa/iHD hardware:

- nv12: GPU RGBA->NV12 compute (BT.709 full-range), byte-exact vs a CPU
  reference.
- vaapi: VAAPI hwcontext + h264_vaapi encode (CPU-fed NV12 -> valid H.264),
  and DRM-PRIME surface layout probing.
- vk_device: a custom wgpu Vulkan device that adds
  VK_EXT_image_drm_format_modifier (+ external-memory fd/dma-buf) via the
  wgpu-hal device-from-raw path, so a tiled VAAPI surface can be imported.
- dmabuf: import a VAAPI NV12 surface's tiled DMA-BUF as two aliasing wgpu
  textures (Y=R8, UV=RG8) at the plane offsets.
- zerocopy test: render values via Vulkan straight into the VAAPI surface
  and read them back 100% correct -- proving the GPU writes into the
  encoder surface with no CPU copy.

Not yet wired into the editor; real-frame render + encode-from-surface +
fallback wiring follow. Linux-only (libva); other platforms fall back.
2026-06-23 19:07:37 -04:00