Repository navigation
perf(desktop-gpui): convert the camera preview at bubble size, newest frame only, while shown - #2806
Draft
richiemcilroy wants to merge 5 commits into
Draft
richiemcilroy wants to merge 5 commits into
richiemcilroy wants to merge 5 commits into
Conversation
Contributor
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ng it saves little
Member
Author
|
@greptileai review |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2761 (
perf/camera-preview-convert-off-main), so this diff shows only the work on top of it.What
Before this change, every camera frame was converted at the camera's full size, even though the bubble shows it at about 460 px tall by default. At 4K that is 33 MB written per frame (99 MB when mirrored) and a 127 to 222 MB IOSurface ring. Queued frames were converted even after newer ones had arrived. Frames were also converted while the bubble was covered, the display was asleep, or the window was ordered out.
Change
CameraWindow::preview_targettakes the bubble's size (the larger of the requested window size and the current viewport, minus the toolbar) and multiplies it by the scale factor. It rounds each axis up to a fixed step: 270, 360, 480, 540, 720, 960, 1080, 1440, 1920 or 2160.cap_gpui_kernels::camera_preview::cover_dimensionsthen picks the smallest size that has the source's aspect ratio and still covers that step.Converted::layout_dims, andCameraPreviewFrame::dimson Windows and Linux). The rounding never moves the window's aspect, so the Linux recording snapshot check sees exactly what it sees today.queue_conversionevicts a frame still waiting in the conversion thread's single-slot queue, so the thread always picks up the newest one. Before, the old frame was kept and the new one was dropped.Disconnected.platform::window_is_presentingchecksocclusionStateforNSWindowOcclusionStateVisible. That is the same test gpui's display link (and the frame pacer patch'sFrameRequests::Once) starts and stops on, with the macOS 26 shim applied, so a window that fails it draws nothing anyway.Hona-authored lines (
snapshot_bgra, thecopy_rowscall in the preview image builder) are unchanged.Measurements
Synthetic frames on CI (no cameras there), from scratch branch
ci/camera-preview-downscale-ab(not for merge). Bubbles: small = 230 pt round (default), medium = 400 pt round (large preset), large = 600 pt full shape. All at 2x scale. "main" is the conversion main and #2761 run every frame with blur off (full size). "branch" is this PR.macOS (Blacksmith macOS 26.3, Apple M5 Max virtual machine)
Source:
cargo run --example camera-preview-convert-benchmark -- --bubble. The benchmark runs the same VideoToolbox transfer, plus the rotation pass when mirrored, thatFrameConverterruns.Reading it:
camera-preview-convertthread, not the main thread. It stays far below the 33 ms frame interval.Windows (Blacksmith Windows 2025)
Source:
cargo test --bin cap-gpui camera_preview_scale_benchmark -- --ignored --nocapture. It times the realcamera_preview_image_at(swscale, row copy,RenderImage) at full size against the bubble target. MB per frame is theRenderImage, which is what the main thread uploads to the atlas each frame.Linux (Blacksmith Ubuntu 24.04)
Windows and Linux are faster or equal on every row. For the default bubble they are 2 to 5x faster, and the main-thread atlas upload shrinks 2.3x at 720p, 5x at 1080p and 20x at 4K. Where the branch column is up to 0.3 ms higher, both sides run the identical full-size conversion. That difference is run-to-run noise.
cap-recording'scamera-preview-benchmarkneeds a physical camera, which CI does not have. The ignored test above replaces it, using synthetic NV12 and YUYV frames.Not in this PR
set_camera_preview_renderingduring clean capture, and Windows has no equivalent hook yet.copy_rowsstill zero-fills itsVec, and the atlas still re-uploads each frame on Windows and Linux. They are now about 5x smaller at 1080p. A follow-up can address them.Needs an on-device check
camera preview cadencelog should show painted fps dropping to 0 and resuming at once.cargo run -p cap-desktop-gpui --example camera-preview-convert-benchmark -- --bubble. If scaled VideoToolbox transfers also measure slower there, this PR keeps the memory win and costs a little off-main time.