mirror of
https://github.com/storytold/photocraft.git
synced 2026-11-12 21:23:02 +00:00
Step 2 of #6916: the local Laplacian filter behind Shadows and Highlights (Paris, Hasinoff, Kautz 2011, sampled as in Aubry et al. 2014, as local_tone.rs does) as wgpu fragment passes, chained in front of step 1's per-pixel pass with no readback in between. - algo: local_tone exposes its constants and resolves the sliders into LocalTone / TonePass (the remapping is a method); the CPU filter runs those passes. PerPixel gains local_tone and measure_whites_blacks; whites_blacks_model() exposes the Whites and Blacks tables; quantile_rank() is the one rank rule. CPU output unchanged bit for bit (86 hashes, 8-bit and float, 171x113 to 2100x1300) and as fast. - gpu: camera_raw_tone.rs/.wgsl. Pyramid levels are R32Float textures; the remapped pyramids of up to 96 references sit in one Rgba32Float atlas per level, four per tile. The filter's quantiles, and Whites and Blacks' points after it, are exact order statistics on the GPU (16 thresholds per round, 8 rounds); a pass renders the Whites and Blacks rows into the table texture. Textures, passes and bind groups are planned once per frame size. Pipelines build with the rest on the existing thread. - ui-egui: the proxy worker sends Shadows and Highlights frames to the GPU; Dehaze, Texture, Clarity and Detail still use the CPU for the frame. GPU vs CPU at 8, 16 and 32 bits: at most 9.9e-6 (RTX 5060 Ti, Vulkan and DX12), 1.03e-5 (WARP); tests keep 1/4096. 858x572 proxy, release: Shadows +50 8.7 ms (Vulkan) / 10.6 ms (DX12) vs 147-300 ms on the CPU. Part of #6916. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>