Skip to content

Commit ce562f1

Browse files
authored
Merge branch 'dev' into new-civit-browser
2 parents eed9572 + d4277ce commit ce562f1

17 files changed

Lines changed: 396 additions & 85 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,20 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2
1212
- Added setting for Inference dimension step change - the value the dimensions increase or decrease by when using the step buttons or scroll wheel in Inference
1313
- Added "Install Nunchaku" option to the ComfyUI Package Commands menu
1414
- Added "Select All" button to the Installed Extensions page
15+
- Added experimental ROCm pytorch install for ComfyUI (non-Zluda) on Windows - requires a compatible AMD GPU
1516
### Changed
1617
- Redesigned Civitai model details page
1718
- You can now select release versions when installing ComfyUI
1819
- You can no longer select branches when installing InvokeAI
1920
- Updated InvokeAI install to use pinned torch index from release tag
2021
- Updated ComfyUI installs for AMD users on Linux to use the latest rocm6.3 torch index
22+
- Updated ComfyUI-Zluda installs to use the newer install-n method (fixes [#1347](https://github.com/LykosAI/StabilityMatrix/issues/1347))
23+
- Updated uv to 0.8.4
24+
- Removed disclaimer from reForge since the author is now active again
2125
### Fixed
2226
- Fixed Civitai-generated image parsing in Inference
27+
- Fixed some first-time setup crashes from missing prerequisites
28+
- Fixed one-click installer not using default preferred Python version
2329

2430
## v2.15.0-dev.2
2531
### Added

StabilityMatrix.Avalonia/Helpers/UnixPrerequisiteHelper.cs

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,16 @@ namespace StabilityMatrix.Avalonia.Helpers;
2727
public class UnixPrerequisiteHelper(
2828
IDownloadService downloadService,
2929
ISettingsManager settingsManager,
30-
IPyRunner pyRunner
30+
IPyRunner pyRunner,
31+
IPyInstallationManager pyInstallationManager
3132
) : IPrerequisiteHelper
3233
{
3334
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
3435

3536
private const string UvMacDownloadUrl =
36-
"https://github.com/astral-sh/uv/releases/download/0.7.19/uv-aarch64-apple-darwin.tar.gz";
37+
"https://github.com/astral-sh/uv/releases/download/0.8.4/uv-aarch64-apple-darwin.tar.gz";
3738
private const string UvLinuxDownloadUrl =
38-
"https://github.com/astral-sh/uv/releases/download/0.7.19/uv-x86_64-unknown-linux-gnu.tar.gz";
39+
"https://github.com/astral-sh/uv/releases/download/0.8.4/uv-x86_64-unknown-linux-gnu.tar.gz";
3940

4041
private DirectoryPath HomeDir => settingsManager.LibraryDir;
4142
private DirectoryPath AssetsDir => HomeDir.JoinDir("Assets");
@@ -81,7 +82,7 @@ private bool IsPythonVersionInstalled(PyVersion version) =>
8182
private string UvExtractPath => Path.Combine(AssetsDir, "uv");
8283
public string UvExePath => Path.Combine(UvExtractPath, "uv");
8384
public bool IsUvInstalled => File.Exists(UvExePath);
84-
private string ExpectedUvVersion => "0.7.19";
85+
private string ExpectedUvVersion => "0.8.4";
8586

8687
// Helper method to get Python download URL for a specific version
8788
private RemoteResource GetPythonDownloadResource(PyVersion version)
@@ -105,30 +106,38 @@ private async Task<bool> CheckIsGitInstalled()
105106
return isGitInstalled == true;
106107
}
107108

108-
public Task InstallPackageRequirements(BasePackage package, IProgress<ProgressReport>? progress = null) =>
109-
InstallPackageRequirements(package.Prerequisites.ToList(), progress);
109+
public Task InstallPackageRequirements(
110+
BasePackage package,
111+
PyVersion? pyVersion = null,
112+
IProgress<ProgressReport>? progress = null
113+
) => InstallPackageRequirements(package.Prerequisites.ToList(), pyVersion, progress);
110114

111115
public async Task InstallPackageRequirements(
112116
List<PackagePrerequisite> prerequisites,
117+
PyVersion? pyVersion = null,
113118
IProgress<ProgressReport>? progress = null
114119
)
115120
{
116121
await UnpackResourcesIfNecessary(progress);
122+
await InstallUvIfNecessary(progress);
117123

118124
if (prerequisites.Contains(PackagePrerequisite.Python310))
119125
{
120126
await InstallPythonIfNecessary(PyInstallationManager.Python_3_10_11, progress);
121127
await InstallVirtualenvIfNecessary(PyInstallationManager.Python_3_10_11, progress);
122128
}
123129

124-
if (prerequisites.Contains(PackagePrerequisite.Python31017))
130+
if (pyVersion is not null)
125131
{
126-
await InstallPythonIfNecessary(PyInstallationManager.Python_3_10_17, progress);
127-
await InstallVirtualenvIfNecessary(PyInstallationManager.Python_3_10_17, progress);
132+
if (!await EnsurePythonVersion(pyVersion.Value))
133+
{
134+
throw new MissingPrerequisiteException(
135+
@"Python",
136+
@$"Python {pyVersion} was not found and/or failed to install. Please check the logs for more details."
137+
);
138+
}
128139
}
129140

130-
await InstallUvIfNecessary(progress);
131-
132141
if (prerequisites.Contains(PackagePrerequisite.Git))
133142
{
134143
await InstallGitIfNecessary(progress);
@@ -186,7 +195,6 @@ public async Task InstallAllIfNecessary(IProgress<ProgressReport>? progress = nu
186195
{
187196
await UnpackResourcesIfNecessary(progress);
188197
await InstallPythonIfNecessary(PyInstallationManager.Python_3_10_11, progress);
189-
await InstallPythonIfNecessary(PyInstallationManager.Python_3_10_17, progress);
190198
await InstallUvIfNecessary(progress);
191199
}
192200

@@ -686,6 +694,12 @@ private async Task<string> GetInstalledUvVersionAsync()
686694
}
687695
}
688696

697+
private async Task<bool> EnsurePythonVersion(PyVersion pyVersion)
698+
{
699+
var result = await pyInstallationManager.GetInstallationAsync(pyVersion);
700+
return result.Exists();
701+
}
702+
689703
[UnsupportedOSPlatform("Linux")]
690704
[UnsupportedOSPlatform("macOS")]
691705
public Task InstallTkinterIfNecessary(IProgress<ProgressReport>? progress = null)

StabilityMatrix.Avalonia/Helpers/WindowsPrerequisiteHelper.cs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ IPyInstallationManager pyInstallationManager
4949
private const string PythonLibsDownloadUrl = "https://cdn.lykos.ai/python_libs_for_sage.zip";
5050

5151
private const string UvWindowsDownloadUrl =
52-
"https://github.com/astral-sh/uv/releases/download/0.7.19/uv-x86_64-pc-windows-msvc.zip";
52+
"https://github.com/astral-sh/uv/releases/download/0.8.4/uv-x86_64-pc-windows-msvc.zip";
5353

5454
private string HomeDir => settingsManager.LibraryDir;
5555

@@ -115,7 +115,7 @@ private string GetPythonLibraryZipPath(PyVersion version) =>
115115
private string UvExtractPath => Path.Combine(AssetsDir, "uv");
116116
public string UvExePath => Path.Combine(UvExtractPath, "uv.exe");
117117
public bool IsUvInstalled => File.Exists(UvExePath);
118-
private string ExpectedUvVersion => "0.7.19";
118+
private string ExpectedUvVersion => "0.8.4";
119119

120120
public string GitBinPath => Path.Combine(PortableGitInstallDir, "bin");
121121
public bool IsVcBuildToolsInstalled => Directory.Exists(VcBuildToolsExistsPath);
@@ -191,8 +191,11 @@ public async Task RunNpm(
191191
onProcessOutput?.Invoke(ProcessOutput.FromStdErrLine(result.StandardError));
192192
}
193193

194-
public Task InstallPackageRequirements(BasePackage package, IProgress<ProgressReport>? progress = null) =>
195-
InstallPackageRequirements(package.Prerequisites.ToList(), progress);
194+
public Task InstallPackageRequirements(
195+
BasePackage package,
196+
PyVersion? pyVersion = null,
197+
IProgress<ProgressReport>? progress = null
198+
) => InstallPackageRequirements(package.Prerequisites.ToList(), pyVersion, progress);
196199

197200
public async Task InstallUvIfNecessary(IProgress<ProgressReport>? progress = null)
198201
{
@@ -245,6 +248,7 @@ public async Task InstallUvIfNecessary(IProgress<ProgressReport>? progress = nul
245248

246249
public async Task InstallPackageRequirements(
247250
List<PackagePrerequisite> prerequisites,
251+
PyVersion? pyVersion = null,
248252
IProgress<ProgressReport>? progress = null
249253
)
250254
{
@@ -262,6 +266,17 @@ public async Task InstallPackageRequirements(
262266
await InstallVirtualenvIfNecessary(PyInstallationManager.Python_3_10_11, progress);
263267
}
264268

269+
if (pyVersion is not null)
270+
{
271+
if (!await EnsurePythonVersion(pyVersion.Value))
272+
{
273+
throw new MissingPrerequisiteException(
274+
@"Python",
275+
@$"Python {pyVersion} was not found and/or failed to install. Please check the logs for more details."
276+
);
277+
}
278+
}
279+
265280
if (prerequisites.Contains(PackagePrerequisite.Git))
266281
{
267282
await InstallGitIfNecessary(progress);
@@ -287,10 +302,10 @@ public async Task InstallPackageRequirements(
287302
await InstallTkinterIfNecessary(PyInstallationManager.Python_3_10_11, progress);
288303
}
289304

290-
if (prerequisites.Contains(PackagePrerequisite.VcBuildTools))
291-
{
292-
await InstallVcBuildToolsIfNecessary(progress);
293-
}
305+
// if (prerequisites.Contains(PackagePrerequisite.VcBuildTools))
306+
// {
307+
// await InstallVcBuildToolsIfNecessary(progress);
308+
// }
294309
}
295310

296311
public async Task InstallAllIfNecessary(IProgress<ProgressReport>? progress = null)
@@ -1051,4 +1066,10 @@ private async Task<string> GetInstalledUvVersionAsync()
10511066
return string.Empty;
10521067
}
10531068
}
1069+
1070+
private async Task<bool> EnsurePythonVersion(PyVersion pyVersion)
1071+
{
1072+
var result = await pyInstallationManager.GetInstallationAsync(pyVersion);
1073+
return result.Exists();
1074+
}
10541075
}

StabilityMatrix.Avalonia/ViewModels/Dialogs/NewOneClickInstallViewModel.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,12 @@ private async Task InstallPackage(BasePackage selectedPackage)
115115
OnPrimaryButtonClick();
116116

117117
var installLocation = Path.Combine(settingsManager.LibraryDir, "Packages", selectedPackage.Name);
118+
var recommendedPython = selectedPackage.RecommendedPythonVersion;
118119

119120
var steps = new List<IPackageStep>
120121
{
121122
new SetPackageInstallingStep(settingsManager, selectedPackage.Name),
122-
new SetupPrerequisitesStep(
123-
prerequisiteHelper,
124-
selectedPackage,
125-
PyInstallationManager.Python_3_10_17
126-
)
123+
new SetupPrerequisitesStep(prerequisiteHelper, selectedPackage, recommendedPython),
127124
};
128125

129126
// get latest version & download & install
@@ -160,7 +157,8 @@ private async Task InstallPackage(BasePackage selectedPackage)
160157
LastUpdateCheck = DateTimeOffset.Now,
161158
PreferredTorchIndex = torchVersion,
162159
PreferredSharedFolderMethod = recommendedSharedFolderMethod,
163-
PythonVersion = PyInstallationManager.Python_3_10_17.StringValue
160+
UseSharedOutputFolder = selectedPackage.SharedOutputFolders is { Count: > 0 },
161+
PythonVersion = recommendedPython.StringValue,
164162
};
165163

166164
var downloadStep = new DownloadPackageVersionStep(
@@ -181,7 +179,7 @@ private async Task InstallPackage(BasePackage selectedPackage)
181179
{
182180
SharedFolderMethod = recommendedSharedFolderMethod,
183181
VersionOptions = downloadVersion,
184-
PythonOptions = { TorchIndex = torchVersion }
182+
PythonOptions = { TorchIndex = torchVersion, PythonVersion = recommendedPython },
185183
}
186184
);
187185
steps.Add(installStep);
@@ -203,7 +201,7 @@ private async Task InstallPackage(BasePackage selectedPackage)
203201
{
204202
ShowDialogOnStart = false,
205203
HideCloseButton = false,
206-
ModificationCompleteMessage = $"{selectedPackage.DisplayName} installed successfully"
204+
ModificationCompleteMessage = $"{selectedPackage.DisplayName} installed successfully",
207205
};
208206

209207
runner

StabilityMatrix.Avalonia/ViewModels/MainWindowViewModel.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,8 +522,13 @@ public async Task ShowUpdateDialog()
522522

523523
private async Task ShowMigrationTipIfNecessaryAsync()
524524
{
525-
if (settingsManager.Settings.SeenTeachingTips.Contains(TeachingTip.SharedFolderMigrationTip))
525+
if (
526+
settingsManager.Settings.SeenTeachingTips.Contains(TeachingTip.SharedFolderMigrationTip)
527+
|| settingsManager.Settings.InstalledPackages.Count == 0
528+
)
529+
{
526530
return;
531+
}
527532

528533
var folderReference = DialogHelper.CreateMarkdownDialog(MarkdownSnippets.SharedFolderMigration);
529534
folderReference.CloseButtonText = Resources.Action_OK;

StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageInstallDetailViewModel.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ public override async Task OnLoadedAsync()
123123
SelectedSharedFolderMethod = SelectedPackage.RecommendedSharedFolderMethod;
124124

125125
// Initialize Python versions
126+
await prerequisiteHelper.UnpackResourcesIfNecessary();
126127
await prerequisiteHelper.InstallUvIfNecessary();
127128
var pythonVersions = await pyInstallationManager.GetAllAvailablePythonsAsync();
128129
AvailablePythonVersions = new ObservableCollection<UvPythonInfo>(pythonVersions);

StabilityMatrix.Core/Helper/HardwareInfo/GpuInfo.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,61 @@ public bool IsLegacyNvidiaGpu()
6060
return ComputeCapabilityValue < 7.5m;
6161
}
6262

63+
public bool IsWindowsRocmSupportedGpu()
64+
{
65+
var gfx = GetAmdGfxArch();
66+
if (gfx is null)
67+
return false;
68+
69+
return gfx.StartsWith("gfx110") || gfx.StartsWith("gfx120") || gfx.Equals("gfx1151");
70+
}
71+
6372
public bool IsAmd => Name?.Contains("amd", StringComparison.OrdinalIgnoreCase) ?? false;
6473
public bool IsIntel => Name?.Contains("arc", StringComparison.OrdinalIgnoreCase) ?? false;
6574

75+
public string? GetAmdGfxArch()
76+
{
77+
if (!IsAmd || string.IsNullOrWhiteSpace(Name))
78+
return null;
79+
80+
var name = Name.ToLowerInvariant();
81+
82+
if (name.Contains("9070") || name.Contains("R9700"))
83+
return "gfx1201";
84+
85+
if (name.Contains("9060"))
86+
return "gfx1200";
87+
88+
if (name.Contains("z2") || name.Contains("880m") || name.Contains("8050s") || name.Contains("8060s"))
89+
return "gfx1151";
90+
91+
if (name.Contains("740m") || name.Contains("760m") || name.Contains("780m") || name.Contains("z1"))
92+
return "gfx1103";
93+
94+
if (
95+
name.Contains("w7400")
96+
|| name.Contains("w7500")
97+
|| name.Contains("w7600")
98+
|| name.Contains("7500 xt")
99+
|| name.Contains("7600")
100+
|| name.Contains("7650 gre")
101+
|| name.Contains("7700s")
102+
)
103+
return "gfx1102";
104+
105+
if (
106+
name.Contains("v710")
107+
|| name.Contains("7700")
108+
|| (name.Contains("7800") && !name.Contains("w7800"))
109+
)
110+
return "gfx1101";
111+
112+
if (name.Contains("w7800") || name.Contains("7900") || name.Contains("7950") || name.Contains("7990"))
113+
return "gfx1100";
114+
115+
return null;
116+
}
117+
66118
public virtual bool Equals(GpuInfo? other)
67119
{
68120
if (other is null)

StabilityMatrix.Core/Helper/HardwareInfo/HardwareHelper.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,13 +281,22 @@ public static bool HasAmdGpu()
281281
return IterGpuInfo().Any(gpu => gpu.IsAmd);
282282
}
283283

284+
public static bool HasWindowsRocmSupportedGpu() =>
285+
IterGpuInfo().Any(gpu => gpu is { IsAmd: true, Name: not null } && gpu.IsWindowsRocmSupportedGpu());
286+
287+
public static GpuInfo? GetWindowsRocmSupportedGpu()
288+
{
289+
return IterGpuInfo().FirstOrDefault(gpu => gpu.IsWindowsRocmSupportedGpu());
290+
}
291+
284292
public static bool HasIntelGpu() => IterGpuInfo().Any(gpu => gpu.IsIntel);
285293

286294
// Set ROCm for default if AMD and Linux
287295
public static bool PreferRocm() => !HasNvidiaGpu() && HasAmdGpu() && Compat.IsLinux;
288296

289297
// Set DirectML for default if AMD and Windows
290-
public static bool PreferDirectMLOrZluda() => !HasNvidiaGpu() && HasAmdGpu() && Compat.IsWindows;
298+
public static bool PreferDirectMLOrZluda() =>
299+
!HasNvidiaGpu() && HasAmdGpu() && Compat.IsWindows && !HasWindowsRocmSupportedGpu();
291300

292301
private static readonly Lazy<bool> IsMemoryInfoAvailableLazy = new(() => TryGetMemoryInfo(out _));
293302
public static bool IsMemoryInfoAvailable => IsMemoryInfoAvailableLazy.Value;

StabilityMatrix.Core/Helper/IPrerequisiteHelper.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,14 @@ Task RunNpm(
191191
IReadOnlyDictionary<string, string>? envVars = null
192192
);
193193
Task InstallNodeIfNecessary(IProgress<ProgressReport>? progress = null);
194-
Task InstallPackageRequirements(BasePackage package, IProgress<ProgressReport>? progress = null);
194+
Task InstallPackageRequirements(
195+
BasePackage package,
196+
PyVersion? pyVersion = null,
197+
IProgress<ProgressReport>? progress = null
198+
);
195199
Task InstallPackageRequirements(
196200
List<PackagePrerequisite> prerequisites,
201+
PyVersion? pyVersion = null,
197202
IProgress<ProgressReport>? progress = null
198203
);
199204

StabilityMatrix.Core/Models/PackageModification/SetupPrerequisitesStep.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ public class SetupPrerequisitesStep(
1313
{
1414
public async Task ExecuteAsync(IProgress<ProgressReport>? progress = null)
1515
{
16-
await prerequisiteHelper.InstallPackageRequirements(package, progress).ConfigureAwait(false);
16+
await prerequisiteHelper
17+
.InstallPackageRequirements(package, pythonVersion, progress)
18+
.ConfigureAwait(false);
1719
}
1820

1921
public string ProgressTitle => "Installing prerequisites...";

0 commit comments

Comments
 (0)