Commit Graph
1974 Commits
Author SHA1 Message Date
aiongg c2155326d6 Merge PR #2942: Issue #2936: build the GPU kernels on parallel threads 2026-10-31 02:11:04 +00:00
aiongg c9c69ddd4c Merge PR #2919: PERF-WINDOW: the window queues one frame, not two (eframe's low-latency surface)
# Conflicts:
#	docs/whats-new.md
2026-10-31 02:11:01 +00:00
aiongg 5062acc601 Merge PR #2421: fix(windows): add opt-in DirectComposition workaround for VRR flicker
apps/lightcraft/src/main.rs: kept main's split; hunks ported (clear_color, compose_window, with_transparent); test moved to tests.rs
crates/ui-egui/src/panels/settings.rs: deleted on main; checkbox ported to dialogs/settings/performance.rs
crates/ui-egui/src/state.rs: compose_window field and default ported to state/settings.rs
crates/ui-egui/locales/*.json: main's file plus the new key
docs/gaps.md, docs/parity-checklist.md: main's header and rows plus the PR's additions; duplicated header line and blank lines dropped
2026-10-31 02:10:21 +00:00
aiongg 866ed3846c Merge PR #3385: Never crash: a mask id at the u32 limit doesn't overflow the next mask's id
# Conflicts:
#	docs/whats-new.md
2026-10-31 02:09:14 +00:00
aiongg ac36428e6d Merge PR #3384: LR-MASK-OBJECTS: a SAM 3 checkpoint in Meta's original format is named as such, not as an unsupported dtype (#3378)
# Conflicts:
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:09:05 +00:00
aiongg 9b748af445 Merge PR #3379: LR-MASK-COLORRANGE: a colour-range mask keeps at most 64 samples however it is loaded (#2556)
# Conflicts:
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:08:39 +00:00
aiongg 856b3c46fc Merge PR #3323: LR-MASK-PINS: Object and Describe masks show a pin that selects them (#3049)
# Conflicts:
#	docs/whats-new.md
2026-10-31 02:08:24 +00:00
aiongg 9e732c2233 Merge PR #3298: Issue #3272: AI masks are enlarged along the photo's edges, no outline under a raised Exposure
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-31 02:08:02 +00:00
aiongg 27c4692dcd Merge PR #2639: LR-MASK-BRUSH: with the mask overlay hidden, the stroke being painted no longer tints the photo (#2549)
crates/ui-egui/src/panels/detail.rs: kept main's split; hunk ported to panels/detail/masks.rs
docs/parity-checklist.md: header and LR-MASK-BRUSH row carry both sides
2026-10-31 02:07:39 +00:00
aiongg 01c0b1e274 Merge PR #1654: Bound interpolation for extreme brush segments
# Conflicts:
#	docs/gaps.md
#	docs/parity-checklist.md
2026-10-31 02:06:52 +00:00
Brandon Thomas cfdf63c6e4 Merge PR #2917
# Conflicts:
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-30 15:24:59 -04:00
Brandon Thomas 13711ace2b Merge PR #2155 2026-10-30 15:24:41 -04:00
Brandon Thomas 7e8bf5cd9e Merge PR #2831 2026-10-30 15:24:41 -04:00
Brandon Thomas ddbc218ad1 Merge PR #3213
# Conflicts:
#	docs/parity-checklist.md
2026-10-30 15:24:40 -04:00
Bruno-Alumn bc12ec8e40 Never crash: a mask id at the u32 limit doesn't overflow the next mask's id
Mask ids come unchecked from develop.merge, sidecars (lc:settings) and
pastes. With a mask id of u32::MAX, next_mask_id() and Preset::apply
added 1 to it: debug builds panicked, release builds wrapped to 0, so
the second new mask got the same id as the first.

next_mask_id() now falls back to the lowest id no mask uses when the
highest is at the limit, and Preset::apply takes each preset mask's id
from it instead of counting on its own, so mask.add, mask.brushStroke,
mask.duplicate and presets with masks all get unused ids.
2026-10-30 13:31:01 +01:00
Bruno-Alumn cfbd109534 LR-MASK-OBJECTS: a SAM 3 checkpoint in Meta's original format is named as such, not as an unsupported dtype (#3378)
The sam3.safetensors on community mirrors (AEmotionStudio/sam3,
1038lab/sam3) is a conversion of Meta's original sam3.pt: its tensors
keep Meta's names, and its RoPE tables are C64. Renamed to
model.safetensors, it failed to load with "unsupported dtype
Some("C64")", which read like a LightCraft limitation.

Weights::open now lists a tensor of another dtype instead of failing
the whole file; reading it fails with the dtype error (LightCraft
computes RoPE itself and never reads those tables). Sam3::load_on then
checks the format: when the backbone's first tensor in Hugging Face
naming is missing and the file has Meta's detector.backbone. or
tracker. tensors, the error says it is Meta's original checkpoint and
that model.safetensors from facebook/sam3 in the Hugging Face format
is needed. docs/ai-masks.md says so for installing by hand.
2026-10-30 13:25:37 +01:00
Bruno-Alumn 06e2ec43ba LR-MASK-COLORRANGE: a colour-range mask keeps at most 64 samples however it is loaded (#2556)
Render cost is pixels x samples (CPU and GPU), and only mask.add / mask.update capped the list, so a
sidecar's lc:settings, a preset, develop.merge, render --settings or a catalog / history load could
carry thousands and stall a render or lose the GPU device. MAX_COLOR_RANGE_SAMPLES moves to
lightcraft-develop and ColorRange::samples deserializes through a capped visitor (the first 64 in
order, the rest skipped as IgnoredAny); the CPU and GPU renders also take at most 64 for settings
built in code.
2026-10-30 12:03:03 +01:00
Bruno-Alumn cb841a3fe1 LR-MASK-PINS: with the Object tool on, a click on the selected mask's own pin adds no Object click (#3049) 2026-10-30 02:13:07 +01:00
Bruno-Alumn 7174891939 LR-MASK-PINS: with the Object tool on, a click on another mask's pin selects it (#3049) 2026-10-29 23:05:20 +01:00
Bruno-Alumn 63b7d0766e LR-MASK-PINS: Object and Describe masks show a pin that selects them (#3049)
With Show Pins on, Object and Describe masks had no pin on the photo, so they could only be picked in the Masking panel. An Object component's pin now sits at its first click and a Describe component's in the middle of what its segmentation selected. Clicking the pin selects the mask; dragging it changes nothing and adds no History step. Subject, Sky, Background, People, Landscape and the range masks still have no pin.
2026-10-29 15:04:47 +01:00
eliets2 6a7a6fa3cf docs: trim the brush note to what the change does
The gap 24 row, the change-log line and the two document headers now say only
that an extreme brush segment skips its intermediate dabs. They no longer claim
live preview, edge refinement or a mask test count, and the headers no longer
carry the unrelated gap 15 and print-page entries.
2026-10-29 13:59:18 +02:00
eliets2 bf8b5e3584 LR-MASK-BRUSH: skip the interpolation of extreme brush segments
push_dabs clamped the number of intermediate dabs of one brush segment to 1,000,000, so a
finite but extreme segment (a point 10,000,000 px away) still allocated a million dabs. A
segment that would need more than that many now keeps only its endpoints; ordinary
spacing and the segment's end point are unchanged.

Adds oversized_brush_segments_skip_intermediate_dabs, which checks both the extreme case
(2 dabs) and an ordinary feathered-brush segment (21 dabs, end point kept, spacing kept).
The docs record the fix under gap 24 and LR-MASK-BRUSH; the parity status stays partial.
2026-10-29 13:57:51 +02:00
Brain WangandClaude Opus 5.5 f14d166fdf Issue #3272: AI masks are enlarged along the photo's edges, no outline under a raised Exposure
An Object / Describe mask is stored as a model's logit grid (288² over the whole photo,
~20 px cells on a 24 MP export) and was enlarged by bilinear sampling alone, so its edge
spilled 1–2 px onto the background; raising the mask's Exposure turned that strip into a
bright outline in previews and exports (CPU and GPU: the GPU renderer evaluates these
shapes with the same CPU `shape_alpha`).

`sample_seg` now guided-filters the sampled logits by the photo's log luminance where the
grid is coarser than the output: the fast (subsampled) guided filter, a window of 1.5 grid
cells, so a preview and an export put the edge in the same place. Filtering logits, not
coverage, lets the confident side win (the spill goes to ≈ 0, not to a mean of ≈ 0.1).
Pixels whose window is all inside or all outside, and edges the photo has no contrast
across, keep the plain sample exactly. Refine Edges still runs afterwards on the combined
mask and finds the edges in place: no second halo, no tightening.

One implementation: `guided_cross` (Refine Edges, Auto Mask) and the new
`guided_cross_fast` share `guided_coeffs`; the subsampled form uses
`local::guided_fast_step` and a box `resize`, like `local::guided_fast`. `guided_cross`'s
output is unchanged.

Existing AI masks become 1–2 px tighter at a subject's edges, on every process; their
inside, outside and contrast-less edges are unchanged. This lands in place under the
bug-fix rule of docs/process-versions.md (output that is in neither the photo nor the
edit), noted there.

Cost per AI selection (M2 Pro, 12 cores; one shape_alpha, before → after):
24 MP 25.7 → 48.2 ms, heap peak 96.5 → 108.8 MB; 60 MP 64.1 → 109.9 ms, 239.9 → 256.7 MB;
2.7 MP preview 3.1 → 10.6 ms, 11.2 → 26.5 MB.

Tests (a dark disc on a light background, its mask on a 32² grid): ≈ 0 one and two px
outside and ≈ 1 inside, all around (1 px outside was 0.66), bit-identical away from the
edge; with Refine Edges 50 / 100 (was 0.29 outside) and the edge within 1 px of the
unrefined one; the same edge position at 256, 512 and 1024 px; a Prompt mask's window
matches the whole render.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 11:13:04 +08:00
radialmonsterandClaude Opus 5.5 6188590675 Docs: link gap 8 and roadmap priority 7 to lens profile issue #329
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014ti8KemZbjE2ZgHgV1q1BM
2026-10-28 13:58:49 -04:00
Nathaniel Ledford e60b7d1787 MENU-EDIT-SELECTNONE: Edit lists Select Only Active Photo and Paste Settings from Previous with their kin, and the native Edit menu keeps single separators 2026-10-27 22:50:05 -04:00
Nathaniel Ledford 4f6f4c4ee8 MENU-FILE-CLOSE: the page says saving at quit can fail 2026-10-27 19:53:43 -04:00
Nathaniel Ledford e472ffd6a4 MENU-FILE-CLOSE: document that closing the window quits the app 2026-10-27 18:29:56 -04:00
Jeremy 5dea67e348 docs(installer): say that an upgrade reuses the recorded folder even if it was deleted
The restore actions use the recorded folder without checking that it still
exists, so an upgrade creates it again rather than using the default folder.
2026-10-27 21:13:30 +00:00
Jeremy 51ecbfece8 docs(installer): note that the 32-bit all-users folder is Program Files (x86); tidy wording 2026-10-27 12:25:19 +00:00
Jeremy 3d40cf08e7 docs(installer): describe the per-user default install location and scope 2026-10-27 12:09:03 +00:00
aiongg 69048937d0 docs: update source paths after the layout moves 2026-10-26 21:39:56 +00:00
softwaregames1andClaude Opus 5.5 22b963f262 Merge storytold/lightcraft main into LR-FILT-SEARCH-META
Conflict only in the docs/parity-checklist.md "Last updated" line: upstream's
line kept, with the LR-FILT-SEARCH-META entry added in front.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqKgSkHi5MfTQFrZvDKBjm
Co-authored-by: softwaregames1 <167585946+softwaregames1@users.noreply.github.com>
2026-10-26 12:25:52 +00:00
aiongg 21a53cf61f Merge title-bar-movable (lightcraft#2930) into docking-adoption; every craft-libs crate at craft-libs main 1e6f127 2026-10-26 02:20:20 +00:00
aiongg 1952d4fd3c Merge upstream main into docking-adoption 2026-10-26 02:18:38 +00:00
aiongg 003779ce51 Merge upstream main into title-bar-movable; craft-window at craft-libs main 1e6f127 2026-10-26 02:18:22 +00:00
Dylan M. Taylor 8020cd081c showcase: check the file is readable without an empty with-block (#3001) 2026-10-25 21:13:45 -04:00
Michael Anderson ab3f6af82a Merge remote-tracking branch 'origin/main' into fix/2119-erf-mef-strip-length
# Conflicts:
#	crates/raw/src/vendor/mef.rs
2026-10-25 19:20:01 -05:00
aiongg 672baaea46 Merge lightcraft#2913 (egui 0.37) into docking-adoption; craft-ui and craft-docpath at craft-libs main a091680 2026-10-25 17:36:59 +00:00
aiongg c01d4c7074 Merge lightcraft#2913 (egui 0.37) into title-bar-movable; craft-window at craft-libs main a091680 2026-10-25 17:19:47 +00:00
aiongg d4cfd2e6d5 LR-BEHAV-TITLEBAR: the checklist row follows craft-window's title_bar 2026-10-25 17:07:16 +00:00
Ingmar LübbeandClaude Opus 5.5 1ada7c2af0 Issue #2936: gpu-pipeline.md says what is measured about the remaining kernel time
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QWU3BMJMENFqFqxDHzV3b
2026-10-25 16:39:14 +01:00
Ingmar LübbeandClaude Opus 5.5 fa4bccff64 Issue #2936: build the GPU kernels on parallel threads
Gpu::new built the 27 compute pipelines one after another. On DX12 each one is compiled by FXC
(issue #471), single-threaded, inside create_compute_pipeline, so every process waited ~2.2 s for
them on an Intel Core Ultra 7 165U iGPU (app.gpu 2.4 s median) while the other cores idled.

build_kernels creates the shader modules and layouts on the calling thread and shares the pipelines
out to worker threads (std::thread::scope, an atomic job counter; the calling thread works too, so
every kernel is built even when no thread can be started). wgpu's error scopes are per thread, so
each worker pushes its own validation and internal scopes: a refused kernel or a panicked worker
still means no GPU, never a half-built one. app.gpu: 2.4 s -> 1.2 s median on that machine, exports
pixel-identical. The gpu: info line now reports the kernel count and build time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018QWU3BMJMENFqFqxDHzV3b
2026-10-25 16:38:12 +01:00
skylar taylor-barrick c627ce7210 egui-037: preserve modal input ownership and packaged font notices 2026-10-25 13:14:34 +01:00
Jason LukerandClaude Opus 5.5 2dd02f6f97 PERF-WINDOW: the window queues one frame, not two (eframe's low-latency surface)
window_gpu::base_options() built the window's wgpu options from
egui_wgpu::WgpuConfiguration::default(), which is egui-wgpu's HIGH_THROUGHPUT
surface (desired_maximum_frame_latency 2; three drawables on Metal), not
eframe's default. eframe's NativeOptions::default() uses LOW_LATENCY
(latency 1). The window had eframe's default until #136 started building
the options by hand to choose the backends.

Start from eframe::NativeOptions::default().wgpu_options and change only
the backends, the DX12 compiler and the instance flags, as before. The
probed Windows configurations are built on the same options.

Measured on an M2 Max at 120 Hz (Metal System Trace, heavy develop drag,
presents joined to WindowServer's reads of the same IOSurface): the window
cycles 2 drawables instead of 3, and a frame reaches the compositor about
8.3 ms (one frame) sooner, 9.5-10.6 ms instead of 17.9-18.9 ms after it is
presented, at the same ~119 frames a second.

Test: window_gpu::tests::window_surface_keeps_one_frame_in_flight (fails
on the old options: latency Some(2) instead of Some(1)).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 02:19:57 -07:00
Claude 8fe7198dbd LR-FILT-SEARCH-META: >= and <= in fielded search tokens
`rating:>=3`, `iso:<=400`, `f:>=2.8` read the `=` as part of the number, the
parse failed, and the token silently matched no photo. Parse the two-character
operators first and compare inclusively; `>`, `<`, `=` and bare numbers are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SqKgSkHi5MfTQFrZvDKBjm
2026-10-25 08:47:10 +00:00
skylartaylor e7144adc1f M0.37: reconcile current LightCraft main and qualify the migration 2026-10-25 07:47:22 +01:00
aiongg 7291abdc14 Merge upstream main into docking-adoption 2026-10-25 05:55:03 +00:00
aiongg 31ec62cd03 Info panel Target Photo edits, Add Keywords cursor request and Fixed keys follow-ups (#2889)
* LR-PREF-SHORTCUTS: the shortcuts panel's Fixed keys ignore keys saved for unknown commands

* KEYC-METADATA: an Add Keywords request the Keywords panel can't take in time expires

* LR-META-INFO: Target Photo saves an Info edit to the photo it shows
2026-10-25 00:58:10 -04:00
aiongg c3feda15c0 LR-META-INFO: the Info panel shows Selected Photos by default; gaps.md lists its change notes once 2026-10-25 03:36:14 +00:00
aiongg e339afc263 Merge PR #2810: LR-META-INFO: the Info panel can show metadata for the selected photos 2026-10-25 02:25:16 +00:00