Skip to content

fix(raster): centre motion blur and pin blur family contracts - #593

Merged
github-actions[bot] merged 1 commit into
devfrom
lead/effects-engine-r1-b1
Oct 19, 2026
Merged

github-actions[bot] merged 1 commit into
devfrom
lead/effects-engine-r1-b1

Conversation

@prakashUXtech

@prakashUXtech prakashUXtech commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Anatomy round 1, batch r1-b1 for effects-engine (#433). Fixes the blur-family findings in Sources/CoreRaster/Effects/BlurFamily.swift and adds the tests and mutation entries those contracts were missing.

Fixes

  1. Box blur reach documented. boxBlurred(radius:) now says that each pass averages a 2·radius+1 px window, that colour spreads up to 3·radius px, that the result is close to a Gaussian of sigma ≈ sqrt(radius·(radius+1)), and that a caller should pad by 3·radius. Proved by BlurFamilyTests.boxReachesThreeRadii: at radius 2 a dot is nonzero 6 px away and exactly zero 7 px away, on both axes.
  2. Motion blur centring documented. motionBlurred(degrees:distance:) and the file header now say the blur is centred, so only the axis matters. They also give the integer-distance snap and say that an odd integer distance sits 1/2 px toward -angle.
  3. Motion blur is centred (contract fix). Before, the first sample offset was always floor(-distance/2), so a 0.4 px blur moved the layer 0.8 px. It now starts exactly at -distance/2. Exact centring for every distance broke the integer-distance acceptance test motionSpreadsTen (half-pixel samples spread a 9 px blur over 11 columns). So the code takes the snap option: an integer distance snaps its first sample down to a whole pixel (floor(-distance/2), as before), and every non-integer distance is centred exactly. Proved by BlurFamilyTests.motionIsCentred: for d in 0.4, 2.5 and 9 at 0 and 180 degrees, the centroid stays within 1/2 px of 16 in x and on row 16. For the non-integer distances, 0 and 180 degrees give the same centroid within 1e-6. Before the fix d = 0.4 gave 16.8. Mutation: "motion blur floors its first sample offset".
  4. Box blur is pinned to both axes and three passes. boxKeepsEnergy now also requires the occupied rows to grow. The new BlurFamilyTests.boxSpreadsBothAxesThreePasses checks that a dot at radius 1 covers exactly rows and columns 13...19 and that its centre alpha is (7/27)^2. Mutations: "box blur skips its vertical pass" and "box blur runs one pass per axis instead of three".
  5. Edge extension is tested. BlurFamilyTests.opaqueEdgesStayOpaque: an opaque red 12x12 buffer stays exactly red and opaque at every pixel, corners included, under box radius 3 and motion distance 7. Mutation: "box blur pads before the start of a line with zeros".
  6. Right-angle snap is tested. horizontalSpreadsColumns now checks for exact zeros where the cos/sin residue would leak. These are pixels at the buffer edge whose off-centre sample would land just past column or row 0. The interior pixel the finding suggested, (17,16), does not detect the leak, because the residue rounds away next to 16. Mutation: "motion blur keeps the cos residue at 90 degrees".
  7. The inclusive cap is checked from the accepting side. overCapThrows now also requires radius 1,000 and distance 1,000 to return a buffer. Mutation: "blur reach check excludes its upper bound".

scripts/ci: CI: PASS on the head below. scripts/mutate --run --changed-since origin/dev: 9/9 caught. No platform API is new here (only Double.rounded, already in use), so no docs lookup was needed.

Note: the requested branch name lead/effects-engine/r1-b1 cannot exist, because the branch lead/effects-engine already exists. This PR uses lead/effects-engine-r1-b1 instead.

Refs #433 (feature-lead issue; this batch does not close it)

Belt-Lead: act-1a150bfbcf7-sfwy
Feature: effects-engine
Slice: FX-blur
Mutate: 9/9 CoreRaster.BlurFamily
Fast-Check: pass
Head: cfd4407


@prakashUXtech prakashUXtech added the fast-lane Small green PR, auto-merge when eligible label Oct 19, 2026 — with Claude
@github-actions
github-actions Bot merged commit 705e16c into dev Oct 19, 2026
1 check passed
@github-actions github-actions Bot added the fast-lane-merged Merged by the fast lane; review after the fact label Oct 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Fast lane: merged into dev (123 lines, 3 files, Fast-Check marker).

prakashUXtech added a commit that referenced this pull request Oct 19, 2026
@github-actions github-actions Bot mentioned this pull request Oct 19, 2026
prakashUXtech added a commit to qbtrix/creative-apps that referenced this pull request Oct 19, 2026
…rallel (#3126)

Moves the creative-core pin from bf5426e to 0de5687, the head of core
`main` (green, promoted from dev). The range has the resident-rendering
speedups from qbtrix/creative-core#620: the batched composite commits
without waiting, the resident dirty check is storage identity instead of
a pixel compare, and the Float16 tile upload vectorizes. It also has
qbtrix/creative-core#626, which repoints the mutation anchor #620 moved.

Core range (58 commits):
qbtrix/creative-core@bf5426e...0de5687

Core PRs in the range: qbtrix/creative-core#567 qbtrix/creative-core#568
qbtrix/creative-core#569 qbtrix/creative-core#570
qbtrix/creative-core#571 qbtrix/creative-core#573
qbtrix/creative-core#574 qbtrix/creative-core#575
qbtrix/creative-core#576 qbtrix/creative-core#577
qbtrix/creative-core#578 qbtrix/creative-core#579
qbtrix/creative-core#580 qbtrix/creative-core#581
qbtrix/creative-core#582 qbtrix/creative-core#583
qbtrix/creative-core#584 qbtrix/creative-core#585
qbtrix/creative-core#586 qbtrix/creative-core#587
qbtrix/creative-core#588 qbtrix/creative-core#589
qbtrix/creative-core#590 qbtrix/creative-core#591
qbtrix/creative-core#592 qbtrix/creative-core#593
qbtrix/creative-core#594 qbtrix/creative-core#595
qbtrix/creative-core#596 qbtrix/creative-core#597
qbtrix/creative-core#598 qbtrix/creative-core#599
qbtrix/creative-core#600 qbtrix/creative-core#601
qbtrix/creative-core#602 qbtrix/creative-core#603
qbtrix/creative-core#605 qbtrix/creative-core#606
qbtrix/creative-core#607 qbtrix/creative-core#608
qbtrix/creative-core#609 qbtrix/creative-core#612
qbtrix/creative-core#613 qbtrix/creative-core#614
qbtrix/creative-core#615 qbtrix/creative-core#616
qbtrix/creative-core#617 qbtrix/creative-core#618
qbtrix/creative-core#619 qbtrix/creative-core#620
qbtrix/creative-core#621 qbtrix/creative-core#622
qbtrix/creative-core#623 qbtrix/creative-core#625
qbtrix/creative-core#626

Besides the pin:
- `project.yml` gets the same revision, as in #3023.
- `PhotoWorkspace.residentComposited` syncs a region's layer tiles
across the cores (through `PhotoLayerComposite.inParallel`), as the CPU
route renders its tiles. Steps keep their order. On a brush frame that
crosses two tiles the sync went from about 0.73 ms to 0.39 ms.
- `Tests/render-budgets.md` has the new 8K table and says where a
resident brush frame's time goes.

8K brush frame, release on the M2 Pro (median of three runs; the Mac was
loaded, with another Photo running): CPU 1.0 ms, GPU-resident 1.4 ms
(was 1.7). The GPU route is still behind the CPU. Most of what's left is
the display into the presenter's texture, which waits about 0.55 ms for
the GPU because the presenter draws from its own queue. Full redraw on
the resident route is 31 ms (was 35) and the first picture 166 ms (was
192).

Checked locally on macOS: `scripts/bump-core`'s steps at 0de5687. `swift
build --build-tests` passed. Every `*ModelTests` target passed except
four Library wall-clock budget tests
(`oneEditOnSixtyPhotosStaysInBudget`, `cullOneWithinBudget`,
`beginImportWithinBudget`, `orderRebuildWithinBudget`), which went over
in the parallel run on the loaded Mac and pass when run alone. The brush
perf suites (PhotoBrushDisplayTests, PhotoBrushLatencyTests,
PhotoBrushInkLatencyTests) passed. With the parallel sync on top,
`PhotoModelTests` and `PhotoRenderBackendTests` passed (647 tests), and
`PhotoRenderBudgetTests` ran in release with
`Tests/SuiteUITests/SegmentedTabsTests.swift` set aside, since it
doesn't link in release on SDK 27.
prakashUXtech added a commit that referenced this pull request Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fast-lane Small green PR, auto-merge when eligible fast-lane-merged Merged by the fast lane; review after the fact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant