Skip to content

feat(mask): implement blur scissor logic and optimise rendering pipeline - #2490

Merged
richiemcilroy merged 5 commits into
CapSoftware:mainfrom
viralcodex:blur-gpu-perf
Oct 20, 2026
Merged

richiemcilroy merged 5 commits into
CapSoftware:mainfrom
viralcodex:blur-gpu-perf

Conversation

@viralcodex

@viralcodex viralcodex commented Oct 13, 2026 •

Copy link
Copy Markdown

Problem

Every privacy-mask blur draws two fullscreen triangles per frame. Even a small mask processes the entire output in both passes, wasting GPU time during playback and export.

The shader already limits expensive blur sampling, but fragments outside the mask still run.

flowchart LR
  subgraph Before
    B1["Fullscreen horizontal pass"] --> B2["Fullscreen vertical pass"]
  end
  subgraph After
    A1["Mask bounds + blur support"] --> A2["Mask bounds"]
  end
Loading

Solution

  • mask.rs applies conservative scissor rectangles. The horizontal pass includes vertical blur support and sampling guards; the vertical pass covers the mask.
  • Bounds round outward and clip to the output. Fully offscreen masks skip drawing. Fullscreen masks keep the existing draw commands.
  • Attachment clears, blur sampling, blending, and non-blur modes remain unchanged.

Benchmark

The reproducible harness and its dependency lockfile are prepared locally and pending push under scripts/bench-mask-scissor/. It imports the production mask layer and shader without the FFmpeg dependency. Exact inputs and methodology are documented in scripts/bench-mask-scissor/README.md.

Apple M4 Pro, Metal, 3840x2160, release build, blur radius 12. Medians of 21 alternating samples per variant after three warmup pairs. Each sample batches eight mask sequences; timings below are milliseconds per sequence, not per batch.

These are submission-to-GPU-completion timings, not GPU-only timestamps. They include submission and synchronization, exclude resource creation and CPU command encoding, and replace the previous timing table. Metal timestamp queries produced zero or misleading stage values, so the harness does not use them. These are mask-layer timings, not end-to-end playback/export timings.

Mask Fullscreen ms Scissored ms Speedup
Small 0.63 0.17 3.67x
Medium 1.56 1.11 1.41x
Overlapping 1.73 0.79 2.18x
Edge-clipped 0.63 0.16 3.92x
Fullscreen 4.07 4.07 1.00x

Run from the repository root after the harness is pushed:

CARGO_TARGET_DIR=target/mask-scissor-bench cargo test --manifest-path scripts/bench-mask-scissor/Cargo.toml --release --lib mask::benchmark::blur_scissor_benchmark -- --exact --ignored --nocapture --test-threads=1

Pixel validation

The rendered comparison checks every output byte against the original fullscreen draw for fractional, edge-clipped, and sequential overlapping masks. Both variants share the shader, sampler, clears, blending, and varying-color/alpha input. Each case must change pixels to reject inert renders.

To run only the bounds and pixel checks:

CARGO_TARGET_DIR=target/mask-scissor-bench cargo test \
  --manifest-path scripts/bench-mask-scissor/Cargo.toml --release --lib \
  blur_scissor -- --include-ignored --skip blur_scissor_benchmark \
  --nocapture --test-threads=1

RetriggerConfidence Score: 5/5

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

Summary

Limits blur drawing to conservative mask bounds while keeping the existing clears, sampling, and blending.

  • Privacy-mask blur draws only the area each pass needs.
  • A standalone harness compares fullscreen and scissored blur.

Reviews (3) · Last reviewed commit: "Add initial implementation for mask scis..." · Reviewed by Greptile

Comment thread crates/rendering/src/layers/mask.rs

Copy link
Copy Markdown
Member

Please address Greptile’s remaining feedback and get this to 5/5 before we merge. Add a rendered pixel comparison against the original fullscreen blur path, covering fractional bounds, edge-clipped and overlapping masks. The rectangle tests alone do not verify that blur-edge pixels stay unchanged. Please also include the reproducible benchmark harness/command for the timings in the description.

@viralcodex

Copy link
Copy Markdown
Author

Please address Greptile’s remaining feedback and get this to 5/5 before we merge. Add a rendered pixel comparison against the original fullscreen blur path, covering fractional bounds, edge-clipped and overlapping masks. The rectangle tests alone do not verify that blur-edge pixels stay unchanged. Please also include the reproducible benchmark harness/command for the timings in the description.

yes sir on it

@viralcodex

Copy link
Copy Markdown
Author

@greptileai review

@vercel

vercel Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

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

A member of the Team first needs to authorize it.

@viralcodex

Copy link
Copy Markdown
Author

added, please check :)

@richiemcilroy

Copy link
Copy Markdown
Member

Thanks for the PR. Greptile's 5/5 was for 6a23daf, and new commits have landed since, so the current head hasn't been scored. We only merge once the current head is 5/5. Please comment @greptileai to request a re-review and get it back to 5/5. The sync-tests (windows-2022) check is also failing on the current head and needs to be green.

@viralcodex

Copy link
Copy Markdown
Author

@greptileai review

@viralcodex

viralcodex commented Oct 14, 2026 •

Copy link
Copy Markdown
Author

Thanks for the PR. Greptile's 5/5 was for 6a23daf, and new commits have landed since, so the current head hasn't been scored. We only merge once the current head is 5/5. Please comment @greptileai to request a re-review and get it back to 5/5. The sync-tests (windows-2022) check is also failing on the current head and needs to be green.

hey @richiemcilroy, everything is green with 5/5 review

@richiemcilroy
richiemcilroy merged commit 4b52128 into CapSoftware:main Oct 20, 2026
44 of 46 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