Skip to content

Commit c5f67ef

Browse files
authored
Merge pull request #1700 from LykosAI/main
v2.16.2
2 parents 7e76681 + 3581283 commit c5f67ef

81 files changed

Lines changed: 4116 additions & 954 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,57 @@ All notable changes to Stability Matrix will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html).
77

8+
## v2.16.2
9+
> Full technical notes for this release: [docs.lykos.ai/stability-matrix/release-notes/2.16.2](https://docs.lykos.ai/stability-matrix/release-notes/2.16.2)
10+
### Added
11+
- 📚 **New documentation site** at [docs.lykos.ai](https://docs.lykos.ai/stability-matrix/) — getting started and installation guides, package manager and Inference walkthroughs, environment variable and advanced configuration references, a terminology glossary, and troubleshooting for common issues. Written by @NeuralFault!
12+
- Added **OneTrainer** to the native **Windows ROCm (AMD GPU)** helper — new OneTrainer installs on supported AMD hardware get the ROCm PyTorch build, ROCm-aware bitsandbytes and triton dependencies, and the right launch environment applied automatically. New OneTrainer installs also default to Python 3.12 on all platforms - thanks to @NeuralFault!
13+
### Changed
14+
- **Generate now auto-resumes after launching ComfyUI.** If you press Generate in Inference while ComfyUI isn't connected and choose to launch it from the connection prompt, the queued generation now waits for startup and runs on its own once connected - no need to press Generate a second time
15+
- Updated the **Windows ROCm helper**'s bundled bitsandbytes wheel to a build compatible with ROCm 7.13–7.15, so it keeps working as AMD's ROCm Technical Preview builds update - thanks to @NeuralFault!
16+
- CivitAI downloads now pick their destination folder from the file's declared type (**Diffusion Model**/**UNet** → DiffusionModels, **Text Encoder** → TextEncoders, **CLIP Vision** → ClipVision, **ControlNet** → ControlNet, **Upscaler** → upscalers) instead of guessing from the model's name. Name-based guessing remains only for files typed plain "Model", and now recognizes **Krea 2** checkpoints as UNet-only
17+
### Fixed
18+
- Fixed a class of random crashes in the Inference **mask editor** and **image annotation editor** — undo/redo, layer operations, exporting, or closing the editor could free graphics resources that were still being drawn with, occasionally crashing mid-stroke or while saving. Canvas rendering has been restructured so this can't happen
19+
- Fixed **pen pressure** re-widening the whole stroke instead of following the pen while drawing, and mouse-drawn strokes coming back ~25% thicker after saving and reopening a project. Existing project files load exactly as before
20+
- Fixed the mask editor and image annotation editor leaking graphics memory — the paint canvas wasn't released on close, and paint-bucket fills were never freed
21+
- Fixed fast brush strokes occasionally failing with a "collection was modified" error while the stroke was still being drawn
22+
- Fixed opening older projects whose masks contained stroke points outside the canvas failing with an overflow error
23+
- Fixed a potential crash when the paint canvas rendered before its size was set
24+
- Fixed CivitAI models showing an empty Files section with no download links when their files use CivitAI's newer type labels (e.g. **Krea 2 Turbo** and **Z-Image**, typed **Diffusion Model** or **Text Encoder**). All current CivitAI file types are now recognized across the browser, details page, version dialog, bulk download, and installed/update detection
25+
- Fixed CivitAI "Download with Stability Matrix" links saving UNet-only checkpoints (Flux, Wan Video, Hunyuan, Krea 2) into the **StableDiffusion** folder — external links now use the same destination logic as the in-app browser
26+
- Fixed [#1666](https://github.com/LykosAI/StabilityMatrix/issues/1666) - AppImage builds creating a broken `.desktop` entry that never appeared in the application launcher and reverted manual edits on the next launch. AppImage runs now install a proper launcher entry with the app icon, and the running window shows the correct icon in the dock/taskbar (deb/rpm/flatpak installs keep their package-managed entries)
27+
- Fixed `stabilitymatrix://` deep links (e.g. CivitAI "Download with Stability Matrix" buttons) being ignored on Linux AppImage builds
28+
- Fixed [#1668](https://github.com/LykosAI/StabilityMatrix/issues/1668) - the **Output Browser** crashing on open when an output folder contained a broken junction or symlink (a folder whose target no longer exists); those entries are now skipped instead of taking the page down
29+
- Fixed [#1681](https://github.com/LykosAI/StabilityMatrix/issues/1681) - Inference generation with **FaceDetailer** failing instantly with "An item with the same key has already been added" when two installed custom node folders share the same git remote
30+
- Fixed [#1679](https://github.com/LykosAI/StabilityMatrix/issues/1679) - model details pages never showing the **Installed** label, delete button, or version checkmark for files whose type displays as "Unknown". Installed detection now goes by file hash, so it works no matter what type CivitAI reports
31+
- Fixed [#1667](https://github.com/LykosAI/StabilityMatrix/issues/1667) - importing an existing package folder silently pre-selecting **Forge** as the package type, misclassifying re-imported packages. The type is now auto-detected from the folder's git remote
32+
- Fixed [#1669](https://github.com/LykosAI/StabilityMatrix/issues/1669) - **Stable Diffusion WebUI reForge** installing the CUDA build of PyTorch on Linux AMD systems even with ROCm selected
33+
- Fixed [#1672](https://github.com/LykosAI/StabilityMatrix/issues/1672) - **Image Lab** failing with a generic "ComfyUI rejected the workflow" error when generating with a GGUF model while the **ComfyUI-GGUF** extension isn't installed — it now offers the same one-click **install and restart** prompt as Inference
34+
- Fixed GGUF-quantized **text encoders** failing with a ComfyUI error when selected — they now load through the ComfyUI-GGUF CLIP loaders in all Inference workflows and Image Lab (mixed GGUF + safetensors selections work too), with the install prompt appearing if the extension is missing
35+
- Fixed **Chroma** and other single-encoder models being impossible to configure in Inference UNet workflows — the encoder **Type** dropdown was missing `chroma` and other single-encoder types, and the closest option (`flux`) demanded a second encoder these models don't use. The missing types are now listed, and single-encoder types get a single encoder slot
36+
- Fixed GGUF text encoders in the shared **TextEncoders** folder not appearing in the Inference Text Encoder dropdowns while connected to ComfyUI
37+
- Fixed [#1682](https://github.com/LykosAI/StabilityMatrix/issues/1682) - the Linux **AppImage** failing to start on modern distros (Ubuntu 24.04+, Fedora 40+) that no longer ship `libfuse2`. The AppImage now uses a FUSE3-based runtime, and falls back to extract-and-run when FUSE isn't available at all - thanks to @NeuralFault!
38+
- Fixed the Model Browser failing with "CivitAI can't be reached right now (OK: OK)" — CivitAI recently started returning `null` for some model statistics (download counts, ratings), which broke loading the whole page of results. Missing stats are now read as 0
39+
- Fixed [#1695](https://github.com/LykosAI/StabilityMatrix/issues/1695) - models whose CivitAI page has since been deleted showing an error dialog on every click, with no way to break the link:
40+
- The model details page now shows locally cached info instead of a dead page when the CivitAI page is gone
41+
- **Next/Previous** on the details page skip over deleted models instead of getting stuck on an error
42+
- New right-click **Disconnect from Source** action on Checkpoint Manager cards severs the link to the deleted page while keeping the local metadata (name, description, thumbnail, trigger words) — after disconnecting, clicking the card selects it like any other local model
43+
- Fixed **OneTrainer** failing to launch with current upstream versions after its UI script was renamed (`train_ui.py``train_ui_ctk.py`) - thanks to @NeuralFault!
44+
### Performance
45+
- Dragging an image layer with the **Move** tool in the layered mask editor now re-renders only the dragged layer instead of re-compositing every layer on each pointer move, so dragging stays smooth in multi-layer projects
46+
- Faster color-mask extraction for regional prompting — a 1024×1024 canvas with six regions previously did over six million dictionary lookups per extraction
47+
- Fixed a small native memory leak while drawing with the mouse (a path object per frame was never freed), and removed a redundant full-canvas scan after every paint-bucket fill
48+
- The **Checkpoints** and **Outputs** galleries now load thumbnails at display size instead of full resolution, using far less memory and scrolling much more smoothly with large libraries
49+
- The **CivitAI** and **OpenModelDB** browsers now keep card images in memory, so scrolling back over models you've already seen no longer re-loads them from disk
50+
- Lightened the CivitAI model cards so they render faster while scrolling
51+
### Security
52+
- Bundled **ADetailer** model downloads now point at a fixed Hugging Face revision instead of the repository's moving `main` branch, so an upstream re-upload can't change what you get - thanks to @ungrav!
53+
### Supporters
54+
#### 🌟 Visionaries
55+
There's not much glamour in a release like this one: crashes hunted down in the mask editor, downloads finally landing in the folders they belong in, Linux installs that just start. Our Visionaries are the reason we can hand a whole cycle to that kind of work, and to writing the documentation that now lives inside the app. Thank you **Waterclouds**, **MrMxyzptlk12836**, **Psilocyfer18731**, **bluepopsicle**, **Ibixat**, **Droolguy**, **KalAbaddon**, **LG**, **snotty**, **whudunit**, **cusalapapen1481**, and **moon_milky2843** for backing the unglamorous parts as generously as the exciting ones. And a warm welcome to **tarekk071223**, **CC**, and **SnooSnooEternal**, the newest names on this list; it's genuinely good to have you here. 💛
56+
#### 🚀 Pioneers
57+
Our Pioneers hold up the other half of this, and what a steady crew you are: **Szir777**, **[USA]TechDude**, **SinthCore**, **Jisuren**, **Tigon**, **jweg79**, **rwx14662**, **Hurbie53**, **ahnhj.al**, **drew.lukas**, **Tuskaruho**, **Cjloha**, **Alligator1907**, **Bitti**, **Ghislain G**, **CommissarGiygas16050**, **qob97515211**, **bastardofbethlehem**, and **Zombop**, thank you for sticking around release after release. A big hello as well to **Silerae**, **joshsciascia72**, and **rad64741317**, who join the Pioneers this time; we're really happy you're with us. Every fix in this changelog has a bit of all of you behind it. 💛
58+
859
## v2.16.1
960
### Added
1061
- Added **automatic text encoder and VAE selection** to the Inference Model card. Selecting a model now fills any empty encoder slots and the default VAE with the matching local files for the detected workflow, so you don't need to know which files pair with which architecture (e.g. `qwen_3_4b` or `qwen_3_8b` + Flux.2 VAE for Flux.2 Klein, `clip_l` + `t5xxl` for Flux, `qwen_3_06b` + `qwen_image_vae` for Anima). Anything you pick manually is never overridden

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ node("Diligence") {
3939
// - pupnet 1.9.1 globally installed
4040
sh "rm -rf StabilityMatrix.Avalonia/bin/*"
4141
sh "rm -rf StabilityMatrix.Avalonia/obj/*"
42-
sh "/home/jenkins/.dotnet/tools/pupnet -r linux-x64 -c Release --kind appimage --app-version $RELEASE_VERSION --clean"
42+
sh "/home/jenkins/.dotnet/tools/pupnet -r linux-x64 -c Release --kind appimage --app-version ${version} --clean -y"
4343
}
4444
}
4545
} finally {

StabilityMatrix.Avalonia/App.axaml.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,12 @@ private void Setup()
366366
// Setup uri handler for `stabilitymatrix://` protocol
367367
Program.UriHandler.RegisterUriScheme();
368368

369+
// Write a correct .desktop entry for AppImage runs so the app appears in the launcher
370+
if (Compat.IsLinux)
371+
{
372+
LinuxDesktopIntegration.CreateDesktopFile();
373+
}
374+
369375
// Setup activation protocol handlers (uri handler on macOS)
370376
if (Compat.IsMacOS && this.TryGetFeature<IActivatableLifetime>() is { } activatableLifetime)
371377
{

StabilityMatrix.Avalonia/Assets/sitecustomize.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ def is_terminal(self) -> bool:
6565
except ImportError:
6666
pass
6767
except Exception as e:
68-
print("[sitecustomize error]:", e)
69-
68+
print("[sitecustomize error]:", e, file=sys.stderr)
69+
7070
try:
7171
from pip._vendor.rich import console
7272

@@ -79,19 +79,19 @@ def is_terminal(self) -> bool:
7979
except ImportError:
8080
pass
8181
except Exception as e:
82-
print("[sitecustomize error]:", e)
82+
print("[sitecustomize error]:", e, file=sys.stderr)
8383

8484
# Patch tqdm to use stdout instead of stderr
8585
def _patch_tqdm():
8686
try:
8787
import sys
8888
from tqdm import std
89-
89+
9090
sys.stderr = sys.stdout
9191
except ImportError:
9292
pass
9393
except Exception as e:
94-
print("[sitecustomize error]:", e)
94+
print("[sitecustomize error]:", e, file=sys.stderr)
9595

9696
# Run startup customizations. Each is isolated so that a failure in one (or an
9797
# unusual host environment, e.g. an interpreter probe with no real stdio) can
@@ -101,7 +101,7 @@ def _run_safely(func):
101101
func()
102102
except Exception as e:
103103
try:
104-
print("[sitecustomize error]:", e)
104+
print("[sitecustomize error]:", e, file=sys.stderr)
105105
except Exception:
106106
pass
107107

StabilityMatrix.Avalonia/Controls/ImageLoaders.cs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,35 +15,35 @@ internal static class ImageLoaders
1515
{
1616
private static string BaseFileCachePath => Path.Combine(Path.GetTempPath(), "StabilityMatrix", "Cache");
1717

18-
private static readonly Lazy<MemoryImageCache> OutputsPageImageCacheLazy =
19-
new(
20-
() => new MemoryImageCache { MaxMemoryCacheCount = 64 },
21-
LazyThreadSafetyMode.ExecutionAndPublication
22-
);
18+
private static readonly Lazy<MemoryImageCache> OutputsPageImageCacheLazy = new(
19+
() => new MemoryImageCache { MaxMemoryCacheCount = 64 },
20+
LazyThreadSafetyMode.ExecutionAndPublication
21+
);
2322

2423
public static IImageCache OutputsPageImageCache => OutputsPageImageCacheLazy.Value;
2524

26-
private static readonly Lazy<ImageCache> OpenModelDbImageCacheLazy =
27-
new(
28-
() =>
29-
new ImageCache(
30-
new CacheOptions
25+
private static readonly Lazy<ImageCache> OpenModelDbImageCacheLazy = new(
26+
() =>
27+
new ImageCache(
28+
new CacheOptions
29+
{
30+
BaseCachePath = BaseFileCachePath,
31+
CacheFolderName = "OpenModelDbImageCache",
32+
CacheDuration = TimeSpan.FromDays(1),
33+
// Keep decoded bitmaps in memory so scrolling doesn't re-decode from disk each time.
34+
MaxMemoryCacheCount = 96,
35+
HttpClient = new HttpClient(NetCache.Background)
3136
{
32-
BaseCachePath = BaseFileCachePath,
33-
CacheFolderName = "OpenModelDbImageCache",
34-
CacheDuration = TimeSpan.FromDays(1),
35-
HttpClient = new HttpClient(NetCache.Background)
37+
DefaultRequestHeaders =
3638
{
37-
DefaultRequestHeaders =
38-
{
39-
UserAgent = { new ProductInfoHeaderValue("StabilityMatrix", "2.0") },
40-
Referrer = new Uri("https://openmodelsdb.info/"),
41-
}
42-
}
43-
}
44-
),
45-
LazyThreadSafetyMode.ExecutionAndPublication
46-
);
39+
UserAgent = { new ProductInfoHeaderValue("StabilityMatrix", "2.0") },
40+
Referrer = new Uri("https://openmodelsdb.info/"),
41+
},
42+
},
43+
}
44+
),
45+
LazyThreadSafetyMode.ExecutionAndPublication
46+
);
4747

4848
public static IImageCache OpenModelDbImageCache => OpenModelDbImageCacheLazy.Value;
4949
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Threading;
4+
5+
namespace StabilityMatrix.Avalonia.Controls.Models;
6+
7+
/// <summary>
8+
/// An in-progress stroke being drawn by the user. Unlike a finalized <see cref="PenPath"/>,
9+
/// a live stroke is written by the UI thread (pointer events appending points) while the
10+
/// compositor render thread concurrently reads it every frame.
11+
/// </summary>
12+
/// <remarks>
13+
/// Thread safety comes from copy-on-append publication rather than locks: points live in an
14+
/// array that is never mutated after it becomes visible to readers. Appending copies the
15+
/// current array into a larger one and publishes it with a single
16+
/// <see cref="Volatile.Write{T}(ref T, T)"/>, so a reader always observes a fully written,
17+
/// stable snapshot — there is no window where a resize or in-place write can tear a read.
18+
/// Writes must come from a single thread (the UI thread); reads may come from any thread.
19+
/// </remarks>
20+
public sealed class LiveStroke
21+
{
22+
private PenPoint[] points = [];
23+
24+
/// <summary>
25+
/// Immutable stroke metadata (color, radius, feathering, shape bounds, etc.).
26+
/// The template's own <see cref="PenPath.Points"/> list is unused and stays empty;
27+
/// live points are tracked by this class instead.
28+
/// </summary>
29+
public required PenPath Template { get; init; }
30+
31+
/// <summary>
32+
/// Returns a stable snapshot of the points recorded so far. The returned array is
33+
/// never mutated — callers may iterate it freely on any thread.
34+
/// </summary>
35+
public PenPoint[] GetPointsSnapshot() => Volatile.Read(ref points);
36+
37+
/// <summary>
38+
/// Appends points to the stroke. Must only be called from the single writer (UI) thread.
39+
/// </summary>
40+
public void AddPoints(ReadOnlySpan<PenPoint> newPoints)
41+
{
42+
if (newPoints.IsEmpty)
43+
return;
44+
45+
// Single-writer: no other thread mutates `points`, so a plain read is sufficient here.
46+
var current = points;
47+
var next = new PenPoint[current.Length + newPoints.Length];
48+
current.AsSpan().CopyTo(next);
49+
newPoints.CopyTo(next.AsSpan(current.Length));
50+
51+
// Release-publish: the array contents above are guaranteed visible to any thread
52+
// that observes the new reference.
53+
Volatile.Write(ref points, next);
54+
}
55+
56+
/// <summary>
57+
/// Snapshots this live stroke into a finalized, fully independent <see cref="PenPath"/>.
58+
/// </summary>
59+
public PenPath ToPenPath() => Template with { Points = [.. GetPointsSnapshot()] };
60+
61+
/// <summary>
62+
/// Creates a live stroke from a previously serialized <see cref="PenPath"/>.
63+
/// </summary>
64+
public static LiveStroke FromPenPath(PenPath path)
65+
{
66+
var stroke = new LiveStroke { Template = path with { Points = [] } };
67+
stroke.AddPoints(CollectionsMarshal.AsSpan(path.Points));
68+
return stroke;
69+
}
70+
}

0 commit comments

Comments
 (0)