Skip to content

perf(desktop-gpui): accelerate screenshot-export and frame kernels - #2529

Merged
richiemcilroy merged 1 commit into
CapSoftware:mainfrom
mihir0209:perf/gpui-export-frame-kernels
Oct 19, 2026
Merged

richiemcilroy merged 1 commit into
CapSoftware:mainfrom
mihir0209:perf/gpui-export-frame-kernels

Conversation

@mihir0209

@mihir0209 mihir0209 commented Oct 13, 2026 •

Copy link
Copy Markdown

Rebased onto main (2b2bf84). Speeds up the GPUI screenshot-export path. All outputs are bit-identical to the current code.

Changes

  • kernels/src/screenshot.rs — flatten_onto_white fast-paths fully-opaque pixels (skip) and fully-transparent pixels (fill white) instead of running three integer divisions per pixel, and hoists the per-pixel 255 * (255 - alpha) recompute. This has four production callers, including the unannotated-composite fast path added in perf: speed up unannotated screenshot exports #2493.
  • kernels/src/codec.rs — new flatten_rgba_to_rgb_over_white fuses the Share-JPEG flatten plus the alpha strip into a single pass with one allocation, replacing two full-frame passes and a 33 MB transient at 4K. rgba_to_rgb pre-sizes its output instead of growing it through flat_map + collect.
  • src/screenshot_export.rs — encode_jpeg uses the fused kernel.
  • kernels/benches/frame_export.rs — before/after bench in the style of screenshot_blit.rs (old code preserved as mod baseline, equality asserted, alternating execution order, CSV output). Run with cargo bench -p cap-gpui-kernels --bench frame_export.

Benchmarks

Median of 25 samples after 5 warmup, alternating before/after order on the same buffers, opt-level = 3:

workload before after speedup
flatten opaque 1080p 4.56 ms 1.48 ms 3.09x
flatten opaque 4K 18.41 ms 6.01 ms 3.06x
flatten mixed-alpha 4K 18.30 ms 7.70 ms 2.38x
export flatten + strip 4K (fused) 49.19 ms 15.20 ms 3.24x
rgba_to_rgb 4K 31.00 ms 19.44 ms 1.59x

The 4K Share-JPEG pre-encode stage drops ~34 ms and one 33 MB transient allocation.

Note on the last row: after this PR encode_jpeg uses the fused kernel, so rgba_to_rgb no longer has a production caller and is kept as a public-kernels improvement, covered by the bench.

Correctness

cargo test -p cap-gpui-kernels — 34 passed, 0 failed. The pre-existing exhaustive all-channel/all-alpha flatten test, the JPEG round-trip test, and the new fused_flatten_to_rgb_matches_two_step test (all 65,536 channel/alpha pairs, empty input, trailing bytes) all pass, so outputs are bit-identical.

A previous revision of this PR also changed frame::swap_red_blue to a u32 swizzle. The in-crate benchmark showed that as a 5.5x regression when called across a crate boundary (the copy_from_slice lowers to a per-pixel memcpy there), and a direct-index rewrite measured as a wash, so that change has been dropped rather than shipped.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no actionable issues remain.

Summary

Speeds up screenshot export without changing the pixel formulas.

  • Screenshot exports flatten onto white faster by skipping work for solid and clear pixels.
  • Share JPEG exports turn RGBA into white-backed RGB in one pass.

All three earlier findings are addressed: benchmark columns stay correctly labeled, the fused function has unit tests, and the unnecessary comment is gone. The supplied threads were manually resolved by mihir0209 without explanatory replies.

The review used the full PR diff because the current and previously reviewed commits have different merge bases. Tests and benchmarks were inspected, not executed.

Reviews (6) · Last reviewed commit: "perf(desktop-gpui): speed up the screens..." · Reviewed by Greptile

@vercel

vercel Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Someone is attempting to deploy a commit to the Cap Software Inc Team on Vercel.

A member of the Team first needs to authorize it.

Comment thread apps/desktop-gpui/kernels/benches/frame_export.rs Outdated
Comment thread apps/desktop-gpui/kernels/src/codec.rs
@richiemcilroy

Copy link
Copy Markdown
Member

Thanks for the PR. Greptile currently has this at 4/5, and we only merge PRs once Greptile scores the current head 5/5. Please address the remaining Greptile feedback, then comment @greptileai to request a re-review, and repeat until it reaches 5/5.

@mihir0209

Copy link
Copy Markdown
Author

@greptileai please re-review. Addressed both P2 findings: (1) bench now keeps (baseline, candidate) column order on alternating samples in both emit and run_swap; (2) added exhaustive fused_flatten_to_rgb_matches_two_step unit test in kernels/src/codec.rs covering all channel/alpha pairs, empty input, and trailing bytes.

@mihir0209

Copy link
Copy Markdown
Author

@greptileai both P2 threads are now resolved (fixes in 4e38f37: bench column order kept as (baseline, candidate) on alternating samples, plus exhaustive fused unit test). Please re-review the current head for the 5/5.

Comment thread apps/desktop-gpui/kernels/benches/frame_export.rs Outdated
@mihir0209

Copy link
Copy Markdown
Author

@greptileai run-command comment removed (2719e65), thread resolved. Please re-review the current head for the 5/5.

@mihir0209

This comment was marked as spam.

@mihir0209

Copy link
Copy Markdown
Author

@richiemcilroy all Greptile feedback is addressed and verified on the current head (2719e65): bench column order fixed, exhaustive fused unit test added, run-command comment removed. All three review threads resolved and the Greptile Review run is green with no new findings. Ready for your 5/5 check whenever suits.

@mihir0209

Copy link
Copy Markdown
Author

@greptileai fixed the CI compile error in the new unit test (pinned Vec:: for the empty-input assert, 69a7035). Please re-review the current head.

@richiemcilroy

Copy link
Copy Markdown
Member

Thanks for this! It now conflicts with main after today's merges. Could you merge or rebase onto the latest main? Once it's up to date I'll run the full engine verify and real-capture suites on it and merge if they pass.

flatten_onto_white fast-paths fully-opaque pixels (skip) and fully-transparent
pixels (fill white) instead of running three integer divisions per pixel, and
hoists the per-pixel 255 * (255 - alpha) recompute. A new fused
flatten_rgba_to_rgb_over_white does the Share-JPEG flatten plus the alpha strip
in one pass with one allocation, replacing two full-frame passes and a 33 MB
transient at 4K, and rgba_to_rgb now pre-sizes its output instead of growing it
through flat_map + collect.

Outputs are bit-identical: the exhaustive all-channel/all-alpha flatten test,
the JPEG round-trip test and a new fused-vs-two-step test all pass unchanged.

Benchmarked by kernels/benches/frame_export.rs (median of 25 samples after
warmup, alternating order, same buffers):

  flatten opaque 1080p   4.56 ms -> 1.48 ms   3.09x
  flatten opaque 4k     18.41 ms -> 6.01 ms   3.06x
  flatten mixed 4k      18.30 ms -> 7.70 ms   2.38x
  rgba strip 4k         31.00 ms -> 19.44 ms  1.59x
  export flatten+strip  49.19 ms -> 15.20 ms  3.24x
@mihir0209
mihir0209 force-pushed the perf/gpui-export-frame-kernels branch from 69a7035 to ec63a2a Compare October 18, 2026 18:32
@mihir0209

Copy link
Copy Markdown
Author

@greptileai rebased onto main (2b2bf84) with a single clean commit, and the benchmark caught a regression in my own change: the rame::swap_red_blue u32 swizzle is a 5.5x slowdown across the crate boundary, so it has been dropped. The PR now only carries the flatten fast-path, the fused flatten-to-RGB kernel and the pre-sized strip, with corrected before/after numbers from the in-crate bench. Please re-review the current head.

@richiemcilroy richiemcilroy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Verified: the alpha 0/255 fast paths are exact against the original formula, the fused flatten is tested exhaustively against the two-step path, CI green, Greptile 5/5. Thanks!

@richiemcilroy
richiemcilroy merged commit a05ee24 into CapSoftware:main Oct 19, 2026
37 of 39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants