Skip to content

feat(moq-video): export the studio program to the encoder on the GPU - #6805

Merged
kixelated merged 32 commits into
mainfrom
quest/m1/studio-gpu/encode
Oct 26, 2026
Merged

kixelated merged 32 commits into
mainfrom
quest/m1/studio-gpu/encode

Conversation

@kixelated

@kixelated kixelated commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Finishes quest/m1/studio-gpu/encode.md (deleted here): the studio's program reaches moq-video's encoder as a GPU surface on NVENC, VideoToolbox, and Media Foundation, and takes a counted CPU readback for an encoder that reads frames on the CPU.

Builds on moq-dev/moq#6797, which added rs/moq-studio and rs/moq-scene and has merged; this now targets main.

What landed

moq_video::render::export is the mirror of Renderer: Exporter::copy snapshots an RGBA texture into one of Exporter::DEPTH (3) slots and returns at once; Pending::wait blocks on the GPU on the encoding thread and hands back a Frame. A copy that finds every slot busy returns None, so a slow encoder drops pictures rather than adding latency.

Exporter::new(device, queue, &mut encode::Config) settles the encoder and the route once. It tries the encoders config.kind allows in priority order, probing each with a frame exported from device (not a synthetic CPU picture). An encoder that reads this platform's GPU surface (NVENC on Linux, VideoToolbox, Media Foundation) takes Route::Gpu, and only if it encodes this device's export; every other one (OpenH264, VA-API and V4L2 today) takes Route::Readback. It leaves config.kind as Kind::Named(<the encoder it settled on>) and, on Linux, config.input as that encoder's device, so the encoder opened next is the one probed and the published rendition is true. An encoder never switches routes:

  • Hybrid GPUs work by default. Under Auto, Hardware or Software, an encoder that cannot read this device's export (NVENC while wgpu sits on the iGPU, another vendor's GPU, or lavapipe; or any device without the export extensions) is passed over for the next encoder, which reads frames back.
  • An explicit choice fails loudly. Kind::Named("nvenc") with a device on another GPU fails Exporter::new with nvenc cannot encode this device's export (...); if nvenc runs on another GPU, open the device there with moq_video::render::request_device, or pick an encoder that reads CPU frames.
  • Once running, a failed GPU copy is an Err, never a retry or a degrade.
  • An explicit encode::Config::color other than Color::infer's is refused at setup: every route converts in the inferred space, so such a config would otherwise fail every frame with ColorMismatch.

The GPU route on each platform:

  • Linux / Vulkan (NVENC): an exportable image (opaque-fd memory) plus a timeline semaphore, handed over as Surface::Vulkan through the existing frame::vulkan slot contract. A compute shader does the copy because wgpu-hal maps storage usage to GENERAL, the layout the contract requires. The ready value is host-signalled after the copy's submission completes, since wgpu's signal-semaphore hook applies to whatever submits next. The same slot serves VA-API and AMD Vulkan Video later with no API change.
  • macOS / Metal (VideoToolbox): a CVPixelBufferPool of IOSurface-backed NV12 buffers, capped at the depth with the pool's allocation threshold. CVMetalTextureCache aliases each plane as a drawable Metal texture. A shader converts RGBA to NV12 in Color::infer's space (the one Surface::rgba picks), so the encoder gets the format every other Apple producer hands it. The shader is also checked against the CPU matrix on Linux.
  • Windows / Direct3D12 (Media Foundation): a BGRA texture created shareable on wgpu's D3D12 device and opened on a D3D11 device on the same adapter (by LUID). After wgpu's draw lands, the D3D11 video processor converts it to NV12 (the path WGC capture already takes) and hands over Surface::Texture. An event query per slot keeps a slot from being redrawn while the conversion still reads it.

render::request_device opens a wgpu device with what the zero-copy paths need (the DMA-BUF feature and VK_KHR_external_semaphore_fd on Linux), shared with the import side (moq-dev/moq#6806). The studio opens its device with it, publishes through an Exporter, and its Output panel shows frames handed to the encoder and readbacks ("none; the encoder reads the GPU" on the GPU route, known from startup). moq-scene's own Readback is gone.

Public API and wire impact

  • New (moq-video, render feature):
    • render::request_device
    • render::export::{Exporter, Pending, Route}, with Exporter::{new, route, size, copy, DEPTH} and Pending::{wait, timestamp}.
    • Route { Gpu, Readback }, exhaustive, so a third route breaks a caller's match loudly.
  • moq-scene (unpublished, added in moq-dev/moq#6797) drops Readback, Pending, and Error::Gpu; the studio uses the export instead.
  • encode::Config is unchanged. Exporter::new rewrites its existing kind to the settled Kind::Named, and on Linux its existing input.
  • No wire impact.

Decisions (maintainer, 2026-10-25)

  • No silent fallback; fail loud. Removed export::Config { zero_copy }, Exporter::probe and its runtime switch to readback, and every Ok(None) "cannot export, read back instead" path in the Vulkan, Metal and Direct3D12 exporters (each is now an error naming the cause).

  • Run Platform on this branch before marking ready. Results below.

  • The default configuration must work on hybrid-GPU machines; an explicit mismatch still fails loudly at setup; no runtime fallback. Options considered:

    1. render::request_device (or a new adapter picker) opens the device on the GPU the encoder uses.
    2. ✅ Encoder selection only takes an export-reading encoder that reads this device's export, and otherwise picks one that reads frames back.
    3. Keep failing, and document picking the adapter.

    Picked 2 because it adds no public API: request_device takes the caller's adapter, so 1 needs a new adapter picker that ties the app's whole GPU (window, UI, power) to the encoder and can only learn NVENC's GPU through CUDA. With 2 the caller keeps choosing the adapter (the studio already asks for HighPerformance, which is the NVIDIA GPU on a typical laptop), and a mismatch costs a readback instead of a startup failure. The decision is made once at setup, observable through Exporter::route() and an info log, so it is not a runtime fallback.

Choices made

  • The export lives in moq-video next to Renderer, not moq-scene, so any wgpu app gets it.
  • Exporter::new takes the encode::Config and returns the probed rendition, replacing Exporter::new + Exporter::probe. The route depends on which encoder the config opens, so a single constructor makes an exporter whose route was never settled unrepresentable. Textures are the config's size, so the two cannot disagree.
  • Route replaces Exporter::zero_copy() -> bool, since the decision asked for the route. The Linux Exporter::input getter is private now; Exporter::new sets encode::Config::input itself.
  • Which encoders read the GPU is per backend: vulkan candidates on Linux (NVENC), every hardware encoder on Apple platforms and Windows. A software encoder takes the readback even if it could download a surface, since a readback is cheaper than its per-frame download.
  • The Metal route converts to NV12 in a shader rather than handing VideoToolbox BGRA, so the frame's color label matches the pixels and download_i420 keeps working.
  • d3d11::create_device takes an optional adapter; Texture::capture and Plan::capture are compiled for render as well as capture.
  • Kind::Hardware counts as choosing among encoders, like Auto; only Kind::Named is an explicit choice.
  • The probe encodes a frame this device exported, so setup proves the pairing on every platform. That also catches a Media Foundation MFT on another adapter than the wgpu device (the MFT binds the frame's Direct3D11 device on its first frame), which would otherwise fail on the first real frame.
  • Pinning config.kind to the settled name means Encoder::new no longer logs its own "falling back to software" warning, so Exporter::new logs it instead.
  • Dropped moq-scene's the_program_is_exportable: an export now needs an encoder, and the studio's relay test already exports the compositor's program on the host's route.
  • The two Windows lint fixes this branch carried (moq-relay's clock-lint expectation and the PipeWire-only I420::from_bgra) landed on main in moq-dev/moq#6821; the merge of main takes its versions, so they are no longer in this diff.

Checks

  • Ran: cargo clippy --all-targets -D warnings for moq-video (render,openh264; --no-default-features --features render; defaults), moq-scene, moq-studio (with and without openh264); cargo nextest for the three crates; rustdoc with -D warnings; quest check. just check's flake module fails in this sandbox (unshare: write failed /proc/self/uid_map), unrelated. All rerun after the hybrid-GPU change (clippy also with render,nvidia,openh264).
  • just rs render-sw on lavapipe: readback route, route selection (OpenH264 takes the readback), NV12 shader, compositor, and the studio's relay test.
  • Hybrid-GPU default, pinned without NVIDIA hardware: choosing_passes_over_an_encoder_that_cannot_read_this_device feeds Exporter::settle an export-reading candidate that cannot read the device (OpenH264 marked as reading the GPU, standing in for NVENC on another GPU) ahead of a readback one, and asserts the readback route, Kind::Named("openh264") and no input. a_named_encoder_that_cannot_read_this_device_fails_at_setup keeps the explicit mismatch loud and checks the error names the fix. refuses_a_color_it_does_not_convert_to covers the color refusal. On lavapipe the export cannot open (Mesa exports no memory); on RADV and ANV it opens and the encoder refuses the device, the real hybrid case, so sh/rs/gpu.sh now runs both on real drivers.
  • The ignored export tests on RADV (RX 9070) and ANV (Arrow Lake): the Vulkan export round trip, route selection, the hybrid pass-over and explicit-mismatch tests, the color refusal, and the NV12 shader pass.
  • Type-checked (cross toolchain, clippy --all-targets): the Metal route on aarch64-apple-darwin and the Direct3D12 route on x86_64-pc-windows-msvc, before the hybrid-GPU change. After it, macOS and Windows are covered by Platform only.
  • Platform after the hybrid-GPU change: run 40246348236 passes on macOS and Windows: videotoolbox_reads_the_export_in_place now settles through the exported-frame probe and VideoToolbox still encodes in place with the pool cap intact, and a_software_adapter_is_refused_at_setup passes on WARP.
  • Platform, dispatched on this branch before it: run 40237306732 passes on macOS and Windows.
    • macOS: videotoolbox_reads_the_export_in_place runs on the runner's Metal device, and VideoToolbox encodes the exported pixel buffers in place.
    • Windows: the runner has only WARP, and D3D11CreateDevice with video support fails there (DXGI_ERROR_UNSUPPORTED), so the Direct3D12 route cannot run on it (run 40234531745). exports_an_nv12_texture is now ignored and listed in video hardware validation. The new a_software_adapter_is_refused_at_setup pins the fail-loud setup error on WARP, which every Windows host has.
    • Earlier runs: 40232491446 never reached the export tests. Windows stopped on the relay lint below, and macOS on a moq-tokio flake (quic::driver::tests::stuck_window_evicts_the_lower_priority) that passed on the next two runs.
  • Review findings on d7710fe: the configured-color finding is fixed by the setup refusal above; the poll-first finding is declined in its thread.
  • Not run: NVENC (no NVIDIA here; the ignored test runs from sh/rs/vulkan-cuda.sh); the Direct3D12 round trip and the Media Foundation hardware encode (ignored, listed in video hardware validation).

Suggested follow-ups

  • Media Foundation enumerates the first hardware MFT on any adapter. On a Windows hybrid laptop whose wgpu device is on the other GPU, the probe now catches the mismatch and passes over to a readback encoder, but enumerating the MFT on the texture's adapter (MFT_ENUM_ADAPTER_LUID) would keep a hardware encode on the GPU route there.
  • The studio's default features compile only NVENC, so a host whose drawing GPU NVENC cannot read has no readback encoder to settle on unless built with vaapi or openh264.

(Written by Claude Opus 5.5)

🤖 Generated with Claude Code

kixelated and others added 23 commits October 25, 2026 09:21
Quest-Claim: 9bb42c9a3f0daa9f
Adds the UI-free half of moq-studio: a versioned TOML scene collection,
live sources (capture, image, color, subscribed broadcast), a compositor
with preview, program, cut, and fade, and a pooled program readback.
Adds moq-audio's program bus with per-source strips, and moves Level to
the crate root so the bus and capture share it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One wgpu device serves the sources, the compositor, and the window. A
program clock draws the canvas and mixes the bus, and the program is read
back and encoded only while a viewer watches.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…emains

Adds doc/bin/studio.md, the repository map and AGENTS.md rows, and the
moq-audio migration note for Level. The app quest now holds only the
zero-copy program encode and the macOS and Windows runs, and the studio
quests that only needed the app are unblocked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… frame

The canvas is black until a source delivers its first picture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collection::validate already refuses a negative or non-finite gain from a
scene file, so only a caller bug reaches Strip::set_gain; fail loud there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
app.md keeps only the macOS and Windows runs. Zero-copy program encode and
zero-copy source import become quest/m2/studio-gpu, ranked at the top of m2
and first in the studio epic, with a dated note in m1 and the studio README
that they drive moq-video improvements ahead of the cut without gating it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moq-video's GPU encode and import API changes land before the cut. The m1
quests are scoped to the API shape and the backends provable now (NVENC,
VideoToolbox, Media Foundation, DMA-BUF, Metal); AMD Vulkan encode, Intel
VA-API import, and Direct3D11 render import stay m2 follow-ups.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- moq-studio enters its runtime before building the QUIC client, which
  refused to start outside one, so --connect works from the binary.
- A failed video or audio output aborts its track with the cause instead of
  dropping it unfinished, and a clean stop finishes the video.
- A broadcast source follows catalog updates, switching a rendition when a
  better one appears instead of keeping the first catalog's choice.
- The compositor forgets an edited source's last picture, so a replaced
  source never shows the old one's frame.
- A criterion bench sweeps the program bus over channel count and resampling.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
render::export::Exporter copies a texture into a pooled slot and hands it
back as a Frame: an exported Vulkan image on Linux, a readback elsewhere.
render::request_device opens a device with the Vulkan extension that
shares a timeline semaphore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A rendition name always means the same decoder config, so a metadata-only
catalog update, such as a republished jitter estimate, no longer restarts the
decoder and drops buffered audio.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
moq-scene drops its Readback; the studio hands the program to an Exporter,
which picks a GPU route the encoder takes and falls back to a readback.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Metal draws the program into IOSurface-backed NV12 pixel buffers through a
shader conversion; Direct3D12 draws into a texture shared with a Direct3D11
device on the same adapter, where the video processor converts it to NV12.
Both are tested on their platform's CI recipe; the NV12 shader is also checked
against the CPU matrix in render-sw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The unrun Media Foundation hardware encode moves to video hardware
validation. Also flushes the Metal texture cache before taking a buffer, so
a buffer wgpu has finished with is back in the pool, and asserts every
route's exporter and copies cross threads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated kixelated changed the title feat(moq-scene): hand the program to the encoder as a GPU surface feat(moq-video): export the studio program to the encoder on the GPU Oct 25, 2026
kixelated and others added 2 commits October 25, 2026 13:30
…h no fallback

`Exporter::new(device, queue, &mut encode::Config)` probes the encoder and
takes `Route::Gpu` exactly when that encoder reads this platform's GPU
surface (NVENC, VideoToolbox, Media Foundation), `Route::Readback` otherwise.
A device that cannot export the surface its encoder reads is a setup error
naming what is missing and, on Linux, `request_device`; nothing degrades to a
readback after trying the GPU.

Drops `export::Config { zero_copy }`, `Exporter::probe`, `Exporter::zero_copy`
and the public Linux `Exporter::input`; adds `export::Route` and
`Exporter::route`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ading

- moq-scene: a broadcast rendition restarts when the track its entry
  resolves to changes, not its catalog ID, so a publisher that repoints a
  stable ID at a replacement track (the JS publisher on a codec change) is
  followed. A catalog offering only renditions from another broadcast fails
  the source instead of leaving it live and silent.
- moq-scene: a picture the compositor cannot draw is reported through
  Compositor::error, which the studio shows as the source's status.
- moq-audio: Channel::write refuses a NaN or infinite sample, which would
  poison the whole mix through any gain. Bus::capture no longer reopens a
  device behind the caller's back; it returns the device's error.
- moq-studio: program audio and video are stamped on the catalog's clock,
  so the advertised wall time matches when the program drew them, and the
  canvas keeps drawing after the encoder stops.
- Docs: the scene file can name local paths and devices; Windows system
  audio waits on the Windows capture quest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated and others added 4 commits October 25, 2026 14:12
… clock

The only relay test that reads the host clock is Unix-only, so the
module-wide expectation went unfulfilled on Windows and denied warnings
failed `just rs windows-test` before it reached the render export tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing on Windows calls it (the Desktop Duplication path it named is gone),
so the render export tests `windows-test` now builds with warnings denied
would fail on it as dead code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Platform's Windows runner has only WARP, whose D3D11CreateDevice refuses
video support (DXGI_ERROR_UNSUPPORTED), so the conversion to NV12 cannot run
there. The setup error now names the missing Direct3D11 video device, a
runner test pins that refusal on the software adapter every host has, and the
round trip moves to the ignored hardware tests in video-hardware validation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ee-agent-a3fba740265e97706

# Conflicts:
#	rs/moq-scene/src/compositor.rs
#	rs/moq-studio/src/engine.rs
@kixelated
kixelated marked this pull request as ready for review October 25, 2026 22:34
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T02:19:31.182257Z 9233df0 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d7710fee10

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +99 to +103
pub async fn new(
device: &wgpu::Device,
queue: &wgpu::Queue,
config: &mut crate::encode::Config,
) -> Result<(Self, hang::catalog::VideoConfig), Error> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Expose exporter initialization through a poll-first API

The new library initialization logic is implemented only as an async fn, with no poll_* operation accepting a &kio::Waiter. This violates the poll-first library API requirement in rs/AGENTS.md and prevents callers from driving initialization through the repository's synchronous polling interface. Implement the initialization state behind a poll operation and make the async constructor its helper; the new render::request_device API needs the same treatment.

AGENTS.md reference: rs/AGENTS.md:L21-L24

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declining. Neither function has polling logic of its own to expose. Exporter::new awaits encode::Config::probe's machinery (Sink::open and Sink::encode, which hand the codec to its own thread) and render::request_device awaits wgpu's Adapter::request_device; moq-video's encode surface is async-only today. A poll_* here would store those foreign futures in a pinned state machine and poll them, which is the pattern rs/AGENTS.md calls a smell. Both run once at setup, so there is no hot path a poll API would serve. If moq-video's encode gains poll-first Sink operations, the export should follow them then.

(Written by Claude Opus 5.5)

Comment thread rs/moq-video/src/render/export/metal.rs

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed commit: d7710fee10b96c316a09937e2c77e705da0001cd

No additional actionable bugs found. The existing poll-first API finding and configured-color concern cover the issues identified; no duplicate inline comments. For the latter, export does infer its color, but the existing probe also constructs an inferred-color I420 sample, so mismatched explicit color may fail during probing rather than only on the first exported frame. A regression test should cover the whole initialization-to-encode path.

Overall direction is sound: platform interop stays below the app, bounded slots limit backlog, and encoder failure leaves preview rendering alive. Explicit export/readback routes avoid silently changing behavior.

Verification: GitHub-only static inspection of the export routes, ownership and slot lifecycle, studio integration, feature gates and tests. No builds, tests, GPU execution or benchmarks run; ignored hardware cases remain unverified.

Exporter::new failed setup under Kind::Auto when it picked NVENC while
the wgpu device sat on another GPU, the default on a hybrid laptop or on
lavapipe. It now tries the encoders the config allows in priority order,
probing each with a frame exported from the device: an encoder that reads
the GPU takes that route only when it encodes this device's export, and
choosing passes over it for one that reads frames back. A named encoder
still fails setup, naming the fix. The settled encoder is pinned in
config.kind so the encoder opened next is the one probed.

An explicit encode::Config::color the export does not convert to is now
refused at setup instead of failing every frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@kixelated kixelated left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated review by review (OpenAI)

Reviewed commit: 810f5868a86b749071a689f992a82051cc9c772c

Reviewed the substantive update since d7710fee10b96c316a09937e2c77e705da0001cd; no new actionable bugs found.

Prior findings: the configured-color concern is addressed by rejecting unsupported color at setup, rather than adding arbitrary-color conversion. The poll-first API discussion is unchanged in code, with the author's rationale for declining it now recorded; not a new finding.

Direction is sound: probing an actual export checks device compatibility, shared candidate ordering avoids a second selection policy, and pinning the successful encoder makes subsequent initialization consistent. Setup rejection is a simpler explicit contract than adding unused per-route color conversions. Named encoders still fail rather than silently falling back.

Verification: GitHub-only static review of the incremental changes and relevant encoder/export lifecycle. No builds, tests or GPU execution run; added ignored hardware tests and cross-device behavior remain unverified.

@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 4 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b1c14b46-72e5-432d-a33b-a77fa4698aad
Commits

Reviewing files that changed from the base of the PR and between 88e1a94 and 9233df0.

Files selected for processing: 34
  • doc/bin/studio.md
  • quest/m1/README.md
  • quest/m1/studio-gpu/README.md
  • quest/m1/studio-gpu/encode.md
  • quest/m1/studio-gpu/import.md
  • quest/m3/studio/README.md
  • quest/m3/studio/app.md
  • quest/m3/video-hardware.md
  • rs/justfile
  • rs/moq-scene/src/compositor.rs
  • rs/moq-scene/src/lib.rs
  • rs/moq-scene/src/readback.rs
  • rs/moq-studio/src/engine.rs
  • rs/moq-studio/src/ui.rs
  • rs/moq-video/Cargo.toml
  • rs/moq-video/src/capture/wgc/native.rs
  • rs/moq-video/src/color.rs
  • rs/moq-video/src/encode/backend/mod.rs
  • rs/moq-video/src/encode/encoder.rs
  • rs/moq-video/src/encode/mod.rs
  • rs/moq-video/src/frame.rs
  • rs/moq-video/src/frame/processor.rs
  • rs/moq-video/src/frame/vulkan.rs
  • rs/moq-video/src/mf.rs
  • rs/moq-video/src/render/device.rs
  • rs/moq-video/src/render/export.rs
  • rs/moq-video/src/render/export/dx12.rs
  • rs/moq-video/src/render/export/metal.rs
  • rs/moq-video/src/render/export/nv12.rs
  • rs/moq-video/src/render/export/vulkan.rs
  • rs/moq-video/src/render/metal.rs
  • rs/moq-video/src/render/mod.rs
  • sh/rs/gpu.sh
  • sh/rs/vulkan-cuda.sh
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

# Conflicts:
#	doc/bin/studio.md
#	quest/m1/README.md
#	quest/m1/studio-gpu/README.md
#	quest/m1/studio-gpu/import.md
#	quest/m3/studio/README.md
#	quest/m3/studio/app.md
#	rs/justfile
#	rs/moq-scene/src/compositor.rs
#	rs/moq-scene/src/lib.rs
#	rs/moq-studio/Cargo.toml
#	rs/moq-studio/src/engine.rs
#	rs/moq-studio/src/ui.rs
@kixelated

Copy link
Copy Markdown
Collaborator Author

Merge summary for 9233df0:

  • Retargeted to main after moq-dev/moq#6797 squash-merged, and merged main in. The merge used this branch's last merge of quest/m3/studio/app (b206186) as the base, so the squash reconciles cleanly: only this PR's own changes remain in the diff (export, request_device, studio wiring, moq-scene's Readback removal, the quest deletion).
  • The Windows lint fixes now come from main (moq-dev/moq#6821); rs/moq-relay/src/relay.rs and rs/moq-video/src/capture/pump.rs match main exactly.
  • Local: just rs lint-changed and just rs test-changed (10441 passed), quest check, markdown check. CI required checks pass; Codex approved the head with a thumbs-up.
  • Left open for the maintainer: the declined poll-first finding.

(Written by Claude Opus 5.5)

@kixelated
kixelated added this pull request to the merge queue Oct 26, 2026
Merged via the queue into main with commit 00f51d3 Oct 26, 2026
11 checks passed
@kixelated
kixelated deleted the quest/m1/studio-gpu/encode branch October 26, 2026 05:52
kixelated added a commit that referenced this pull request Oct 26, 2026
Resolve against the GPU program export (#6805): `moq play` now opens its
device with `render::request_device`, the render docs point Linux callers
at it, and both macOS test sets run. With the encode quest finished there,
this PR completes the studio-gpu epic, so it is deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant