Merge: focus peaking, so a frame can be judged without zooming to 100%

FR-CULL-3's peaking half. The raw histogram and raw clipping indicators
remain unbuilt -- what exists is a display histogram tagged FR-DSP-7,
counting AdjustPass's 8-bit output, which reports a highlight as gone
precisely where FR-CULL-3 needs it to report the highlight recoverable.

Verified before merge: fmt clean, clippy --workspace --all-targets
-D warnings green, 11 focus GPU tests, 79 baseline dr-gpu tests, 511
dr-ui tests. The cfg(target_os = "android") arm is unverified -- the
host-target clippy never compiled it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

# Conflicts:
#	ui/dr-ui/src/lib.rs
#	ui/dr-ui/ui/app.slint
This commit is contained in:
2026-08-29 21:43:35 +02:00
9 changed files with 1781 additions and 1 deletions
+21
View File
@@ -55,6 +55,27 @@ readback is at viewport resolution, not sensor resolution. The 7.43 ms at 4K in
not the bill. **It has not been measured on the device**, which is the first thing to do if the
develop view feels heavy on the tablet; do not assume this is the cause without a number.
### And a second transfer, while focus peaking is on
Added 2026-08-29 with FR-CULL-3. The focus-peaking overlay is a compute pass writing its own
`Rgba8Unorm` texture, which on desktop reaches the compositor with no copy — but on Android there is
no more a path for *that* texture than for the frame it belongs to, and an overlay that stayed on
the device while the picture underneath it did not would simply never be seen. So
`FocusPeakPass::read_overlay` follows the frame back through memory, and the Android frame path
carries **two** full-resolution `copy_texture_to_buffer` transfers instead of one.
This is recorded under TD-1 rather than as its own entry because it is not an independent choice.
It exists only because TD-1 exists, it is bounded by the same thing — `render` fits the pass to the
canvas, so both transfers are at viewport resolution — and TD-1's "Done when" already covers it:
whichever of the three fixes above lands removes the readback for the frame and the overlay
together, because both are the same missing capability.
Two things worth saying plainly. The doubling is **reasoned, not measured on the device** — the same
gap TD-1 admits about its own cost, and the reason neither number should be quoted as a measurement.
And it is paid only while the photographer has the overlay switched on: `DevelopSession::focus_overlay`
returns on its first line when peaking is off, so with it off there is no dispatch and no transfer,
and the Android frame path is exactly what it was before this feature existed.
### Paying it off
Any one of these removes it: