Skip to content

chore(core): bump creative-core to 0de5687, sync resident tiles in parallel - #3126

Merged
prakashUXtech merged 2 commits into
devfrom
chore/bump-core-0de5687
Oct 19, 2026
Merged

prakashUXtech merged 2 commits into
devfrom
chore/bump-core-0de5687

Conversation

@prakashUXtech

Copy link
Copy Markdown
Contributor

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 chore(core): bump creative-core to bf5426e #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.

The GPU route syncs the layer tiles under a region in parallel, as the
CPU route renders its tiles; steps keep their order. On an 8K brush
frame that crosses two tiles, the sync drops from about 0.73 ms to 0.39.

Tests/render-budgets.md records the 8K table with core 0de5687 and says
where a resident brush frame's time goes now.
@prakashUXtech
prakashUXtech merged commit bede834 into dev Oct 19, 2026
prakashUXtech added a commit that referenced this pull request Oct 20, 2026
… 8K (#3144)

Dragging a colour slider on an 8K image was slow on the GPU route.
Hue/Saturation was read back and run on the CPU for every band. Any
visible adjustment layer sent every redraw (a slider, a Move, a brush
frame) down that same read-back path. This moves both onto GPU passes,
using the tone programs from qbtrix/creative-core#624.

What changed:
- `PhotoLiveTone.swift` adds the live route. Each band keeps its
composite of the pixel layers (under the lowest adjustment layer) on the
GPU while those layers are unchanged. Adjustment layers higher up run as
one tone-program pass each, and a faded or blended one is composited
back with its mode and opacity. The adjustment layers at the top and the
image's adjustments are folded into the display write itself. A slider
step therefore composites nothing, uploads nothing and reads nothing
back. Photo's own Hue/Saturation (the W3C colour matrix) goes in as a
matrix operation, so the GPU picture matches the CPU and export result.
- `TileCanvas` gives its Metal target a `writeToned` write
(`display_tone`).
- The Curves histogram waits until a slider rests for 150 ms before it
recounts. Before, every Levels or Exposure step started a CPU recount
that ran to the end even after the next step replaced it.
- The core pin moves to 9ed9ef0 (bf5426e..9ed9ef0 via #3126's 0de5687;
the new piece is qbtrix/creative-core#624). `project.yml` gets the same
revision.

8K, release, M2 Pro, one step p50 / p95
(`PhotoAdjustSliderLatencyTests`, GPU route into the canvas texture):

| Step | before | after |
|---|---|---|
| Hue/Saturation | 636 / 661 ms | 12.4 / 13.4 ms |
| Levels gamma | 79 / 93 ms | 18.8 / 24.2 ms |
| Curves | 79 / 113 ms | 17.8 / 19.2 ms |
| Levels adjustment layer | 820 / 869 ms | 18.0 / 22.2 ms |
| Hue/Sat adjustment layer | 816 / 839 ms | 12.5 / 13.9 ms |
| Move, top layer | 35 / 41 ms | 33 ms p50 (composites every layer,
unchanged) |

Not moved: Blur (any radius over 0 keeps the old path for the whole
picture), masked adjustment layers, and the CPU route. Levels and Curves
rebuild their tables on the CPU each step (about 2.5 ms), which keeps
them over the 16 ms target. That miss is recorded as a known issue, and
the budgets are in `Tests/render-budgets.md`.

Tests:
- `PhotoLiveToneTests` (Linux): whole-image steps, adjustment layers at
the top, in the middle and at 50 % Multiply, all match the CoreRaster
reference within 2 levels and composite nothing on a step. Blur falls
back.
-
`PhotoRenderBackendTests.theLiveRouteDrawsAdjustmentsAndLayersAsTheReference`
(Metal): the app's own wiring matches the reference within `standard`.
- Mutation plan `PhotoModel.PhotoLiveTone`: 3/3 caught.
- New perf tests `PhotoAdjustSliderLatencyTests` and
`PhotoWindowLiveEditTests` are in the perf list.

Allow-Dup: Tone settings PhotoLiveTone.swift adapts AdjustmentSettings
onto creative-core's ToneProgram for the GPU live route; it moves to the
shared imaging target with tone-controls. Recorded in
Tests/canonical-baseline.txt.
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.

1 participant