From cd8a245fe7ab6b23be06bac1991ea20082350370 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Sun, 10 Dec 2023 21:10:21 +1300 Subject: [PATCH 01/15] Basic Upscale UI --- .../Services/IUpscaleService.cs | 9 +- .../Services/UpscaleService.cs | 15 + OnnxStack.UI/App.xaml | 57 ++- OnnxStack.UI/App.xaml.cs | 2 + OnnxStack.UI/MainWindow.xaml | 13 + OnnxStack.UI/MainWindow.xaml.cs | 109 ++++-- OnnxStack.UI/Models/UpscaleInfoModel.cs | 67 ++++ OnnxStack.UI/Models/UpscaleModelSetModel.cs | 49 +++ OnnxStack.UI/Models/UpscaleResult.cs | 6 + OnnxStack.UI/OnnxStack.UI.csproj | 6 +- .../UserControls/ImageResultControl.xaml | 9 +- .../UserControls/UpscalePickerControl.xaml | 63 +++ .../UserControls/UpscalePickerControl.xaml.cs | 168 ++++++++ OnnxStack.UI/Utils.cs | 7 +- OnnxStack.UI/Views/UpscaleView.xaml | 204 ++++++++++ OnnxStack.UI/Views/UpscaleView.xaml.cs | 370 ++++++++++++++++++ OnnxStack.UI/appsettings.json | 22 ++ 17 files changed, 1139 insertions(+), 37 deletions(-) create mode 100644 OnnxStack.UI/Models/UpscaleInfoModel.cs create mode 100644 OnnxStack.UI/Models/UpscaleModelSetModel.cs create mode 100644 OnnxStack.UI/Models/UpscaleResult.cs create mode 100644 OnnxStack.UI/UserControls/UpscalePickerControl.xaml create mode 100644 OnnxStack.UI/UserControls/UpscalePickerControl.xaml.cs create mode 100644 OnnxStack.UI/Views/UpscaleView.xaml create mode 100644 OnnxStack.UI/Views/UpscaleView.xaml.cs diff --git a/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs b/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs index 1b4fba95..4600e59c 100644 --- a/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs +++ b/OnnxStack.ImageUpscaler/Services/IUpscaleService.cs @@ -46,7 +46,6 @@ public interface IUpscaleService /// Task LoadModelAsync(UpscaleModelSet model); - /// /// Unloads the model. /// @@ -54,6 +53,14 @@ public interface IUpscaleService /// Task UnloadModelAsync(UpscaleModelSet model); + /// + /// Determines whether [is model loaded] [the specified model options]. + /// + /// The model options. + /// + /// true if [is model loaded] [the specified model options]; otherwise, false. + /// + bool IsModelLoaded(UpscaleModelSet modelOptions); /// /// Generates the upscaled image. diff --git a/OnnxStack.ImageUpscaler/Services/UpscaleService.cs b/OnnxStack.ImageUpscaler/Services/UpscaleService.cs index eb2e6254..6d39caf4 100644 --- a/OnnxStack.ImageUpscaler/Services/UpscaleService.cs +++ b/OnnxStack.ImageUpscaler/Services/UpscaleService.cs @@ -124,6 +124,20 @@ public async Task UnloadModelAsync(UpscaleModelSet model) } + /// + /// Determines whether [is model loaded] [the specified model options]. + /// + /// The model options. + /// + /// true if [is model loaded] [the specified model options]; otherwise, false. + /// + /// + public bool IsModelLoaded(UpscaleModelSet modelOptions) + { + return _modelService.IsModelLoaded(modelOptions); + } + + /// /// Generates the upscaled image. /// @@ -231,5 +245,6 @@ private UpscaleInput CreateInputParams(Image imageSource, int maxTileSiz var height = imageSource.Height * scaleFactor; return new UpscaleInput(tiles, width, height); } + } } \ No newline at end of file diff --git a/OnnxStack.UI/App.xaml b/OnnxStack.UI/App.xaml index 038a9c28..40ee803b 100644 --- a/OnnxStack.UI/App.xaml +++ b/OnnxStack.UI/App.xaml @@ -106,7 +106,7 @@ - + @@ -233,8 +233,8 @@ - - + @@ -260,7 +263,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnnxStack.UI/App.xaml.cs b/OnnxStack.UI/App.xaml.cs index 62de9235..7abed205 100644 --- a/OnnxStack.UI/App.xaml.cs +++ b/OnnxStack.UI/App.xaml.cs @@ -2,6 +2,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using OnnxStack.Core; +using OnnxStack.ImageUpscaler; using OnnxStack.UI.Dialogs; using OnnxStack.UI.Models; using OnnxStack.UI.Services; @@ -26,6 +27,7 @@ public App() // Add OnnxStackStableDiffusion builder.Services.AddOnnxStackStableDiffusion(); + builder.Services.AddOnnxStackImageUpscaler(); builder.Services.AddOnnxStackConfig(); // Add Windows diff --git a/OnnxStack.UI/MainWindow.xaml b/OnnxStack.UI/MainWindow.xaml index 02e22227..9abd8619 100644 --- a/OnnxStack.UI/MainWindow.xaml +++ b/OnnxStack.UI/MainWindow.xaml @@ -83,6 +83,19 @@ + + + + + + + + + + + + + diff --git a/OnnxStack.UI/MainWindow.xaml.cs b/OnnxStack.UI/MainWindow.xaml.cs index 3f6376b5..669b5aa4 100644 --- a/OnnxStack.UI/MainWindow.xaml.cs +++ b/OnnxStack.UI/MainWindow.xaml.cs @@ -1,8 +1,8 @@ using Microsoft.Extensions.Logging; using Microsoft.Win32; using Models; +using OnnxStack.ImageUpscaler.Config; using OnnxStack.StableDiffusion.Config; -using OnnxStack.StableDiffusion.Enums; using OnnxStack.UI.Commands; using OnnxStack.UI.Models; using OnnxStack.UI.Views; @@ -27,36 +27,43 @@ public partial class MainWindow : Window, INotifyPropertyChanged private INavigatable _selectedTabItem; private readonly ILogger _logger; private ObservableCollection _models; + private ObservableCollection _upscaleModels; - public MainWindow(StableDiffusionConfig configuration, OnnxStackUIConfig uiSettings, ILogger logger) + public MainWindow(OnnxStackUIConfig uiSettings, StableDiffusionConfig configuration, ImageUpscalerConfig upscaleConfiguration, ILogger logger) { _logger = logger; UISettings = uiSettings; - SaveImageCommand = new AsyncRelayCommand(SaveImageFile); + SaveImageCommand = new AsyncRelayCommand(SaveUpscaleImageFile); + SaveImageResultCommand = new AsyncRelayCommand(SaveImageResultFile); SaveBlueprintCommand = new AsyncRelayCommand(SaveBlueprintFile); NavigateTextToImageCommand = new AsyncRelayCommand(NavigateTextToImage); NavigateImageToImageCommand = new AsyncRelayCommand(NavigateImageToImage); NavigateImageInpaintCommand = new AsyncRelayCommand(NavigateImageInpaint); NavigateImagePaintToImageCommand = new AsyncRelayCommand(NavigateImagePaintToImage); - + NavigateUpscalerCommand = new AsyncRelayCommand(NavigateUpscaler); WindowCloseCommand = new AsyncRelayCommand(WindowClose); WindowRestoreCommand = new AsyncRelayCommand(WindowRestore); WindowMinimizeCommand = new AsyncRelayCommand(WindowMinimize); WindowMaximizeCommand = new AsyncRelayCommand(WindowMaximize); Models = CreateModelOptions(configuration.ModelSets); + UpscaleModels = CreateUpscaleModelOptions(upscaleConfiguration.ModelSets); InitializeComponent(); } + + public AsyncRelayCommand WindowMinimizeCommand { get; } public AsyncRelayCommand WindowRestoreCommand { get; } public AsyncRelayCommand WindowMaximizeCommand { get; } public AsyncRelayCommand WindowCloseCommand { get; } - public AsyncRelayCommand SaveImageCommand { get; } + public AsyncRelayCommand SaveImageCommand { get; } + public AsyncRelayCommand SaveImageResultCommand { get; } public AsyncRelayCommand SaveBlueprintCommand { get; } public AsyncRelayCommand NavigateTextToImageCommand { get; } public AsyncRelayCommand NavigateImageToImageCommand { get; } public AsyncRelayCommand NavigateImageInpaintCommand { get; } public AsyncRelayCommand NavigateImagePaintToImageCommand { get; } + public AsyncRelayCommand NavigateUpscalerCommand { get; } public OnnxStackUIConfig UISettings { @@ -72,6 +79,13 @@ public ObservableCollection Models set { _models = value; NotifyPropertyChanged(); } } + public ObservableCollection UpscaleModels + { + get { return _upscaleModels; } + set { _upscaleModels = value; NotifyPropertyChanged(); } + } + + public int SelectedTabIndex { get { return _selectedTabIndex; } @@ -104,6 +118,10 @@ private async Task NavigateImagePaintToImage(ImageResult result) await NavigateToTab(TabId.PaintToImage, result); } + private async Task NavigateUpscaler(ImageResult result) + { + await NavigateToTab(TabId.Upscaler, result); + } private async Task NavigateToTab(TabId tab, ImageResult imageResult) { @@ -116,7 +134,8 @@ private enum TabId TextToImage = 0, ImageToImage = 1, ImageInpaint = 2, - PaintToImage = 3 + PaintToImage = 3, + Upscaler = 4 } private ObservableCollection CreateModelOptions(List onnxModelSets) @@ -131,29 +150,47 @@ private ObservableCollection CreateModelOptions(List(models); } - private async Task SaveImageFile(ImageResult imageResult) + + private ObservableCollection CreateUpscaleModelOptions(List modelSets) + { + var models = modelSets.Select(model => new UpscaleModelSetModel + { + Name = model.Name, + ModelOptions = model, + IsEnabled = model.IsEnabled + }); + return new ObservableCollection(models); + } + + private async Task SaveImageResultFile(ImageResult imageResult) { try { - var saveFileDialog = new SaveFileDialog - { - Title = Title, - Filter = "png files (*.png)|*.png", - DefaultExt = "png", - AddExtension = true, - RestoreDirectory = true, - InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), - FileName = $"image-{imageResult.SchedulerOptions.Seed}.png" - }; + var filename = GetSaveFilename($"image-{imageResult.SchedulerOptions.Seed}"); + if (string.IsNullOrEmpty(filename)) + return; - var dialogResult = saveFileDialog.ShowDialog(); - if (dialogResult == false) - { - _logger.LogInformation("Saving image canceled"); + var result = await imageResult.Image.SaveImageFileAsync(filename); + if (!result) + _logger.LogError("Error saving image"); + + } + catch (Exception ex) + { + _logger.LogError(ex, "Error saving image"); + } + } + + + private async Task SaveUpscaleImageFile(UpscaleResult imageResult) + { + try + { + var filename = GetSaveFilename($"image-{imageResult.Info.OutputWidth}x{imageResult.Info.OutputHeight}"); + if (string.IsNullOrEmpty(filename)) return; - } - var result = await imageResult.SaveImageFileAsync(saveFileDialog.FileName); + var result = await imageResult.Image.SaveImageFileAsync(filename); if (!result) _logger.LogError("Error saving image"); @@ -187,6 +224,8 @@ private async Task SaveBlueprintFile(ImageResult imageResult) return; } + + var result = await imageResult.SaveBlueprintFileAsync(saveFileDialog.FileName); if (!result) _logger.LogError("Error saving image blueprint"); @@ -199,6 +238,30 @@ private async Task SaveBlueprintFile(ImageResult imageResult) } + private string GetSaveFilename(string initialFilename) + { + var saveFileDialog = new SaveFileDialog + { + Title = Title, + Filter = "png files (*.png)|*.png", + DefaultExt = "png", + AddExtension = true, + RestoreDirectory = true, + InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), + FileName = $"{initialFilename}.png" + }; + + var dialogResult = saveFileDialog.ShowDialog(); + if (dialogResult == false) + { + _logger.LogInformation("Saving image canceled"); + return null; + } + + return saveFileDialog.FileName; + } + + /// /// Gets or sets the output log. /// diff --git a/OnnxStack.UI/Models/UpscaleInfoModel.cs b/OnnxStack.UI/Models/UpscaleInfoModel.cs new file mode 100644 index 00000000..58499be9 --- /dev/null +++ b/OnnxStack.UI/Models/UpscaleInfoModel.cs @@ -0,0 +1,67 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace OnnxStack.UI.Models +{ + public record UpscaleInfoModel : INotifyPropertyChanged + { + private int _inputWidth; + private int _inputHeight; + private int _outputWidth; + private int _outputHeight; + private int _sampleSize; + private int _scaleFactor; + + public int InputWidth + { + get { return _inputWidth; } + set { _inputWidth = value; NotifyPropertyChanged(); Update(); } + } + + public int InputHeight + { + get { return _inputHeight; } + set { _inputHeight = value; NotifyPropertyChanged(); Update(); } + } + + public int OutputWidth + { + get { return _outputWidth; } + set { _outputWidth = value; NotifyPropertyChanged(); } + } + + public int OutputHeight + { + get { return _outputHeight; } + set { _outputHeight = value; NotifyPropertyChanged(); } + } + + public int SampleSize + { + get { return _sampleSize; } + set { _sampleSize = value; NotifyPropertyChanged(); } + } + + + public int ScaleFactor + { + get { return _scaleFactor; } + set { _scaleFactor = value; NotifyPropertyChanged(); Update(); } + } + + public void Update() + { + OutputWidth = _inputWidth * _scaleFactor; + OutputHeight = _inputHeight * _scaleFactor; + } + + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + #endregion + } +} diff --git a/OnnxStack.UI/Models/UpscaleModelSetModel.cs b/OnnxStack.UI/Models/UpscaleModelSetModel.cs new file mode 100644 index 00000000..d528779e --- /dev/null +++ b/OnnxStack.UI/Models/UpscaleModelSetModel.cs @@ -0,0 +1,49 @@ +using OnnxStack.StableDiffusion.Config; +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace OnnxStack.UI.Models +{ + public class UpscaleModelSetModel : INotifyPropertyChanged + { + private string _name; + private bool _isLoaded; + private bool _isLoading; + private bool _isEnabled; + + public string Name + { + get { return _name; } + set { _name = value; NotifyPropertyChanged(); } + } + + public bool IsLoaded + { + get { return _isLoaded; } + set { _isLoaded = value; NotifyPropertyChanged(); } + } + + public bool IsLoading + { + get { return _isLoading; } + set { _isLoading = value; NotifyPropertyChanged(); } + } + + public bool IsEnabled + { + get { return _isEnabled; } + set { _isEnabled = value; NotifyPropertyChanged(); } + } + + public UpscaleModelSet ModelOptions { get; set; } + + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + #endregion + } +} diff --git a/OnnxStack.UI/Models/UpscaleResult.cs b/OnnxStack.UI/Models/UpscaleResult.cs new file mode 100644 index 00000000..c124a7d8 --- /dev/null +++ b/OnnxStack.UI/Models/UpscaleResult.cs @@ -0,0 +1,6 @@ +using System.Windows.Media.Imaging; + +namespace OnnxStack.UI.Models +{ + public record UpscaleResult(BitmapSource Image, UpscaleInfoModel Info, double Elapsed); +} diff --git a/OnnxStack.UI/OnnxStack.UI.csproj b/OnnxStack.UI/OnnxStack.UI.csproj index ae3d4fac..931eec50 100644 --- a/OnnxStack.UI/OnnxStack.UI.csproj +++ b/OnnxStack.UI/OnnxStack.UI.csproj @@ -40,19 +40,19 @@ - - + - + + diff --git a/OnnxStack.UI/UserControls/ImageResultControl.xaml b/OnnxStack.UI/UserControls/ImageResultControl.xaml index baf03877..534c4576 100644 --- a/OnnxStack.UI/UserControls/ImageResultControl.xaml +++ b/OnnxStack.UI/UserControls/ImageResultControl.xaml @@ -51,8 +51,8 @@ - - - + diff --git a/OnnxStack.UI/UserControls/UpscalePickerControl.xaml b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml new file mode 100644 index 00000000..42b3275e --- /dev/null +++ b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnnxStack.UI/UserControls/UpscalePickerControl.xaml.cs b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml.cs new file mode 100644 index 00000000..e57ad14e --- /dev/null +++ b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml.cs @@ -0,0 +1,168 @@ +using Microsoft.Extensions.Logging; +using Models; +using OnnxStack.Core; +using OnnxStack.ImageUpscaler.Services; +using OnnxStack.StableDiffusion.Common; +using OnnxStack.StableDiffusion.Enums; +using OnnxStack.UI.Commands; +using OnnxStack.UI.Models; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; + +namespace OnnxStack.UI.UserControls +{ + /// + /// Interaction logic for UpscalePickerControl.xaml + /// + public partial class UpscalePickerControl : UserControl, INotifyPropertyChanged + { + private readonly ILogger _logger; + private readonly IUpscaleService _upscaleService; + + /// Initializes a new instance of the class. + public UpscalePickerControl() + { + if (!DesignerProperties.GetIsInDesignMode(this)) + { + _logger = App.GetService>(); + _upscaleService = App.GetService(); + } + + LoadCommand = new AsyncRelayCommand(LoadModel); + UnloadCommand = new AsyncRelayCommand(UnloadModel); + InitializeComponent(); + } + + public AsyncRelayCommand LoadCommand { get; set; } + public AsyncRelayCommand UnloadCommand { get; set; } + + + /// + /// Gets or sets the models. + /// + public ObservableCollection Models + { + get { return (ObservableCollection)GetValue(ModelsProperty); } + set { SetValue(ModelsProperty, value); } + } + public static readonly DependencyProperty ModelsProperty = + DependencyProperty.Register("Models", typeof(ObservableCollection), typeof(UpscalePickerControl), new PropertyMetadata(propertyChangedCallback: OnModelsChanged)); + + + public OnnxStackUIConfig UISettings + { + get { return (OnnxStackUIConfig)GetValue(UISettingsProperty); } + set { SetValue(UISettingsProperty, value); } + } + public static readonly DependencyProperty UISettingsProperty = + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(UpscalePickerControl)); + + + + /// + /// Gets or sets the supported diffusers. + /// + public List SupportedDiffusers + { + get { return (List)GetValue(SupportedDiffusersProperty); } + set { SetValue(SupportedDiffusersProperty, value); } + } + public static readonly DependencyProperty SupportedDiffusersProperty = + DependencyProperty.Register("SupportedDiffusers", typeof(List), typeof(UpscalePickerControl)); + + + /// + /// Gets or sets the selected model. + /// + public UpscaleModelSetModel SelectedModel + { + get { return (UpscaleModelSetModel)GetValue(SelectedModelProperty); } + set { SetValue(SelectedModelProperty, value); } + } + public static readonly DependencyProperty SelectedModelProperty = + DependencyProperty.Register("SelectedModel", typeof(UpscaleModelSetModel), typeof(UpscalePickerControl)); + + + + /// + /// Loads the model. + /// + private async Task LoadModel() + { + if (_upscaleService.IsModelLoaded(SelectedModel.ModelOptions)) + return; + + var elapsed = _logger.LogBegin($"'{SelectedModel.Name}' Loading..."); + SelectedModel.IsLoaded = false; + SelectedModel.IsLoading = true; + + try + { + if (UISettings.ModelCacheMode == ModelCacheMode.Single) + { + foreach (var model in Models.Where(x => x.IsLoaded)) + { + _logger.LogInformation($"'{model.Name}' Unloading..."); + await _upscaleService.UnloadModelAsync(model.ModelOptions); + model.IsLoaded = false; + } + } + + SelectedModel.IsLoaded = await _upscaleService.LoadModelAsync(SelectedModel.ModelOptions); + } + catch (Exception ex) + { + _logger.LogError($"An error occured while loading model '{SelectedModel.Name}' \n {ex}"); + } + + SelectedModel.IsLoading = false; + _logger.LogEnd($"'{SelectedModel.Name}' Loaded.", elapsed); + } + + + /// + /// Unloads the model. + /// + private async Task UnloadModel() + { + if (!_upscaleService.IsModelLoaded(SelectedModel.ModelOptions)) + return; + + _logger.LogInformation($"'{SelectedModel.Name}' Unloading..."); + SelectedModel.IsLoading = true; + await _upscaleService.UnloadModelAsync(SelectedModel.ModelOptions); + SelectedModel.IsLoading = false; + SelectedModel.IsLoaded = false; + _logger.LogInformation($"'{SelectedModel.Name}' Unloaded."); + } + + + /// + /// Called when the Models source collection has changes, via Settings most likely. + /// + /// The owner. + /// The instance containing the event data. + private static void OnModelsChanged(DependencyObject owner, DependencyPropertyChangedEventArgs e) + { + if (owner is UpscalePickerControl control) + { + control.SelectedModel = control.Models.FirstOrDefault(x => x.ModelOptions.IsEnabled); + } + } + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + #endregion + } +} diff --git a/OnnxStack.UI/Utils.cs b/OnnxStack.UI/Utils.cs index 1d99f9e7..a22e93f1 100644 --- a/OnnxStack.UI/Utils.cs +++ b/OnnxStack.UI/Utils.cs @@ -49,13 +49,12 @@ public static byte[] GetImageBytes(this BitmapSource image) } } - - public static async Task SaveImageFileAsync(this ImageResult imageResult, string filename) + public static async Task SaveImageFileAsync(this BitmapSource image, string filename) { await Task.Run(() => { var encoder = new PngBitmapEncoder(); - encoder.Frames.Add(BitmapFrame.Create(imageResult.Image)); + encoder.Frames.Add(BitmapFrame.Create(image)); using (var fileStream = new FileStream(filename, FileMode.Create)) { encoder.Save(fileStream); @@ -88,7 +87,7 @@ public static async Task AutoSaveAsync(this ImageResult imageResult, strin var random = RandomString(); var imageFile = Path.Combine(autosaveDirectory, $"image-{imageResult.SchedulerOptions.Seed}-{random}.png"); var blueprintFile = Path.Combine(autosaveDirectory, $"image-{imageResult.SchedulerOptions.Seed}-{random}.json"); - if (!await imageResult.SaveImageFileAsync(imageFile)) + if (!await imageResult.Image.SaveImageFileAsync(imageFile)) return false; if (includeBlueprint) diff --git a/OnnxStack.UI/Views/UpscaleView.xaml b/OnnxStack.UI/Views/UpscaleView.xaml new file mode 100644 index 00000000..bed9fa18 --- /dev/null +++ b/OnnxStack.UI/Views/UpscaleView.xaml @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnnxStack.UI/Views/UpscaleView.xaml.cs b/OnnxStack.UI/Views/UpscaleView.xaml.cs new file mode 100644 index 00000000..f0a1d323 --- /dev/null +++ b/OnnxStack.UI/Views/UpscaleView.xaml.cs @@ -0,0 +1,370 @@ +using Microsoft.Extensions.Logging; +using Models; +using OnnxStack.Core.Image; +using OnnxStack.ImageUpscaler.Services; +using OnnxStack.UI.Commands; +using OnnxStack.UI.Models; +using System; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media.Imaging; + +namespace OnnxStack.UI.Views +{ + /// + /// Interaction logic for UpscaleView.xaml + /// + public partial class UpscaleView : UserControl, INavigatable, INotifyPropertyChanged + { + private readonly ILogger _logger; + private readonly IUpscaleService _upscaleService; + + private bool _hasResult; + private int _progressMax; + private int _progressValue; + private bool _isGenerating; + private int _selectedTabIndex; + private bool _isControlsEnabled; + private UpscaleResult _resultImage; + private UpscaleModelSetModel _selectedModel; + private CancellationTokenSource _cancelationTokenSource; + private BitmapSource _inputImage; + private string _imageFile; + private UpscaleInfoModel _upscaleInfo; + + /// + /// Initializes a new instance of the class. + /// + public UpscaleView() + { + if (!DesignerProperties.GetIsInDesignMode(this)) + { + _logger = App.GetService>(); + _upscaleService = App.GetService(); + } + + CancelCommand = new AsyncRelayCommand(Cancel, CanExecuteCancel); + GenerateCommand = new AsyncRelayCommand(Generate, CanExecuteGenerate); + ClearHistoryCommand = new AsyncRelayCommand(ClearHistory, CanExecuteClearHistory); + ImageResults = new ObservableCollection(); + UpscaleInfo = new UpscaleInfoModel(); + IsControlsEnabled = true; + InitializeComponent(); + } + + public OnnxStackUIConfig UISettings + { + get { return (OnnxStackUIConfig)GetValue(UISettingsProperty); } + set { SetValue(UISettingsProperty, value); } + } + public static readonly DependencyProperty UISettingsProperty = + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(UpscaleView)); + + public AsyncRelayCommand CancelCommand { get; } + public AsyncRelayCommand GenerateCommand { get; } + public AsyncRelayCommand ClearHistoryCommand { get; set; } + public ObservableCollection ImageResults { get; } + + public UpscaleModelSetModel SelectedModel + { + get { return _selectedModel; } + set { _selectedModel = value; NotifyPropertyChanged(); UpdateInfo(); } + } + + public UpscaleResult ResultImage + { + get { return _resultImage; } + set { _resultImage = value; NotifyPropertyChanged(); } + } + + public BitmapSource InputImage + { + get { return _inputImage; } + set { _inputImage = value; NotifyPropertyChanged(); } + } + + public string ImageFile + { + get { return _imageFile; } + set { _imageFile = value; NotifyPropertyChanged(); LoadImage(); } + } + + + + public UpscaleInfoModel UpscaleInfo + { + get { return _upscaleInfo; } + set { _upscaleInfo = value; NotifyPropertyChanged(); } + } + + + + public int ProgressValue + { + get { return _progressValue; } + set { _progressValue = value; NotifyPropertyChanged(); } + } + + public int ProgressMax + { + get { return _progressMax; } + set { _progressMax = value; NotifyPropertyChanged(); } + } + + public bool IsGenerating + { + get { return _isGenerating; } + set { _isGenerating = value; NotifyPropertyChanged(); } + } + + public bool HasResult + { + get { return _hasResult; } + set { _hasResult = value; NotifyPropertyChanged(); } + } + + public int SelectedTabIndex + { + get { return _selectedTabIndex; } + set { _selectedTabIndex = value; NotifyPropertyChanged(); } + } + + public bool IsControlsEnabled + { + get { return _isControlsEnabled; } + set { _isControlsEnabled = value; NotifyPropertyChanged(); } + } + + private ScrollBarVisibility _scrollBarVisibility; + + public ScrollBarVisibility ScrollBarVisibility + { + get { return _scrollBarVisibility; } + set { _scrollBarVisibility = value; NotifyPropertyChanged(); } + } + + private bool _showFullImage; + + public bool ShowFullImage + { + get { return _showFullImage; } + set { _showFullImage = value; NotifyPropertyChanged(); UpdateScrollBar(); } + } + + private void UpdateScrollBar() + { + ScrollBarVisibility = _showFullImage + ? ScrollBarVisibility.Auto + : ScrollBarVisibility.Disabled; + } + + + + + /// + /// Called on Navigate + /// + /// The image result. + /// + public async Task NavigateAsync(ImageResult imageResult) + { + if (IsGenerating) + await Cancel(); + + Reset(); + HasResult = false; + ResultImage = null; + InputImage = imageResult.Image; + UpdateInfo(); + SelectedTabIndex = 0; + } + + + /// + /// Generates this image result. + /// + private async Task Generate() + { + HasResult = false; + IsGenerating = true; + IsControlsEnabled = false; + ResultImage = null; + + + try + { + var timestamp = Stopwatch.GetTimestamp(); + var resultBytes = await _upscaleService.GenerateAsByteAsync(SelectedModel.ModelOptions, new InputImage(InputImage.GetImageBytes())); + if (resultBytes != null) + { + var elapsed = Stopwatch.GetElapsedTime(timestamp).TotalSeconds; + var imageResult = new UpscaleResult(Utils.CreateBitmap(resultBytes), UpscaleInfo with { }, elapsed); + ResultImage = imageResult; + HasResult = true; + + + ImageResults.Add(imageResult); + } + + } + catch (OperationCanceledException) + { + _logger.LogInformation($"Generate was canceled."); + } + catch (Exception ex) + { + _logger.LogError($"Error during Generate\n{ex}"); + } + + Reset(); + } + + + /// + /// Determines whether this instance can execute Generate. + /// + /// + /// true if this instance can execute Generate; otherwise, false. + /// + private bool CanExecuteGenerate() + { + return !IsGenerating && InputImage is not null; + } + + + /// + /// Cancels this generation. + /// + /// + private Task Cancel() + { + _cancelationTokenSource?.Cancel(); + return Task.CompletedTask; + } + + + /// + /// Determines whether this instance can execute Cancel. + /// + /// + /// true if this instance can execute Cancel; otherwise, false. + /// + private bool CanExecuteCancel() + { + return IsGenerating; + } + + + /// + /// Clears the history. + /// + /// + private Task ClearHistory() + { + ImageResults.Clear(); + return Task.CompletedTask; + } + + + /// + /// Determines whether this instance can execute ClearHistory. + /// + /// + /// true if this instance can execute ClearHistory; otherwise, false. + /// + private bool CanExecuteClearHistory() + { + return ImageResults.Count > 0; + } + + + /// + /// Resets this instance. + /// + private void Reset() + { + IsGenerating = false; + IsControlsEnabled = true; + ProgressValue = 0; + } + + private void LoadImage() + { + InputImage = string.IsNullOrEmpty(_imageFile) + ? null + : new BitmapImage(new Uri(_imageFile)); + UpdateInfo(); + } + + private void UpdateInfo() + { + if (SelectedModel != null) + { + UpscaleInfo.SampleSize = SelectedModel.ModelOptions.SampleSize; + UpscaleInfo.ScaleFactor = SelectedModel.ModelOptions.ScaleFactor; + UpscaleInfo.InputWidth = InputImage?.PixelWidth ?? SelectedModel.ModelOptions.SampleSize; + UpscaleInfo.InputHeight = InputImage?.PixelHeight ?? SelectedModel.ModelOptions.SampleSize; + return; + } + UpscaleInfo = new UpscaleInfoModel(); + } + + //private async Task GenerateResultAsync(byte[] imageBytes, long timestamp) + //{ + // var image = Utils.CreateBitmap(imageBytes); + + // //var imageResult = new ImageResult + // //{ + // // Image = image, + // // Model = _selectedModel, + + // // Elapsed = Stopwatch.GetElapsedTime(timestamp).TotalSeconds + // //}; + + // if (UISettings.ImageAutoSave) + // await imageResult.AutoSaveAsync(Path.Combine(UISettings.ImageAutoSaveDirectory, "TextToImage"), UISettings.ImageAutoSaveBlueprint); + // return imageResult; + //} + + + /// + /// StableDiffusion progress callback. + /// + /// + private Action ProgressCallback() + { + return (value, maximum) => + { + App.UIInvoke(() => + { + if (_cancelationTokenSource.IsCancellationRequested) + return; + + if (ProgressMax != maximum) + ProgressMax = maximum; + + ProgressValue = value; + }); + }; + } + + + + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + + #endregion + } + +} \ No newline at end of file diff --git a/OnnxStack.UI/appsettings.json b/OnnxStack.UI/appsettings.json index 30e86ef3..d84c0ddf 100644 --- a/OnnxStack.UI/appsettings.json +++ b/OnnxStack.UI/appsettings.json @@ -10,6 +10,28 @@ "ModelSets": [ ] }, + "ImageUpscalerConfig": { + "ModelSets": [ + { + "Name": "RealSR BSRGAN x4", + "IsEnabled": true, + "Channels": 3, + "SampleSize": 512, + "ScaleFactor": 4, + "DeviceId": 0, + "InterOpNumThreads": 0, + "IntraOpNumThreads": 0, + "ExecutionMode": "ORT_SEQUENTIAL", + "ExecutionProvider": "DirectML", + "ModelConfigurations": [ + { + "Type": "Unet", + "OnnxModelPath": "D:\\Repositories\\upscaler\\SwinIR\\003_realSR_BSRGAN_DFO_s64w8_SwinIR-M_x4_GAN.onnx" + } + ] + } + ] + }, "OnnxStackUIConfig": { "ModelCacheMode": "Single", "ImageAutoSave": false, From 19bb2e7c027083a53d15a50621ff7f9509813356 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Fri, 15 Dec 2023 12:58:23 +1300 Subject: [PATCH 02/15] New ModelTemplate prototype --- .../Config/UpscaleModelSet.cs | 2 +- .../Config/StableDiffusionModelSet.cs | 2 +- OnnxStack.UI/App.xaml | 16 +- OnnxStack.UI/App.xaml.cs | 4 + .../Converters/ComboBoxAllItemConverter.cs | 30 + OnnxStack.UI/Dialogs/AddModelDialog.xaml | 95 ++- OnnxStack.UI/Dialogs/AddModelDialog.xaml.cs | 132 +++- .../Dialogs/AddUpscaleModelDialog.xaml | 92 +++ .../Dialogs/AddUpscaleModelDialog.xaml.cs | 225 +++++++ OnnxStack.UI/Dialogs/UpdateModelDialog.xaml | 101 +++ .../Dialogs/UpdateModelDialog.xaml.cs | 311 +++++++++ .../Dialogs/UpdateUpscaleModelDialog.xaml | 92 +++ .../Dialogs/UpdateUpscaleModelDialog.xaml.cs | 226 +++++++ OnnxStack.UI/MainWindow.xaml | 13 + OnnxStack.UI/Models/ModelConfigTemplate.cs | 2 +- OnnxStack.UI/Models/OnnxStackUIConfig.cs | 8 +- .../StableDiffusionModelSetViewModel.cs | 11 + OnnxStack.UI/Services/IModelFactory.cs | 10 + OnnxStack.UI/Services/ModelFactory.cs | 108 ++++ OnnxStack.UI/Views/ModelSettingsView.xaml | 241 +++++++ OnnxStack.UI/Views/ModelSettingsView.xaml.cs | 601 ++++++++++++++++++ OnnxStack.UI/Views/ModelView.xaml | 1 + OnnxStack.UI/Views/ModelView.xaml.cs | 53 +- OnnxStack.UI/appsettings.json | 25 + 24 files changed, 2344 insertions(+), 57 deletions(-) create mode 100644 OnnxStack.UI/Converters/ComboBoxAllItemConverter.cs create mode 100644 OnnxStack.UI/Dialogs/AddUpscaleModelDialog.xaml create mode 100644 OnnxStack.UI/Dialogs/AddUpscaleModelDialog.xaml.cs create mode 100644 OnnxStack.UI/Dialogs/UpdateModelDialog.xaml create mode 100644 OnnxStack.UI/Dialogs/UpdateModelDialog.xaml.cs create mode 100644 OnnxStack.UI/Dialogs/UpdateUpscaleModelDialog.xaml create mode 100644 OnnxStack.UI/Dialogs/UpdateUpscaleModelDialog.xaml.cs create mode 100644 OnnxStack.UI/Models/StableDiffusionModelSetViewModel.cs create mode 100644 OnnxStack.UI/Services/IModelFactory.cs create mode 100644 OnnxStack.UI/Services/ModelFactory.cs create mode 100644 OnnxStack.UI/Views/ModelSettingsView.xaml create mode 100644 OnnxStack.UI/Views/ModelSettingsView.xaml.cs diff --git a/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs b/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs index 5a7ba714..febe79e9 100644 --- a/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs +++ b/OnnxStack.ImageUpscaler/Config/UpscaleModelSet.cs @@ -4,7 +4,7 @@ namespace OnnxStack.StableDiffusion.Config { - public class UpscaleModelSet : IOnnxModelSetConfig + public record UpscaleModelSet : IOnnxModelSetConfig { public string Name { get; set; } public int Channels { get; set; } diff --git a/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs b/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs index 6ccf1460..5fb61c5f 100644 --- a/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs +++ b/OnnxStack.StableDiffusion/Config/StableDiffusionModelSet.cs @@ -8,7 +8,7 @@ namespace OnnxStack.StableDiffusion.Config { - public class StableDiffusionModelSet : IOnnxModelSetConfig + public record StableDiffusionModelSet : IOnnxModelSetConfig { public string Name { get; set; } public bool IsEnabled { get; set; } diff --git a/OnnxStack.UI/App.xaml b/OnnxStack.UI/App.xaml index 40ee803b..cfd748e7 100644 --- a/OnnxStack.UI/App.xaml +++ b/OnnxStack.UI/App.xaml @@ -2,8 +2,9 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib" + xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=System.ComponentModel.TypeConverter" xmlns:theme="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero2" - xmlns:local="clr-namespace:OnnxStack.UI" + xmlns:local="clr-namespace:OnnxStack.UI" xmlns:SD_Enums="clr-namespace:OnnxStack.StableDiffusion.Enums;assembly=OnnxStack.StableDiffusion" xmlns:userControls="clr-namespace:OnnxStack.UI.UserControls" xmlns:behaviors="clr-namespace:OnnxStack.UI.Behaviors" @@ -35,6 +36,13 @@ + + + + + + + @@ -42,6 +50,12 @@ + + + + + + diff --git a/OnnxStack.UI/App.xaml.cs b/OnnxStack.UI/App.xaml.cs index 7abed205..bfa9e5c3 100644 --- a/OnnxStack.UI/App.xaml.cs +++ b/OnnxStack.UI/App.xaml.cs @@ -36,6 +36,10 @@ public App() builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); diff --git a/OnnxStack.UI/Converters/ComboBoxAllItemConverter.cs b/OnnxStack.UI/Converters/ComboBoxAllItemConverter.cs new file mode 100644 index 00000000..8ffda443 --- /dev/null +++ b/OnnxStack.UI/Converters/ComboBoxAllItemConverter.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Windows.Data; + +namespace OnnxStack.UI.Converters +{ + public class ComboBoxAllItemConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + IEnumerable container = value as IEnumerable; + if (container != null) + { + IEnumerable genericContainer = container.OfType(); + IEnumerable emptyItem = new object[] { "All" }; + return emptyItem.Concat(genericContainer); + } + + return value; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + return value is string str && str == "All" ? null : value; + } + } +} diff --git a/OnnxStack.UI/Dialogs/AddModelDialog.xaml b/OnnxStack.UI/Dialogs/AddModelDialog.xaml index f233ae8e..932ece21 100644 --- a/OnnxStack.UI/Dialogs/AddModelDialog.xaml +++ b/OnnxStack.UI/Dialogs/AddModelDialog.xaml @@ -3,34 +3,93 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:local="clr-namespace:OnnxStack.UI.Dialogs" + xmlns:userControls="clr-namespace:OnnxStack.UI.UserControls" mc:Ignorable="d" Name="UI" Icon="/Images/Icon.png" - MinWidth="400" + MinWidth="500" SizeToContent="WidthAndHeight" WindowStartupLocation="CenterOwner" SnapsToDevicePixels="True" UseLayoutRounding="True" Style="{StaticResource BaseWindow}" - ContentRendered="OnContentRendered"> + ContentRendered="OnContentRendered" + Title="Add Model"> - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OnnxStack.UI/Dialogs/AddModelDialog.xaml.cs b/OnnxStack.UI/Dialogs/AddModelDialog.xaml.cs index a1b229da..1732c22b 100644 --- a/OnnxStack.UI/Dialogs/AddModelDialog.xaml.cs +++ b/OnnxStack.UI/Dialogs/AddModelDialog.xaml.cs @@ -1,10 +1,17 @@ using Microsoft.Extensions.Logging; using OnnxStack.Core; +using OnnxStack.Core.Config; +using OnnxStack.StableDiffusion.Config; using OnnxStack.StableDiffusion.Enums; using OnnxStack.UI.Commands; +using OnnxStack.UI.Models; +using OnnxStack.UI.Services; using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.ComponentModel; +using System.IO; +using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; @@ -18,14 +25,17 @@ public partial class AddModelDialog : Window, INotifyPropertyChanged { private readonly ILogger _logger; - private string _textResult; - private string _errorMessage; private List _invalidOptions; private DiffuserPipelineType _pipelineType; + private ModelType _modelType; + private string _modelFolder; + private string _modelName; + private IModelFactory _modelFactory; - public AddModelDialog(ILogger logger) + public AddModelDialog(IModelFactory modelFactory, ILogger logger) { _logger = logger; + _modelFactory = modelFactory; WindowCloseCommand = new AsyncRelayCommand(WindowClose); WindowRestoreCommand = new AsyncRelayCommand(WindowRestore); WindowMinimizeCommand = new AsyncRelayCommand(WindowMinimize); @@ -33,7 +43,6 @@ public AddModelDialog(ILogger logger) SaveCommand = new AsyncRelayCommand(Save, CanExecuteSave); CancelCommand = new AsyncRelayCommand(Cancel, CanExecuteCancel); InitializeComponent(); - ErrorMessage = string.Empty; } public AsyncRelayCommand WindowMinimizeCommand { get; } public AsyncRelayCommand WindowRestoreCommand { get; } @@ -42,63 +51,132 @@ public AddModelDialog(ILogger logger) public AsyncRelayCommand SaveCommand { get; } public AsyncRelayCommand CancelCommand { get; } + public ObservableCollection ValidationResults { get; set; } = new ObservableCollection(); + public DiffuserPipelineType PipelineType { get { return _pipelineType; } - set { _pipelineType = value; NotifyPropertyChanged(); } + set + { + _pipelineType = value; + NotifyPropertyChanged(); + if (_pipelineType != DiffuserPipelineType.StableDiffusionXL && _pipelineType != DiffuserPipelineType.LatentConsistencyXL) + { + _modelType = ModelType.Base; + NotifyPropertyChanged(nameof(ModelType)); + } + CreateModelSet(); + } } - public string TextResult + public ModelType ModelType { - get { return _textResult; } - set { _textResult = value; NotifyPropertyChanged(); ErrorMessage = string.Empty; } + get { return _modelType; } + set { _modelType = value; NotifyPropertyChanged(); CreateModelSet(); } } - public List InvalidOptions + public string ModelName { - get { return _invalidOptions; } - set { _invalidOptions = value; NotifyPropertyChanged(); } + get { return _modelName; } + set { _modelName = value; NotifyPropertyChanged(); CreateModelSet(); } } - public string ErrorMessage + public string ModelFolder { - get { return _errorMessage; } - set { _errorMessage = value; NotifyPropertyChanged(); } + get { return _modelFolder; } + set + { + _modelFolder = value; + _modelName = string.IsNullOrEmpty(_modelFolder) + ? string.Empty + : Path.GetFileName(_modelFolder); + + NotifyPropertyChanged(); + NotifyPropertyChanged(nameof(ModelName)); + CreateModelSet(); + } } + private bool _isNameInvalid; - public bool ShowDialog(string title, List invalidOptions = null) + public bool IsNameInvalid { - Title = title; - InvalidOptions = invalidOptions; - return ShowDialog() ?? false; + get { return _isNameInvalid; } + set { _isNameInvalid = value; NotifyPropertyChanged(); } } - private Task Save() + private StableDiffusionModelSet _modelSet; + + public StableDiffusionModelSet ModelSet { - var result = TextResult.Trim(); - if (!InvalidOptions.IsNullOrEmpty() && InvalidOptions.Contains(result)) + get { return _modelSet; } + set { _modelSet = value; NotifyPropertyChanged(); } + } + + + + private void CreateModelSet() + { + ModelSet = null; + IsNameInvalid = false; + ValidationResults.Clear(); + if (string.IsNullOrEmpty(_modelFolder)) + return; + + ModelSet = _modelFactory.CreateModelSet(ModelName.Trim(), ModelFolder, PipelineType, ModelType); + + // Validate + IsNameInvalid = !InvalidOptions.IsNullOrEmpty() && InvalidOptions.Contains(_modelName); + foreach (var validationResult in ModelSet.ModelConfigurations.Select(x => new ValidationResult(x.Type, File.Exists(x.OnnxModelPath)))) { - ErrorMessage = $"{result} is an invalid option"; - return Task.CompletedTask; + ValidationResults.Add(validationResult); } + } - _textResult = result; + + public List InvalidOptions + { + get { return _invalidOptions; } + set { _invalidOptions = value; NotifyPropertyChanged(); } + } + + + public bool ShowDialog(List invalidOptions = null) + { + InvalidOptions = invalidOptions; + return base.ShowDialog() ?? false; + } + + + private Task Save() + { DialogResult = true; return Task.CompletedTask; } private bool CanExecuteSave() { - var result = TextResult?.Trim() ?? string.Empty; - return result.Length > 2 && result.Length <= 24; + if (string.IsNullOrEmpty(_modelFolder)) + return false; + if (string.IsNullOrEmpty(_modelName) || IsNameInvalid) + return false; + if (_modelSet is null) + return false; + + var result = _modelName.Trim(); + if (!InvalidOptions.IsNullOrEmpty() && InvalidOptions.Contains(result)) + return false; + + return (result.Length > 2 && result.Length <= 50) + && (ValidationResults.Count > 0 && ValidationResults.All(x => x.IsValid)); } private Task Cancel() { + ModelSet = null; DialogResult = false; return Task.CompletedTask; } @@ -151,4 +229,6 @@ public void NotifyPropertyChanged([CallerMemberName] string property = "") } #endregion } + + public record ValidationResult(OnnxModelType ModelType, bool IsValid); } diff --git a/OnnxStack.UI/Dialogs/AddUpscaleModelDialog.xaml b/OnnxStack.UI/Dialogs/AddUpscaleModelDialog.xaml new file mode 100644 index 00000000..febb2dfc --- /dev/null +++ b/OnnxStack.UI/Dialogs/AddUpscaleModelDialog.xaml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + ItemsSource="{Binding ModelTemplateCollectionView, Mode=TwoWay}" + SelectedItem="{Binding SelectedModelTemplate, Mode=TwoWay}" + IsSynchronizedWithCurrentItem="True"> - - @@ -231,11 +592,5 @@ - - - - - - diff --git a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs index c5e00546..4ab934ac 100644 --- a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs +++ b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs @@ -1,27 +1,26 @@ using Microsoft.Extensions.Logging; +using OnnxStack.Core; using OnnxStack.Core.Config; using OnnxStack.StableDiffusion.Config; -using OnnxStack.StableDiffusion.Enums; using OnnxStack.UI.Commands; using OnnxStack.UI.Dialogs; using OnnxStack.UI.Models; using OnnxStack.UI.Services; using System; -using System.Collections; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; -using System.Dynamic; -using System.Globalization; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; +using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; + namespace OnnxStack.UI.Views { /// @@ -32,6 +31,21 @@ public partial class ModelSettingsView : UserControl, INavigatable, INotifyPrope private readonly IModelFactory _modelFactory; private readonly IDialogService _dialogService; private readonly ILogger _logger; + private readonly IModelDownloadService _modelDownloadService; + + private ModelTemplateViewModel _selectedModelTemplate; + private ICollectionView _modelTemplateCollectionView; + + private string _modelTemplateFilterText; + private string _modelTemplateFilterAuthor; + private string _modelTemplateFilterTemplateType; + private List _modelTemplateFilterAuthors; + private ModelTemplateStatusFilter _modelTemplateFilterStatus; + + private LayoutViewType _modelTemplateLayoutView; + private string _modelTemplateSortProperty; + private ListSortDirection _modelTemplateSortDirection; + /// /// Initializes a new instance of the class. @@ -40,36 +54,121 @@ public ModelSettingsView() { if (!DesignerProperties.GetIsInDesignMode(this)) { + _logger = App.GetService>(); _modelFactory = App.GetService(); _dialogService = App.GetService(); - _logger = App.GetService>(); + _modelDownloadService = App.GetService(); } + + UpdateModelCommand = new AsyncRelayCommand(UpdateModel); + UpdateModelAdvancedCommand = new AsyncRelayCommand(UpdateModelAdvanced); + + RemoveModelCommand = new AsyncRelayCommand(RemoveModel); + InstallModelCommand = new AsyncRelayCommand(InstallModel); + UninstallModelCommand = new AsyncRelayCommand(UninstallModel); + DownloadModelCommand = new AsyncRelayCommand(DownloadModel); + DownloadModelCancelCommand = new AsyncRelayCommand(DownloadModelCancel); + ModelTemplateFilterResetCommand = new AsyncRelayCommand(ModelTemplateFilterReset); + UpdateModelMetadataCommand = new AsyncRelayCommand(UpdateModelMetadata); + ViewModelMetadataCommand = new AsyncRelayCommand(ViewModelMetadata); + + HyperLinkNavigateCommand = new AsyncRelayCommand(HyperLinkNavigate); + ModelTemplateLayoutCommand = new AsyncRelayCommand(ModelTemplateLayout); + AddUpscaleModelCommand = new AsyncRelayCommand(AddUpscaleModel); - RemoveUpscaleModelCommand = new AsyncRelayCommand(RemoveUpscaleModel, () => SelectedUpscaleModel is not null); - UpdateUpscaleModelCommand = new AsyncRelayCommand(UpdateUpscaleModel, () => SelectedUpscaleModel is not null); AddStableDiffusionModelCommand = new AsyncRelayCommand(AddStableDiffusionModel); - RemoveStableDiffusionModelCommand = new AsyncRelayCommand(RemoveStableDiffusionModel, () => SelectedStableDiffusionModel is not null); - UpdateStableDiffusionModelCommand = new AsyncRelayCommand(UpdateStableDiffusionModel, () => SelectedStableDiffusionModel is not null); - - RenameStableDiffusionModelCommand = new AsyncRelayCommand(RenameStableDiffusionModel); - UninstallStableDiffusionModelCommand = new AsyncRelayCommand(UninstallStableDiffusionModel); - InstallLocalStableDiffusionModelCommand = new AsyncRelayCommand(InstallLocalStableDiffusionModel); InitializeComponent(); } + private Task HyperLinkNavigate(string link) + { + Process.Start(new ProcessStartInfo(link) { UseShellExecute = true }); + return Task.CompletedTask; + } + + + public AsyncRelayCommand UpdateModelCommand { get; } + public AsyncRelayCommand UpdateModelAdvancedCommand { get; } + public AsyncRelayCommand RemoveModelCommand { get; } + public AsyncRelayCommand InstallModelCommand { get; } + public AsyncRelayCommand UninstallModelCommand { get; } + public AsyncRelayCommand DownloadModelCommand { get; } + public AsyncRelayCommand DownloadModelCancelCommand { get; } + public AsyncRelayCommand ModelTemplateFilterResetCommand { get; } + public AsyncRelayCommand HyperLinkNavigateCommand { get; } public AsyncRelayCommand AddUpscaleModelCommand { get; } - public AsyncRelayCommand RemoveUpscaleModelCommand { get; } - public AsyncRelayCommand UpdateUpscaleModelCommand { get; } public AsyncRelayCommand AddStableDiffusionModelCommand { get; } - public AsyncRelayCommand RemoveStableDiffusionModelCommand { get; } - public AsyncRelayCommand UpdateStableDiffusionModelCommand { get; } + public AsyncRelayCommand ModelTemplateLayoutCommand { get; } + public AsyncRelayCommand UpdateModelMetadataCommand { get; } + public AsyncRelayCommand ViewModelMetadataCommand { get; } + + public ModelTemplateViewModel SelectedModelTemplate + { + get { return _selectedModelTemplate; } + set { _selectedModelTemplate = value; NotifyPropertyChanged(); } + } + + public ICollectionView ModelTemplateCollectionView + { + get { return _modelTemplateCollectionView; } + set { _modelTemplateCollectionView = value; NotifyPropertyChanged(); } + } + + public string ModelTemplateFilterText + { + get { return _modelTemplateFilterText; } + set { _modelTemplateFilterText = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } + + public string ModelTemplateFilterTemplateType + { + get { return _modelTemplateFilterTemplateType; } + set { _modelTemplateFilterTemplateType = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } - public AsyncRelayCommand RenameStableDiffusionModelCommand { get; } - public AsyncRelayCommand UninstallStableDiffusionModelCommand { get; } - public AsyncRelayCommand InstallLocalStableDiffusionModelCommand { get; } + public string ModelTemplateFilterAuthor + { + get { return _modelTemplateFilterAuthor; } + set { _modelTemplateFilterAuthor = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } + + public List ModelTemplateFilterAuthors + { + get { return _modelTemplateFilterAuthors; } + set { _modelTemplateFilterAuthors = value; NotifyPropertyChanged(); } + } + + + + public ModelTemplateStatusFilter ModelTemplateFilterStatus + { + get { return _modelTemplateFilterStatus; } + set { _modelTemplateFilterStatus = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + } + + + + + public LayoutViewType ModelTemplateLayoutView + { + get { return _modelTemplateLayoutView; } + set { _modelTemplateLayoutView = value; NotifyPropertyChanged(); } + } + + public string ModelTemplateSortProperty + { + get { return _modelTemplateSortProperty; } + set { _modelTemplateSortProperty = value; NotifyPropertyChanged(); ModelTemplateSort(); } + } + + public ListSortDirection ModelTemplateSortDirection + { + get { return _modelTemplateSortDirection; } + set { _modelTemplateSortDirection = value; NotifyPropertyChanged(); ModelTemplateSort(); } + } public OnnxStackUIConfig UISettings { @@ -77,16 +176,11 @@ public OnnxStackUIConfig UISettings set { SetValue(UISettingsProperty, value); } } public static readonly DependencyProperty UISettingsProperty = - DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(ModelSettingsView), new PropertyMetadata(OnUISettingsChanged)); - - private static void OnUISettingsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - if (d is ModelSettingsView control && e.NewValue is OnnxStackUIConfig settings) + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(ModelSettingsView), new PropertyMetadata((d, e) => { - control.InitializeTemplates(); - } - } - + if (d is ModelSettingsView control && e.NewValue is OnnxStackUIConfig) + control.InitializeTemplates(); + })); public Task NavigateAsync(ImageResult imageResult) @@ -94,104 +188,161 @@ public Task NavigateAsync(ImageResult imageResult) throw new NotImplementedException(); } - private UpscaleModelSetViewModel _selectedUpscaleModel; - public UpscaleModelSetViewModel SelectedUpscaleModel + private async Task RemoveModel() { - get { return _selectedUpscaleModel; } - set { _selectedUpscaleModel = value; NotifyPropertyChanged(); } - } + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await RemoveUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await RemoveStableDiffusionModel(modelTemplate); + } - private StableDiffusionModelSetViewModel _selectedStableDiffusionModel; - public StableDiffusionModelSetViewModel SelectedStableDiffusionModel + private async Task InstallModel() { - get { return _selectedStableDiffusionModel; } - set { _selectedStableDiffusionModel = value; NotifyPropertyChanged(); } + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await InstallUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await InstallStableDiffusionModel(modelTemplate); } - private async Task AddUpscaleModel() + + private async Task UninstallModel() { - var invalidNames = UISettings.UpscaleModelSets.Select(x => x.ModelSet.Name).ToList(); - var addModelDialog = _dialogService.GetDialog(); - if (addModelDialog.ShowDialog(invalidNames)) - { - UISettings.UpscaleModelSets.Add(new UpscaleModelSetViewModel - { - Name = addModelDialog.ModelName, - ModelSet = addModelDialog.ModelSet - }); + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; - await SaveConfigurationFile(); - } + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await UninstallUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await UninstallStableDiffusionModel(modelTemplate); } - private async Task RemoveUpscaleModel() + + private async Task UpdateModel() { - UISettings.UpscaleModelSets.Remove(SelectedUpscaleModel); - await SaveConfigurationFile(); - SelectedUpscaleModel = UISettings.UpscaleModelSets.FirstOrDefault(); + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.IsUserTemplate && x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await UpdateUpscaleModel(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await UpdateStableDiffusionModel(modelTemplate); } - private async Task UpdateUpscaleModel() + private async Task UpdateModelAdvanced() { - var invalidNames = UISettings.UpscaleModelSets.Select(x => x.ModelSet.Name).ToList(); - var addModelDialog = _dialogService.GetDialog(); - if (addModelDialog.ShowDialog(SelectedUpscaleModel.ModelSet, invalidNames)) - { - SelectedUpscaleModel.Name = addModelDialog.ModelName; - SelectedUpscaleModel.ModelSet = addModelDialog.ModelSet; - await SaveConfigurationFile(); - } + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.IsUserTemplate && x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return; + + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await UpdateUpscaleModelAdvanced(modelTemplate); + else if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await UpdateStableDiffusionModelAdvanced(modelTemplate); } - private async Task AddStableDiffusionModel() + private Task DownloadModel(bool isRepostitoryClone) { - var invalidNames = UISettings.StableDiffusionModelSets.Select(x => x.ModelSet.Name).ToList(); - var addModelDialog = _dialogService.GetDialog(); - if (addModelDialog.ShowDialog(invalidNames)) + var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); + if (modelTemplate == null) + return Task.CompletedTask; + + var folderDialog = new System.Windows.Forms.FolderBrowserDialog(); + if (folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { - UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel + var repositoryUrl = modelTemplate.Repository; + var outputDirectory = Path.Combine(folderDialog.SelectedPath, repositoryUrl.Split('/').LastOrDefault()); + modelTemplate.IsDownloading = true; + modelTemplate.CancellationTokenSource = new CancellationTokenSource(); + + // Download File, do not await + _ = Task.Factory.StartNew(async () => { - Name = addModelDialog.ModelName, - ModelSet = addModelDialog.ModelSet + modelTemplate.ErrorMessage = null; + modelTemplate.ProgressValue = 1; + modelTemplate.ProgressText = $"Starting Download..."; + Action progress = (f, fp, tp) => + { + modelTemplate.ProgressText = $"{f}"; + modelTemplate.ProgressValue = tp; + }; + try + { + var isDownloadComplete = !isRepostitoryClone + ? await _modelDownloadService.DownloadHttpAsync(modelTemplate.RepositoryFiles, outputDirectory, progress, modelTemplate.CancellationTokenSource.Token) + : await _modelDownloadService.DownloadRepositoryAsync(modelTemplate.RepositoryClone, outputDirectory, progress, modelTemplate.CancellationTokenSource.Token); + App.UIInvoke(async () => + { + if (isDownloadComplete) + { + if (modelTemplate.Category == ModelTemplateCategory.Upscaler) + await DownloadUpscaleModelComplete(modelTemplate, outputDirectory); + if (modelTemplate.Category == ModelTemplateCategory.StableDiffusion) + await DownloadStableDiffusionModelComplete(modelTemplate, outputDirectory); + } + + modelTemplate.IsDownloading = false; + }); + } + catch (Exception ex) + { + modelTemplate.IsDownloading = false; + modelTemplate.ProgressText = null; + modelTemplate.ProgressValue = 0; + modelTemplate.ErrorMessage = ex.Message; + } }); - - await SaveConfigurationFile(); } + return Task.CompletedTask; } - private async Task RemoveStableDiffusionModel() + private Task DownloadModelCancel() { - UISettings.StableDiffusionModelSets.Remove(SelectedStableDiffusionModel); - await SaveConfigurationFile(); - SelectedStableDiffusionModel = UISettings.StableDiffusionModelSets.FirstOrDefault(); + _selectedModelTemplate?.CancellationTokenSource?.Cancel(); + return Task.CompletedTask; } + private Task ModelTemplateLayout(LayoutViewType layoutViewType) + { + ModelTemplateLayoutView = layoutViewType; + return Task.CompletedTask; + } - private async Task UpdateStableDiffusionModel() + private async Task UpdateModelMetadata() { - var invalidNames = UISettings.StableDiffusionModelSets.Select(x => x.ModelSet.Name).ToList(); - var addModelDialog = _dialogService.GetDialog(); - if (addModelDialog.ShowDialog(SelectedStableDiffusionModel.ModelSet, invalidNames)) + var updateMetadataDialog = _dialogService.GetDialog(); + if (updateMetadataDialog.ShowDialog(_selectedModelTemplate)) { - SelectedStableDiffusionModel.Name = addModelDialog.ModelName; - SelectedStableDiffusionModel.ModelSet = addModelDialog.ModelSet; await SaveConfigurationFile(); } } - - + private Task ViewModelMetadata() + { + var viewMetadataDialog = _dialogService.GetDialog(); + viewMetadataDialog.ShowDialog(_selectedModelTemplate); + return Task.CompletedTask; + } private Task SaveConfigurationFile() { try { ConfigManager.SaveConfiguration(UISettings); + ModelTemplateRefresh(); return Task.FromResult(true); } catch (Exception ex) @@ -202,50 +353,30 @@ private Task SaveConfigurationFile() } - private Task Save() - { - try - { - ConfigManager.SaveConfiguration(UISettings); - } - catch (Exception ex) - { - _logger.LogError($"Error saving configuration file, {ex.Message}"); - } - return Task.CompletedTask; - } - - #region INotifyPropertyChanged - public event PropertyChangedEventHandler PropertyChanged; - - public void NotifyPropertyChanged([CallerMemberName] string property = "") - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); - } - #endregion - - - + #region ModelTemplate private void InitializeTemplates() { if (ModelTemplateCollectionView != null) ModelTemplateCollectionView.CollectionChanged -= ModelTemplateCollectionView_CollectionChanged; - foreach (var item in UISettings.Templates) + foreach (var template in UISettings.Templates.Where(x => x.IsUserTemplate)) { - item.IsInstalled = UISettings.StableDiffusionModelSets.Any(x => x.Name == item.Name); + template.IsInstalled = UISettings.UpscaleModelSets.Any(x => x.Name == template.Name) + || UISettings.StableDiffusionModelSets.Any(x => x.Name == template.Name); } + ModelTemplateFilterAuthors = UISettings.Templates + .Where(x => !string.IsNullOrEmpty(x.Author)) + .Select(x => x.Author) + .Distinct() + .OrderBy(x => x) + .ToList(); + ModelTemplateFilterAuthors.Insert(0, "All"); + ModelTemplateFilterAuthor = "All"; ModelTemplateCollectionView = new ListCollectionView(UISettings.Templates); ModelTemplateSort(); ModelTemplateCollectionView.Filter = ModelTemplateFilter; - ModelTemplateFilterAuthors = UISettings.Templates - .Where(x => !string.IsNullOrEmpty(x.Author)) - .Select(x => x.Author) - .Distinct() - .OrderBy(x => x) - .ToList(); ModelTemplateCollectionView.MoveCurrentToFirst(); SelectedModelTemplate = (ModelTemplateViewModel)ModelTemplateCollectionView.CurrentItem; ModelTemplateCollectionView.CollectionChanged += ModelTemplateCollectionView_CollectionChanged; @@ -274,8 +405,21 @@ private bool ModelTemplateFilter(object obj) return false; return (string.IsNullOrEmpty(_modelTemplateFilterText) || template.Name.Contains(_modelTemplateFilterText, StringComparison.OrdinalIgnoreCase)) - && (string.IsNullOrEmpty(_modelTemplateFilterAuthor) || _modelTemplateFilterAuthor.Equals(template.Author, StringComparison.OrdinalIgnoreCase)) - && (_modelTemplateFilterTemplateType is null || _modelTemplateFilterTemplateType == template.TemplateType); + && (_modelTemplateFilterAuthor == "All" || _modelTemplateFilterAuthor.Equals(template.Author, StringComparison.OrdinalIgnoreCase)) + && (_modelTemplateFilterTemplateType is null || _modelTemplateFilterTemplateType == template.Template) + && (_modelTemplateFilterStatus == ModelTemplateStatusFilter.All + || (_modelTemplateFilterStatus == ModelTemplateStatusFilter.Installed && template.IsInstalled && template.IsUserTemplate) + || (_modelTemplateFilterStatus == ModelTemplateStatusFilter.Uninstalled && !template.IsInstalled && template.IsUserTemplate) + || (_modelTemplateFilterStatus == ModelTemplateStatusFilter.Template && !template.IsUserTemplate)); + } + + private Task ModelTemplateFilterReset() + { + ModelTemplateFilterAuthor = "All"; + ModelTemplateFilterStatus = default; + ModelTemplateFilterTemplateType = null; + ModelTemplateFilterText = null; + return Task.CompletedTask; } @@ -289,224 +433,351 @@ private void ModelTemplateSort() { var inverseDirction = ModelTemplateSortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending; ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("IsInstalled", inverseDirction)); + ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("IsUserTemplate", ListSortDirection.Ascending)); + ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("Rank", ListSortDirection.Descending)); ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending)); return; } - ModelTemplateCollectionView.SortDescriptions.Add(new SortDescription(ModelTemplateSortProperty, ModelTemplateSortDirection)); } + #endregion - private ModelTemplateViewModel _selectedModelTemplate; + #region StableDiffusion Model - public ModelTemplateViewModel SelectedModelTemplate + private async Task AddStableDiffusionModel() { - get { return _selectedModelTemplate; } - set { _selectedModelTemplate = value; NotifyPropertyChanged(); } + var addModelDialog = _dialogService.GetDialog(); + if (addModelDialog.ShowDialog()) + { + var modelTemplate = addModelDialog.ModelTemplate; + if (modelTemplate == null) + return; // TODO: Error + + await InstallStableDiffusionModel(modelTemplate, addModelDialog.ModelSetResult); + } } + private async Task RemoveStableDiffusionModel(ModelTemplateViewModel modelTemplate) + { + if (!modelTemplate.IsUserTemplate) + return; // TODO: Cant remove Templates + if (modelTemplate.Category != ModelTemplateCategory.StableDiffusion) + return; // TODO: Error - private ICollectionView _modelTemplateCollectionView; + var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + UISettings.StableDiffusionModelSets.Remove(modelSet); + UISettings.Templates.Remove(modelTemplate); + await SaveConfigurationFile(); + } - public ICollectionView ModelTemplateCollectionView + + private async Task InstallStableDiffusionModel(ModelTemplateViewModel modelTemplate) { - get { return _modelTemplateCollectionView; } - set { _modelTemplateCollectionView = value; NotifyPropertyChanged(); } + var addModelDialog = _dialogService.GetDialog(); + if (!addModelDialog.ShowDialog(modelTemplate)) + return; // User Canceled + + await InstallStableDiffusionModel(modelTemplate, addModelDialog.ModelSetResult); } + private async Task InstallStableDiffusionModel(ModelTemplateViewModel modelTemplate, StableDiffusionModelSet modelSetResult) + { + if (modelTemplate.IsUserTemplate) + { + modelTemplate.IsInstalled = true; + } + else + { + var newModelTemplate = new ModelTemplateViewModel + { + Name = modelSetResult.Name, + Category = ModelTemplateCategory.StableDiffusion, + IsInstalled = true, + IsUserTemplate = true, + ImageIcon = string.Empty,// modelTemplate.ImageIcon, + Author = "Unknown", //modelTemplate.Author, + Template = modelTemplate.Template, + StableDiffusionTemplate = modelTemplate.StableDiffusionTemplate with { }, + }; + UISettings.Templates.Add(newModelTemplate); + SelectedModelTemplate = newModelTemplate; + } + UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel + { + IsEnabled = true, + Name = modelSetResult.Name, + ModelSet = modelSetResult + }); + await SaveConfigurationFile(); + } + private async Task UninstallStableDiffusionModel(ModelTemplateViewModel modelTemplate) + { + if (modelTemplate.Category != ModelTemplateCategory.StableDiffusion) + return; // TODO: Error + var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + UISettings.StableDiffusionModelSets.Remove(modelSet); - private string _modelTemplateSortProperty; - private ListSortDirection _modelTemplateSortDirection; - private string _modelTemplateFilterText; - private string _modelTemplateFilterAuthor; - private List _modelTemplateFilterAuthors; + modelTemplate.IsInstalled = false; + await SaveConfigurationFile(); + } - public string ModelTemplateSortProperty + private async Task UpdateStableDiffusionModel(ModelTemplateViewModel modelTemplate) { - get { return _modelTemplateSortProperty; } - set { _modelTemplateSortProperty = value; NotifyPropertyChanged(); ModelTemplateSort(); } + var stableDiffusionModel = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (stableDiffusionModel == null) + return; // TODO: Error + + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(stableDiffusionModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + stableDiffusionModel.ModelSet = modelSet; + stableDiffusionModel.Name = modelSet.Name; + stableDiffusionModel.IsEnabled = modelSet.IsEnabled; + SelectedModelTemplate.Name = modelSet.Name; + await SaveConfigurationFile(); + } } - public ListSortDirection ModelTemplateSortDirection + + private async Task UpdateStableDiffusionModelAdvanced(ModelTemplateViewModel modelTemplate) { - get { return _modelTemplateSortDirection; } - set { _modelTemplateSortDirection = value; NotifyPropertyChanged(); ModelTemplateSort(); } + var stableDiffusionModel = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (stableDiffusionModel == null) + return; // TODO: Error + + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(stableDiffusionModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + stableDiffusionModel.ModelSet = modelSet; + stableDiffusionModel.Name = modelSet.Name; + stableDiffusionModel.IsEnabled = modelSet.IsEnabled; + SelectedModelTemplate.Name = modelSet.Name; + await SaveConfigurationFile(); + } } - public string ModelTemplateFilterText + private async Task DownloadStableDiffusionModelComplete(ModelTemplateViewModel modelTemplate, string outputDirectory) { - get { return _modelTemplateFilterText; } - set { _modelTemplateFilterText = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } - } + var modelSet = _modelFactory.CreateStableDiffusionModelSet(modelTemplate.Name, outputDirectory, modelTemplate.StableDiffusionTemplate); + var isModelSetValid = modelSet.ModelConfigurations.All(x => File.Exists(x.OnnxModelPath)); + if (!isModelSetValid) + { + // Error, Invalid modelset after download + modelTemplate.IsDownloading = false; + modelTemplate.ErrorMessage = "Error: Download completed but ModelSet is invalid"; + return; + } - private ModelTemplateType? _modelTemplateFilterTemplateType; + UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel + { + IsEnabled = true, + Name = modelSet.Name, + ModelSet = modelSet + }); - public ModelTemplateType? ModelTemplateFilterTemplateType - { - get { return _modelTemplateFilterTemplateType; } - set { _modelTemplateFilterTemplateType = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + // Update/Save + modelTemplate.IsInstalled = true; + await SaveConfigurationFile(); } + #endregion - public string ModelTemplateFilterAuthor + #region Upscale Model + + private async Task AddUpscaleModel() { - get { return _modelTemplateFilterAuthor; } - set { _modelTemplateFilterAuthor = value; NotifyPropertyChanged(); ModelTemplateRefresh(); } + var addModelDialog = _dialogService.GetDialog(); + if (addModelDialog.ShowDialog()) + { + var modelTemplate = addModelDialog.ModelTemplate; + if (modelTemplate == null) + return; // TODO: Error + + await InstallUpscaleModel(modelTemplate, addModelDialog.ModelSetResult); + } } - public List ModelTemplateFilterAuthors + private async Task UpdateUpscaleModel(ModelTemplateViewModel modelTemplate) { - get { return _modelTemplateFilterAuthors; } - set { _modelTemplateFilterAuthors = value; NotifyPropertyChanged(); } - } + var upscaleModel = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (upscaleModel == null) + return; // TODO: Error - private LayoutViewType _modelTemplateLayoutView; + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(upscaleModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + upscaleModel.ModelSet = modelSet; + upscaleModel.Name = modelSet.Name; + upscaleModel.IsEnabled = modelSet.IsEnabled; + SelectedModelTemplate.Name = modelSet.Name; + await SaveConfigurationFile(); + } + } - public LayoutViewType ModelTemplateLayoutView + private async Task UpdateUpscaleModelAdvanced(ModelTemplateViewModel modelTemplate) { - get { return _modelTemplateLayoutView; } - set { _modelTemplateLayoutView = value; NotifyPropertyChanged(); } - } + var upscaleModel = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (upscaleModel == null) + return; // TODO: Error + var updateModelDialog = _dialogService.GetDialog(); + if (updateModelDialog.ShowDialog(upscaleModel.ModelSet)) + { + var modelSet = updateModelDialog.ModelSetResult; + upscaleModel.ModelSet = modelSet; + upscaleModel.Name = modelSet.Name; + upscaleModel.IsEnabled = modelSet.IsEnabled; + SelectedModelTemplate.Name = modelSet.Name; + await SaveConfigurationFile(); + } + } + private async Task RemoveUpscaleModel(ModelTemplateViewModel modelTemplate) + { + if (!modelTemplate.IsUserTemplate) + return; // TODO: Cant remove Templates + if (modelTemplate.Category != ModelTemplateCategory.Upscaler) + return; // TODO: Error + var modelSet = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + UISettings.UpscaleModelSets.Remove(modelSet); + UISettings.Templates.Remove(modelTemplate); + await SaveConfigurationFile(); + } + private async Task InstallUpscaleModel(ModelTemplateViewModel modelTemplate) + { + var addModelDialog = _dialogService.GetDialog(); + if (!addModelDialog.ShowDialog(modelTemplate)) + return; // User Canceled + await InstallUpscaleModel(modelTemplate, addModelDialog.ModelSetResult); + } - private async Task InstallLocalStableDiffusionModel() + private async Task InstallUpscaleModel(ModelTemplateViewModel modelTemplate, UpscaleModelSet modelSetResult) { - var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); - if (modelTemplate == null) - return; // TODO: Error - - var folderDialog = new System.Windows.Forms.FolderBrowserDialog(); - if (folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) + if (modelTemplate.IsUserTemplate) { - if (_selectedModelTemplate.TemplateType == ModelTemplateType.Upscaler) - { - - } - else + modelTemplate.IsInstalled = true; + } + else + { + var newModelTemplate = new ModelTemplateViewModel { - var stableDiffusionTemplate = _selectedModelTemplate.StableDiffusionTemplate; - if (stableDiffusionTemplate == null) - return; // TODO: Error - - var modelSet = _modelFactory.CreateModelSet(modelTemplate.Name, folderDialog.SelectedPath, stableDiffusionTemplate.PipelineType, stableDiffusionTemplate.ModelType); - var isModelSetValid = modelSet.ModelConfigurations.All(x => File.Exists(x.OnnxModelPath)); - if (isModelSetValid == false) - return; // TODO: Error - - UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel - { - Name = modelSet.Name, - ModelSet = modelSet - }); - } + Name = modelSetResult.Name, + Category = ModelTemplateCategory.Upscaler, + IsInstalled = true, + IsUserTemplate = true, + ImageIcon = string.Empty,// modelTemplate.ImageIcon, + Author = "Unknown", //modelTemplate.Author, + Template = modelTemplate.Template, + UpscaleTemplate = modelTemplate.UpscaleTemplate with { }, + }; + UISettings.Templates.Add(newModelTemplate); + SelectedModelTemplate = newModelTemplate; } - // Update/Save - UISettings.Templates.Remove(modelTemplate); - modelTemplate.IsInstalled = true; - UISettings.Templates.Add(modelTemplate); - SelectedModelTemplate = modelTemplate; + UISettings.UpscaleModelSets.Add(new UpscaleModelSetViewModel + { + IsEnabled = true, + Name = modelSetResult.Name, + ModelSet = modelSetResult + }); await SaveConfigurationFile(); } - private async Task UninstallStableDiffusionModel() + private async Task UninstallUpscaleModel(ModelTemplateViewModel modelTemplate) { - //TODO: Unload - var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == SelectedModelTemplate.Name); - UISettings.StableDiffusionModelSets.Remove(modelSet); - - var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); - if (modelTemplate == null) + if (modelTemplate.Category != ModelTemplateCategory.Upscaler) return; // TODO: Error - if (modelTemplate.IsUserTemplate) - UISettings.Templates.Remove(modelTemplate); + var modelSet = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + UISettings.UpscaleModelSets.Remove(modelSet); - UISettings.Templates.Remove(modelTemplate); modelTemplate.IsInstalled = false; - UISettings.Templates.Add(modelTemplate); - - SelectedModelTemplate = modelTemplate; await SaveConfigurationFile(); } - - private async Task RenameStableDiffusionModel() + private async Task DownloadUpscaleModelComplete(ModelTemplateViewModel modelTemplate, string outputDirectory) { - var invalidNames = UISettings.Templates.Select(x => x.Name).ToList(); - var addModelDialog = _dialogService.GetDialog(); - if (addModelDialog.ShowDialog("Rename Model", "New Name", 1, 50, invalidNames)) + var modelSet = _modelFactory.CreateUpscaleModelSet(modelTemplate.Name, outputDirectory, modelTemplate.UpscaleTemplate); + var isModelSetValid = modelSet.ModelConfigurations.All(x => File.Exists(x.OnnxModelPath)); + if (!isModelSetValid) { - var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); - modelSet.Name = addModelDialog.TextResult; - modelSet.ModelSet.Name = addModelDialog.TextResult; + // Error, Invalid modelset after download + modelTemplate.IsDownloading = false; + modelTemplate.ErrorMessage = "Error: Download completed but ModelSet is invalid"; + return; + } - var modelTemplate = UISettings.Templates.FirstOrDefault(x => x.Name == _selectedModelTemplate.Name); - if (modelTemplate == null) - return; // TODO: Error + UISettings.UpscaleModelSets.Add(new UpscaleModelSetViewModel + { + IsEnabled = true, + Name = modelSet.Name, + ModelSet = modelSet + }); - UISettings.Templates.Remove(modelTemplate); - if (!modelTemplate.IsUserTemplate) - { - modelTemplate.IsInstalled = false; - var userTemplate = modelTemplate with - { - IsInstalled = true, - IsUserTemplate = true, - Name = addModelDialog.TextResult - }; - UISettings.Templates.Add(modelTemplate); - UISettings.Templates.Add(userTemplate); - SelectedModelTemplate = userTemplate; - } - else - { - modelTemplate.Name = addModelDialog.TextResult; - UISettings.Templates.Add(modelTemplate); - } - await SaveConfigurationFile(); - } + // Update/Save + modelTemplate.IsInstalled = true; + await SaveConfigurationFile(); } + + #endregion + + #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + + public void NotifyPropertyChanged([CallerMemberName] string property = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); + } + #endregion } public enum LayoutViewType { - Tile = 0, - List = 1 + TileLarge = 0, + TileSmall = 1, + List = 2 } - public enum ModelTemplateType + + public enum ModelTemplateCategory { StableDiffusion = 0, - StableDiffusionXL = 1, - LatentConsistency = 10, - LatentConsistencyXL = 11, - InstaFlow = 30, - Upscaler = 100, - Other = 255 + Upscaler = 1 } - - public class UpscaleModelSetViewModel + public enum ModelTemplateStatusFilter { - public string Name { get; set; } - public UpscaleModelSet ModelSet { get; set; } + All = 0, + Installed = 1, + Template = 2, + Uninstalled = 3 } - public record ModelTemplateViewModel : INotifyPropertyChanged + public class ModelTemplateViewModel : INotifyPropertyChanged { private string _name; + private string _imageIcon; + private string _author; + + private bool _isInstalled; + private bool _isDownloading; + private double _progressValue; + private string _progressText; + private string _errorMessage; public string Name { @@ -514,36 +785,51 @@ public string Name set { _name = value; NotifyPropertyChanged(); } } - - private string _imageIcon; - public string ImageIcon { get { return _imageIcon; } - set { _imageIcon = value; } + set { _imageIcon = value; NotifyPropertyChanged(); } } - - private string _author; - public string Author { get { return _author; } - set { _author = value; } + set { _author = value; NotifyPropertyChanged(); } } + private string _description; - private ModelTemplateType _templateType; - - public ModelTemplateType TemplateType + public string Description { - get { return _templateType; } - set { _templateType = value; } + get { return _description; } + set { _description = value; NotifyPropertyChanged(); } } + public int Rank { get; set; } + public bool IsUserTemplate { get; set; } + public string Template { get; set; } + + public ModelTemplateCategory Category { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public UpscaleModelTemplate UpscaleTemplate { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public StableDiffusionModelTemplate StableDiffusionTemplate { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Repository { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string RepositoryClone { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List RepositoryFiles { get; set; } + + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public List PreviewImages { get; set; } - private bool _isInstalled; [JsonIgnore] public bool IsInstalled @@ -552,27 +838,20 @@ public bool IsInstalled set { _isInstalled = value; NotifyPropertyChanged(); } } - - private bool _isDownloading; - [JsonIgnore] public bool IsDownloading { get { return _isDownloading; } - set { _isDownloading = value; } + set { _isDownloading = value; NotifyPropertyChanged(); } } - private int _progressValue; - [JsonIgnore] - public int ProgressValue + public double ProgressValue { get { return _progressValue; } set { _progressValue = value; NotifyPropertyChanged(); } } - private string _progressText; - [JsonIgnore] public string ProgressText { @@ -580,11 +859,21 @@ public string ProgressText set { _progressText = value; NotifyPropertyChanged(); } } - public bool IsUserTemplate { get; set; } + [JsonIgnore] + public string ErrorMessage + { + get { return _errorMessage; } + set { _errorMessage = value; NotifyPropertyChanged(); } + } + [JsonIgnore] + public bool IsRepositoryCloneEnabled => !string.IsNullOrEmpty(RepositoryClone); - public StableDiffusionModelTemplate StableDiffusionTemplate { get; set; } + [JsonIgnore] + public bool IsRepositoryDownloadEnabled => !RepositoryFiles.IsNullOrEmpty(); + [JsonIgnore] + public CancellationTokenSource CancellationTokenSource { get; set; } #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; @@ -596,6 +885,6 @@ public void NotifyPropertyChanged([CallerMemberName] string property = "") #endregion } - public record StableDiffusionModelTemplate(DiffuserPipelineType PipelineType, ModelType ModelType); + } diff --git a/OnnxStack.UI/Views/ModelView.xaml b/OnnxStack.UI/Views/ModelView.xaml deleted file mode 100644 index 6c882bc4..00000000 --- a/OnnxStack.UI/Views/ModelView.xaml +++ /dev/null @@ -1,469 +0,0 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + diff --git a/OnnxStack.UI/UserControls/UpscalePickerControl.xaml b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml index 3fa13b95..e0186973 100644 --- a/OnnxStack.UI/UserControls/UpscalePickerControl.xaml +++ b/OnnxStack.UI/UserControls/UpscalePickerControl.xaml @@ -49,14 +49,17 @@ - - - - + + + + + + + diff --git a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs index 4ab934ac..355eb77c 100644 --- a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs +++ b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs @@ -42,7 +42,7 @@ public partial class ModelSettingsView : UserControl, INavigatable, INotifyPrope private List _modelTemplateFilterAuthors; private ModelTemplateStatusFilter _modelTemplateFilterStatus; - private LayoutViewType _modelTemplateLayoutView; + private LayoutViewType _modelTemplateLayoutView = LayoutViewType.TileSmall; private string _modelTemplateSortProperty; private ListSortDirection _modelTemplateSortDirection; @@ -507,7 +507,6 @@ private async Task InstallStableDiffusionModel(ModelTemplateViewModel modelTempl UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel { - IsEnabled = true, Name = modelSetResult.Name, ModelSet = modelSetResult }); @@ -538,7 +537,6 @@ private async Task UpdateStableDiffusionModel(ModelTemplateViewModel modelTempla var modelSet = updateModelDialog.ModelSetResult; stableDiffusionModel.ModelSet = modelSet; stableDiffusionModel.Name = modelSet.Name; - stableDiffusionModel.IsEnabled = modelSet.IsEnabled; SelectedModelTemplate.Name = modelSet.Name; await SaveConfigurationFile(); } @@ -557,7 +555,6 @@ private async Task UpdateStableDiffusionModelAdvanced(ModelTemplateViewModel mod var modelSet = updateModelDialog.ModelSetResult; stableDiffusionModel.ModelSet = modelSet; stableDiffusionModel.Name = modelSet.Name; - stableDiffusionModel.IsEnabled = modelSet.IsEnabled; SelectedModelTemplate.Name = modelSet.Name; await SaveConfigurationFile(); } @@ -577,7 +574,6 @@ private async Task DownloadStableDiffusionModelComplete(ModelTemplateViewModel m UISettings.StableDiffusionModelSets.Add(new StableDiffusionModelSetViewModel { - IsEnabled = true, Name = modelSet.Name, ModelSet = modelSet }); @@ -616,7 +612,6 @@ private async Task UpdateUpscaleModel(ModelTemplateViewModel modelTemplate) var modelSet = updateModelDialog.ModelSetResult; upscaleModel.ModelSet = modelSet; upscaleModel.Name = modelSet.Name; - upscaleModel.IsEnabled = modelSet.IsEnabled; SelectedModelTemplate.Name = modelSet.Name; await SaveConfigurationFile(); } @@ -634,7 +629,6 @@ private async Task UpdateUpscaleModelAdvanced(ModelTemplateViewModel modelTempla var modelSet = updateModelDialog.ModelSetResult; upscaleModel.ModelSet = modelSet; upscaleModel.Name = modelSet.Name; - upscaleModel.IsEnabled = modelSet.IsEnabled; SelectedModelTemplate.Name = modelSet.Name; await SaveConfigurationFile(); } @@ -688,7 +682,6 @@ private async Task InstallUpscaleModel(ModelTemplateViewModel modelTemplate, Ups UISettings.UpscaleModelSets.Add(new UpscaleModelSetViewModel { - IsEnabled = true, Name = modelSetResult.Name, ModelSet = modelSetResult }); @@ -722,7 +715,6 @@ private async Task DownloadUpscaleModelComplete(ModelTemplateViewModel modelTemp UISettings.UpscaleModelSets.Add(new UpscaleModelSetViewModel { - IsEnabled = true, Name = modelSet.Name, ModelSet = modelSet }); From 225e1855bf0883c1477dc900c56a97fb0212e899 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Wed, 20 Dec 2023 09:17:15 +1300 Subject: [PATCH 06/15] Simplify ModelTemplate website and repository metadata --- .../Dialogs/UpdateModelMetadataDialog.xaml | 2 +- .../Dialogs/UpdateModelMetadataDialog.xaml.cs | 25 ++++++++----------- .../Dialogs/ViewModelMetadataDialog.xaml | 4 +-- OnnxStack.UI/Views/ModelSettingsView.xaml.cs | 19 ++++++++++++-- OnnxStack.UI/appsettings.json | 3 ++- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml b/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml index 0e4b7811..40798b2b 100644 --- a/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml +++ b/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml @@ -104,7 +104,7 @@ - + diff --git a/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml.cs b/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml.cs index 1f6b62c1..4483b3b6 100644 --- a/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml.cs +++ b/OnnxStack.UI/Dialogs/UpdateModelMetadataDialog.xaml.cs @@ -80,12 +80,12 @@ public string IconImage set { _iconImage = value; NotifyPropertyChanged(); } } - private string _repositoryClone; + private string _repository; - public string RepositoryClone + public string Repository { - get { return _repositoryClone; } - set { _repositoryClone = value; NotifyPropertyChanged(); } + get { return _repository; } + set { _repository = value; NotifyPropertyChanged(); } } private string _repositoryBranch; @@ -105,15 +105,13 @@ public bool ShowDialog(ModelTemplateViewModel modelTemplate) { _modelTemplate = modelTemplate; - Website = _modelTemplate.Repository; + Website = _modelTemplate.Website; Author = _modelTemplate.Author; Description = _modelTemplate.Description; IconImage = _modelTemplate.ImageIcon; - - var repository = _modelTemplate.RepositoryClone?.Split("-b", StringSplitOptions.TrimEntries); - RepositoryClone = repository?.FirstOrDefault(); - RepositoryBranch = repository?.LastOrDefault(); - + Repository = _modelTemplate.Repository; + RepositoryBranch = _modelTemplate.RepositoryBranch; + for (int i = 0; i < 4; i++) { PreviewImages.Add(_modelTemplate.PreviewImages?.ElementAtOrDefault(i)); @@ -129,13 +127,12 @@ public bool ShowDialog(ModelTemplateViewModel modelTemplate) private Task Save() { // validate links; - _modelTemplate.Repository = Website; + _modelTemplate.Website = Website; _modelTemplate.Author = Author; _modelTemplate.ImageIcon = IconImage; _modelTemplate.Description = Description; - _modelTemplate.RepositoryClone = string.IsNullOrEmpty(_repositoryBranch) - ? RepositoryClone - : $"{_repositoryClone} -b {_repositoryBranch}"; + _modelTemplate.Repository = Repository; + _modelTemplate.RepositoryBranch = RepositoryBranch; _modelTemplate.PreviewImages = PreviewImages.Where(x => !string.IsNullOrEmpty(x)).ToList(); _modelTemplate.RepositoryFiles = RepositoryFiles.Where(x => !string.IsNullOrEmpty(x)).ToList(); diff --git a/OnnxStack.UI/Dialogs/ViewModelMetadataDialog.xaml b/OnnxStack.UI/Dialogs/ViewModelMetadataDialog.xaml index 71a84c95..3035fc9d 100644 --- a/OnnxStack.UI/Dialogs/ViewModelMetadataDialog.xaml +++ b/OnnxStack.UI/Dialogs/ViewModelMetadataDialog.xaml @@ -37,7 +37,7 @@ - + @@ -51,7 +51,7 @@ - + diff --git a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs index 355eb77c..0e8f40cd 100644 --- a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs +++ b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs @@ -810,11 +810,14 @@ public string Description [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public StableDiffusionModelTemplate StableDiffusionTemplate { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string Website { get; set; } + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string Repository { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] - public string RepositoryClone { get; set; } + public string RepositoryBranch { get; set; } [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List RepositoryFiles { get; set; } @@ -822,6 +825,16 @@ public string Description [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public List PreviewImages { get; set; } + [JsonIgnore] + public string RepositoryClone + { + get + { + return string.IsNullOrEmpty(RepositoryBranch) + ? Repository + : $"{Repository} -b {RepositoryBranch}"; + } + } [JsonIgnore] public bool IsInstalled @@ -859,7 +872,7 @@ public string ErrorMessage } [JsonIgnore] - public bool IsRepositoryCloneEnabled => !string.IsNullOrEmpty(RepositoryClone); + public bool IsRepositoryCloneEnabled => !string.IsNullOrEmpty(Repository); [JsonIgnore] public bool IsRepositoryDownloadEnabled => !RepositoryFiles.IsNullOrEmpty(); @@ -867,6 +880,8 @@ public string ErrorMessage [JsonIgnore] public CancellationTokenSource CancellationTokenSource { get; set; } + + #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; diff --git a/OnnxStack.UI/appsettings.json b/OnnxStack.UI/appsettings.json index f9902d2e..1b0fa96f 100644 --- a/OnnxStack.UI/appsettings.json +++ b/OnnxStack.UI/appsettings.json @@ -44,6 +44,7 @@ "DefaultIntraOpNumThreads": 0, "DefaultExecutionMode": "ORT_SEQUENTIAL", "DefaultExecutionProvider": "DirectML", + "Templates": [ { "Name": "StableDiffusion", @@ -207,7 +208,7 @@ ] }, "Repository": "https://huggingface.co/runwayml/stable-diffusion-v1-5", - "RepositoryClone": "https://huggingface.co/runwayml/stable-diffusion-v1-5 -b onnx", + "RepositoryBranch": "onnx", "RepositoryFiles": [ "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/unet/model.onnx", "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/onnx/unet/weights.pb", From 7ec35e050c58ff30920b41eaabf3f2d068f1c1f9 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Wed, 20 Dec 2023 18:29:20 +1300 Subject: [PATCH 07/15] Filter ModelPicker by supported diffusers --- .../UserControls/ModelPickerControl.xaml | 3 +- .../UserControls/ModelPickerControl.xaml.cs | 35 ++++++++++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/OnnxStack.UI/UserControls/ModelPickerControl.xaml b/OnnxStack.UI/UserControls/ModelPickerControl.xaml index 4206e2f9..0d0ebd60 100644 --- a/OnnxStack.UI/UserControls/ModelPickerControl.xaml +++ b/OnnxStack.UI/UserControls/ModelPickerControl.xaml @@ -52,8 +52,9 @@ diff --git a/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs b/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs index d2a31269..f6a2d284 100644 --- a/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs +++ b/OnnxStack.UI/UserControls/ModelPickerControl.xaml.cs @@ -12,6 +12,7 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Data; namespace OnnxStack.UI.UserControls { @@ -22,6 +23,7 @@ public partial class ModelPickerControl : UserControl, INotifyPropertyChanged { private readonly ILogger _logger; private readonly IStableDiffusionService _stableDiffusionService; + private ICollectionView _modelCollectionView; /// Initializes a new instance of the class. public ModelPickerControl() @@ -46,8 +48,11 @@ public OnnxStackUIConfig UISettings set { SetValue(UISettingsProperty, value); } } public static readonly DependencyProperty UISettingsProperty = - DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(ModelPickerControl)); - + DependencyProperty.Register("UISettings", typeof(OnnxStackUIConfig), typeof(ModelPickerControl), new PropertyMetadata((d, e) => + { + if (d is ModelPickerControl control && e.NewValue is OnnxStackUIConfig settings) + control.InitializeModels(); + })); /// /// Gets or sets the supported diffusers. @@ -58,8 +63,11 @@ public List SupportedDiffusers set { SetValue(SupportedDiffusersProperty, value); } } public static readonly DependencyProperty SupportedDiffusersProperty = - DependencyProperty.Register("SupportedDiffusers", typeof(List), typeof(ModelPickerControl)); - + DependencyProperty.Register("SupportedDiffusers", typeof(List), typeof(ModelPickerControl), new PropertyMetadata((d, e) => + { + if (d is ModelPickerControl control && e.NewValue is List diffusers) + control.ModelCollectionView?.Refresh(); + })); /// /// Gets or sets the selected model. @@ -73,6 +81,25 @@ public StableDiffusionModelSetViewModel SelectedModel DependencyProperty.Register("SelectedModel", typeof(StableDiffusionModelSetViewModel), typeof(ModelPickerControl)); + public ICollectionView ModelCollectionView + { + get { return _modelCollectionView; } + set { _modelCollectionView = value; NotifyPropertyChanged(); } + } + + + private void InitializeModels() + { + ModelCollectionView = new ListCollectionView(UISettings.StableDiffusionModelSets); + ModelCollectionView.Filter = (obj) => + { + if (obj is not StableDiffusionModelSetViewModel viewModel) + return false; + + return viewModel.ModelSet.Diffusers.Intersect(SupportedDiffusers).Any(); + }; + } + /// /// Loads the model. From ff3d5386a25a1d4f0d03df1007ad90d9d579f461 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Wed, 20 Dec 2023 18:36:48 +1300 Subject: [PATCH 08/15] Trigger NotifyCollectionChanged event on in certain situations --- OnnxStack.UI/Utils.cs | 14 ++++++++++++++ OnnxStack.UI/Views/ModelSettingsView.xaml.cs | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/OnnxStack.UI/Utils.cs b/OnnxStack.UI/Utils.cs index a22e93f1..b1079c72 100644 --- a/OnnxStack.UI/Utils.cs +++ b/OnnxStack.UI/Utils.cs @@ -3,9 +3,11 @@ using OnnxStack.StableDiffusion.Enums; using OnnxStack.UI.Models; using System; +using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Reflection; +using System.Runtime; using System.Text.Json; using System.Text.Json.Serialization; using System.Threading; @@ -208,5 +210,17 @@ public static void LogToWindow(string message) (System.Windows.Application.Current.MainWindow as MainWindow).UpdateOutputLog(message); })); } + + + /// + /// Forces the notify collection changed event. + /// + /// + /// The collection. + public static void ForceNotifyCollectionChanged(this ObservableCollection collection) + { + // Hack: Moving an item will invoke a collection changed event + collection?.Move(0, 0); + } } } diff --git a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs index 0e8f40cd..863639f2 100644 --- a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs +++ b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs @@ -12,6 +12,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; using System.Threading; @@ -538,6 +539,7 @@ private async Task UpdateStableDiffusionModel(ModelTemplateViewModel modelTempla stableDiffusionModel.ModelSet = modelSet; stableDiffusionModel.Name = modelSet.Name; SelectedModelTemplate.Name = modelSet.Name; + UISettings.StableDiffusionModelSets.ForceNotifyCollectionChanged(); await SaveConfigurationFile(); } } @@ -556,6 +558,7 @@ private async Task UpdateStableDiffusionModelAdvanced(ModelTemplateViewModel mod stableDiffusionModel.ModelSet = modelSet; stableDiffusionModel.Name = modelSet.Name; SelectedModelTemplate.Name = modelSet.Name; + UISettings.StableDiffusionModelSets.ForceNotifyCollectionChanged(); await SaveConfigurationFile(); } } @@ -613,6 +616,7 @@ private async Task UpdateUpscaleModel(ModelTemplateViewModel modelTemplate) upscaleModel.ModelSet = modelSet; upscaleModel.Name = modelSet.Name; SelectedModelTemplate.Name = modelSet.Name; + UISettings.UpscaleModelSets.ForceNotifyCollectionChanged(); await SaveConfigurationFile(); } } @@ -630,6 +634,7 @@ private async Task UpdateUpscaleModelAdvanced(ModelTemplateViewModel modelTempla upscaleModel.ModelSet = modelSet; upscaleModel.Name = modelSet.Name; SelectedModelTemplate.Name = modelSet.Name; + UISettings.UpscaleModelSets.ForceNotifyCollectionChanged(); await SaveConfigurationFile(); } } From 00bd79f5cd5aa88054b23fcf04a5a0ede2153d71 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Wed, 20 Dec 2023 18:56:39 +1300 Subject: [PATCH 09/15] Error handling --- OnnxStack.UI/Views/ModelSettingsView.xaml.cs | 85 ++++++++++++-------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs index 863639f2..93949660 100644 --- a/OnnxStack.UI/Views/ModelSettingsView.xaml.cs +++ b/OnnxStack.UI/Views/ModelSettingsView.xaml.cs @@ -12,7 +12,6 @@ using System.Diagnostics; using System.IO; using System.Linq; -using System.Runtime; using System.Runtime.CompilerServices; using System.Text.Json.Serialization; using System.Threading; @@ -451,22 +450,22 @@ private async Task AddStableDiffusionModel() var addModelDialog = _dialogService.GetDialog(); if (addModelDialog.ShowDialog()) { - var modelTemplate = addModelDialog.ModelTemplate; - if (modelTemplate == null) - return; // TODO: Error - - await InstallStableDiffusionModel(modelTemplate, addModelDialog.ModelSetResult); + await InstallStableDiffusionModel(addModelDialog.ModelTemplate, addModelDialog.ModelSetResult); } } private async Task RemoveStableDiffusionModel(ModelTemplateViewModel modelTemplate) { if (!modelTemplate.IsUserTemplate) - return; // TODO: Cant remove Templates - if (modelTemplate.Category != ModelTemplateCategory.StableDiffusion) - return; // TODO: Error + return; // Cant remove Templates var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + UISettings.StableDiffusionModelSets.Remove(modelSet); UISettings.Templates.Remove(modelTemplate); await SaveConfigurationFile(); @@ -516,12 +515,14 @@ private async Task InstallStableDiffusionModel(ModelTemplateViewModel modelTempl private async Task UninstallStableDiffusionModel(ModelTemplateViewModel modelTemplate) { - if (modelTemplate.Category != ModelTemplateCategory.StableDiffusion) - return; // TODO: Error - var modelSet = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); - UISettings.StableDiffusionModelSets.Remove(modelSet); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + UISettings.StableDiffusionModelSets.Remove(modelSet); modelTemplate.IsInstalled = false; await SaveConfigurationFile(); } @@ -529,8 +530,12 @@ private async Task UninstallStableDiffusionModel(ModelTemplateViewModel modelTem private async Task UpdateStableDiffusionModel(ModelTemplateViewModel modelTemplate) { var stableDiffusionModel = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); - if (stableDiffusionModel == null) - return; // TODO: Error + if (stableDiffusionModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + var updateModelDialog = _dialogService.GetDialog(); if (updateModelDialog.ShowDialog(stableDiffusionModel.ModelSet)) @@ -548,8 +553,11 @@ private async Task UpdateStableDiffusionModel(ModelTemplateViewModel modelTempla private async Task UpdateStableDiffusionModelAdvanced(ModelTemplateViewModel modelTemplate) { var stableDiffusionModel = UISettings.StableDiffusionModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); - if (stableDiffusionModel == null) - return; // TODO: Error + if (stableDiffusionModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } var updateModelDialog = _dialogService.GetDialog(); if (updateModelDialog.ShowDialog(stableDiffusionModel.ModelSet)) @@ -595,19 +603,19 @@ private async Task AddUpscaleModel() var addModelDialog = _dialogService.GetDialog(); if (addModelDialog.ShowDialog()) { - var modelTemplate = addModelDialog.ModelTemplate; - if (modelTemplate == null) - return; // TODO: Error - - await InstallUpscaleModel(modelTemplate, addModelDialog.ModelSetResult); + await InstallUpscaleModel(addModelDialog.ModelTemplate, addModelDialog.ModelSetResult); } } private async Task UpdateUpscaleModel(ModelTemplateViewModel modelTemplate) { var upscaleModel = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); - if (upscaleModel == null) - return; // TODO: Error + if (upscaleModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + var updateModelDialog = _dialogService.GetDialog(); if (updateModelDialog.ShowDialog(upscaleModel.ModelSet)) @@ -624,8 +632,11 @@ private async Task UpdateUpscaleModel(ModelTemplateViewModel modelTemplate) private async Task UpdateUpscaleModelAdvanced(ModelTemplateViewModel modelTemplate) { var upscaleModel = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); - if (upscaleModel == null) - return; // TODO: Error + if (upscaleModel.IsLoaded) + { + MessageBox.Show("Please unload model before updating", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } var updateModelDialog = _dialogService.GetDialog(); if (updateModelDialog.ShowDialog(upscaleModel.ModelSet)) @@ -642,11 +653,15 @@ private async Task UpdateUpscaleModelAdvanced(ModelTemplateViewModel modelTempla private async Task RemoveUpscaleModel(ModelTemplateViewModel modelTemplate) { if (!modelTemplate.IsUserTemplate) - return; // TODO: Cant remove Templates - if (modelTemplate.Category != ModelTemplateCategory.Upscaler) - return; // TODO: Error - + return; // Cant remove Templates + var modelSet = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + UISettings.UpscaleModelSets.Remove(modelSet); UISettings.Templates.Remove(modelTemplate); await SaveConfigurationFile(); @@ -696,12 +711,14 @@ private async Task InstallUpscaleModel(ModelTemplateViewModel modelTemplate, Ups private async Task UninstallUpscaleModel(ModelTemplateViewModel modelTemplate) { - if (modelTemplate.Category != ModelTemplateCategory.Upscaler) - return; // TODO: Error - var modelSet = UISettings.UpscaleModelSets.FirstOrDefault(x => x.Name == modelTemplate.Name); - UISettings.UpscaleModelSets.Remove(modelSet); + if (modelSet.IsLoaded) + { + MessageBox.Show("Please unload model before uninstalling", "Model In Use", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + UISettings.UpscaleModelSets.Remove(modelSet); modelTemplate.IsInstalled = false; await SaveConfigurationFile(); } From 0b9a01eefd6eb389f10f9face129cedd06df0d95 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Wed, 20 Dec 2023 19:23:12 +1300 Subject: [PATCH 10/15] Fix merge --- OnnxStack.UI/OnnxStack.UI.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/OnnxStack.UI/OnnxStack.UI.csproj b/OnnxStack.UI/OnnxStack.UI.csproj index ec4f5f7d..e0648981 100644 --- a/OnnxStack.UI/OnnxStack.UI.csproj +++ b/OnnxStack.UI/OnnxStack.UI.csproj @@ -51,7 +51,6 @@ - From b1f15f1a863093d9d716dc64a5f4764cf5fe3950 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Thu, 21 Dec 2023 15:36:24 +1300 Subject: [PATCH 11/15] Add OpenVino EP support to core --- OnnxStack.Core/Config/ExecutionProvider.cs | 3 ++- OnnxStack.Core/Extensions/Extensions.cs | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/OnnxStack.Core/Config/ExecutionProvider.cs b/OnnxStack.Core/Config/ExecutionProvider.cs index f1413e3d..beccce8c 100644 --- a/OnnxStack.Core/Config/ExecutionProvider.cs +++ b/OnnxStack.Core/Config/ExecutionProvider.cs @@ -5,6 +5,7 @@ public enum ExecutionProvider DirectML = 0, Cuda = 1, Cpu = 2, - CoreML = 3 + CoreML = 3, + OpenVino = 4 } } diff --git a/OnnxStack.Core/Extensions/Extensions.cs b/OnnxStack.Core/Extensions/Extensions.cs index d4771dc2..e8b24585 100644 --- a/OnnxStack.Core/Extensions/Extensions.cs +++ b/OnnxStack.Core/Extensions/Extensions.cs @@ -36,9 +36,11 @@ public static SessionOptions GetSessionOptions(this OnnxModelConfig configuratio sessionOptions.AppendExecutionProvider_CPU(); return sessionOptions; case ExecutionProvider.CoreML: - sessionOptions.AppendExecutionProvider_CoreML( - CoreMLFlags.COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE - ); + sessionOptions.AppendExecutionProvider_CoreML(CoreMLFlags.COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE); + return sessionOptions; + case ExecutionProvider.OpenVino: + //TODO: DeviceId = "CPU_FP32"|"GPU_FP32"|"GPU_FP16"|"MYRIAD_FP16"|"VAD-M_FP16"|"VAD-F_FP32" + sessionOptions.AppendExecutionProvider_OpenVINO(); return sessionOptions; } } From 4c110543499a887af84d12adaeec912d12c68970 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Thu, 21 Dec 2023 15:50:49 +1300 Subject: [PATCH 12/15] Support all device types --- OnnxStack.Core/Extensions/Extensions.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/OnnxStack.Core/Extensions/Extensions.cs b/OnnxStack.Core/Extensions/Extensions.cs index e8b24585..3cd55b9d 100644 --- a/OnnxStack.Core/Extensions/Extensions.cs +++ b/OnnxStack.Core/Extensions/Extensions.cs @@ -39,8 +39,17 @@ public static SessionOptions GetSessionOptions(this OnnxModelConfig configuratio sessionOptions.AppendExecutionProvider_CoreML(CoreMLFlags.COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE); return sessionOptions; case ExecutionProvider.OpenVino: - //TODO: DeviceId = "CPU_FP32"|"GPU_FP32"|"GPU_FP16"|"MYRIAD_FP16"|"VAD-M_FP16"|"VAD-F_FP32" - sessionOptions.AppendExecutionProvider_OpenVINO(); + var deviceId = configuration.DeviceId switch + { + 0 => "CPU_FP32", + 1 => "GPU_FP32", + 2 => "GPU_FP16", + 3 => "MYRIAD_FP16", + 4 => "VAD-M_FP16", + 5 => "VAD-F_FP32", + _ => string.Empty + }; + sessionOptions.AppendExecutionProvider_OpenVINO(deviceId); return sessionOptions; } } From 0ba9a3f7f826437a8e21833fa8d29d90ccec5729 Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Thu, 21 Dec 2023 17:34:06 +1300 Subject: [PATCH 13/15] Update OnnxRuntime + other nugets --- OnnxStack.Console/OnnxStack.Console.csproj | 2 +- OnnxStack.Core/OnnxStack.Core.csproj | 6 +++--- OnnxStack.UI/OnnxStack.UI.csproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OnnxStack.Console/OnnxStack.Console.csproj b/OnnxStack.Console/OnnxStack.Console.csproj index bbea1312..444ee9ae 100644 --- a/OnnxStack.Console/OnnxStack.Console.csproj +++ b/OnnxStack.Console/OnnxStack.Console.csproj @@ -11,7 +11,7 @@ - + diff --git a/OnnxStack.Core/OnnxStack.Core.csproj b/OnnxStack.Core/OnnxStack.Core.csproj index 7c83ecf9..3657b449 100644 --- a/OnnxStack.Core/OnnxStack.Core.csproj +++ b/OnnxStack.Core/OnnxStack.Core.csproj @@ -38,10 +38,10 @@ - + - - + + diff --git a/OnnxStack.UI/OnnxStack.UI.csproj b/OnnxStack.UI/OnnxStack.UI.csproj index e0648981..9b3bbf1d 100644 --- a/OnnxStack.UI/OnnxStack.UI.csproj +++ b/OnnxStack.UI/OnnxStack.UI.csproj @@ -47,9 +47,9 @@ - + - + From 6087b46fc24c333c91e310c756045faf2f65a3db Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Thu, 21 Dec 2023 17:37:56 +1300 Subject: [PATCH 14/15] Use System.Numerics.TensorPrimitives for Cpu math --- .../Helpers/TensorHelper.cs | 294 ++++++------------ 1 file changed, 103 insertions(+), 191 deletions(-) diff --git a/OnnxStack.StableDiffusion/Helpers/TensorHelper.cs b/OnnxStack.StableDiffusion/Helpers/TensorHelper.cs index c7a368a8..60fbda3c 100644 --- a/OnnxStack.StableDiffusion/Helpers/TensorHelper.cs +++ b/OnnxStack.StableDiffusion/Helpers/TensorHelper.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Numerics; - +using System.Numerics.Tensors; namespace OnnxStack.StableDiffusion.Helpers { @@ -14,6 +14,7 @@ namespace OnnxStack.StableDiffusion.Helpers public static class TensorHelper { private static readonly int vectorSize = Vector.Count; + /// /// Creates a new tensor. /// @@ -44,17 +45,9 @@ public static DenseTensor CreateTensor(T[] data, ReadOnlySpan dimensi /// public static DenseTensor MultiplyTensorByFloat(this DenseTensor tensor, float value) { - var mullTensor = new DenseTensor(tensor.Dimensions); - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) * value) - .CopyTo(mullTensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - mullTensor.Buffer.Span[i] = tensor.Buffer.Span[i] * value; - } - return mullTensor; + var result = new DenseTensor(tensor.Dimensions); + TensorPrimitives.Multiply(tensor.Buffer.Span, value, result.Buffer.Span); + return result; } @@ -66,20 +59,12 @@ public static DenseTensor MultiplyTensorByFloat(this DenseTensor t /// public static DenseTensor SubtractFloat(this DenseTensor tensor, float value) { - var subTensor = new DenseTensor(tensor.Dimensions); - Vector vectorValue = new Vector(value); - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - Vector.Subtract(new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)), vectorValue) - .CopyTo(subTensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - subTensor.Buffer.Span[i] = tensor.Buffer.Span[i] - value; - } - return subTensor; + var result = new DenseTensor(tensor.Dimensions); + TensorPrimitives.Subtract(tensor.Buffer.Span, value, result.Buffer.Span); + return result; } + /// /// Adds the tensors. /// @@ -88,18 +73,9 @@ public static DenseTensor SubtractFloat(this DenseTensor tensor, f /// public static DenseTensor AddTensors(this DenseTensor tensor, DenseTensor sumTensor) { - var addTensor = new DenseTensor(tensor.Dimensions); - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) - + new Vector(sumTensor.Buffer.Span.Slice(i * vectorSize, vectorSize))) - .CopyTo(addTensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - addTensor.Buffer.Span[i] = tensor.Buffer.Span[i] + sumTensor.Buffer.Span[i]; - } - return addTensor; + var result = new DenseTensor(tensor.Dimensions); + TensorPrimitives.Add(tensor.Buffer.Span, sumTensor.Buffer.Span, result.Buffer.Span); + return result; } @@ -111,12 +87,12 @@ public static DenseTensor AddTensors(this DenseTensor tensor, Dens /// public static DenseTensor SumTensors(this DenseTensor[] tensors, ReadOnlySpan dimensions) { - var sumTensor = new DenseTensor(dimensions); + var result = new DenseTensor(dimensions); for (int m = 0; m < tensors.Length; m++) { - sumTensor.Add(tensors[m]); + TensorPrimitives.Add(result.Buffer.Span, tensors[m].Buffer.Span, result.Buffer.Span); } - return sumTensor; + return result; } @@ -129,68 +105,31 @@ public static DenseTensor SumTensors(this DenseTensor[] tensors, R public static DenseTensor SubtractTensors(this DenseTensor tensor, DenseTensor subTensor) { var result = new DenseTensor(tensor.Dimensions); - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) - - new Vector(subTensor.Buffer.Span.Slice(i * vectorSize, vectorSize))) - .CopyTo(result.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - result.Buffer.Span[i] = tensor.Buffer.Span[i] - subTensor.Buffer.Span[i]; - } + TensorPrimitives.Subtract(tensor.Buffer.Span, subTensor.Buffer.Span, result.Buffer.Span); return result; } - /// - /// Reorders the tensor. + /// Divides the tensor by float, mutates the original /// - /// The input tensor. + /// The tensor to mutate. + /// The value to divide by. /// - public static DenseTensor ReorderTensor(this DenseTensor tensor, ReadOnlySpan dimensions) + public static DenseTensor DivideBy(this DenseTensor tensor, float value) { - //reorder from batch channel height width to batch height width channel - var inputImagesTensor = new DenseTensor(dimensions); - for (int y = 0; y < tensor.Dimensions[2]; y++) - { - for (int x = 0; x < tensor.Dimensions[3]; x++) - { - inputImagesTensor[0, y, x, 0] = tensor[0, 0, y, x]; - inputImagesTensor[0, y, x, 1] = tensor[0, 1, y, x]; - inputImagesTensor[0, y, x, 2] = tensor[0, 2, y, x]; - } - } - return inputImagesTensor; + value = 1 / value; + TensorPrimitives.Multiply(tensor.Buffer.Span, value, tensor.Buffer.Span); + return tensor; } /// - /// Clips the specified Tensor valuse to the specified minimum/maximum. + /// Multiples the tensor by float, mutates the original /// - /// The tensor. - /// The minimum value. - /// The maximum value. + /// The tensor to mutate. + /// The value to multiply by. /// - public static DenseTensor Clip(this DenseTensor tensor, float minValue, float maxValue) - { - Vector min = new Vector(minValue); - Vector max = new Vector(maxValue); - var clipTensor = new DenseTensor(tensor.Dimensions); - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - Vector.Min(min, - Vector.Max(max, - new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)))) - .CopyTo(clipTensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - clipTensor.Buffer.Span[i] = Math.Clamp(tensor.Buffer.Span[i], minValue, maxValue); - } - return clipTensor; - - } + public static DenseTensor MultiplyBy(this DenseTensor tensor, float value) => DivideBy(tensor, 1 / value); /// @@ -200,16 +139,7 @@ public static DenseTensor Clip(this DenseTensor tensor, float minV /// public static DenseTensor Abs(this DenseTensor tensor) { - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - Span buffer = tensor.Buffer.Span.Slice(i * vectorSize, vectorSize); - Vector.Abs(new Vector(buffer)) - .CopyTo(buffer); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - tensor.Buffer.Span[i] = Math.Abs(tensor.Buffer.Span[i]); - } + TensorPrimitives.Abs(tensor.Buffer.Span, tensor.Buffer.Span); return tensor; } @@ -222,16 +152,7 @@ public static DenseTensor Abs(this DenseTensor tensor) /// public static DenseTensor Multiply(this DenseTensor tensor, DenseTensor mulTensor) { - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) - * new Vector(mulTensor.Buffer.Span.Slice(i * vectorSize, vectorSize))) - .CopyTo(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - tensor.Buffer.Span[i] = tensor.Buffer.Span[i] * mulTensor.Buffer.Span[i]; - } + TensorPrimitives.Multiply(tensor.Buffer.Span, mulTensor.Buffer.Span, tensor.Buffer.Span); return tensor; } @@ -244,17 +165,85 @@ public static DenseTensor Multiply(this DenseTensor tensor, DenseT /// public static DenseTensor Divide(this DenseTensor tensor, DenseTensor divTensor) { + TensorPrimitives.Divide(tensor.Buffer.Span, divTensor.Buffer.Span, tensor.Buffer.Span); + return tensor; + } + + + /// + /// Adds the tensors, mutates the original + /// + /// The tensor to mutate. + /// The tensor values to add to tensor. + /// + public static DenseTensor Add(this DenseTensor tensor, DenseTensor addTensor) + { + TensorPrimitives.Add(tensor.Buffer.Span, addTensor.Buffer.Span, tensor.Buffer.Span); + return tensor; + } + + + /// + /// Subtracts the tensors, mutates the original + /// + /// The tensor to mutate. + /// The tensor to subtract from tensor. + /// The dimensions. + /// + public static DenseTensor Subtract(this DenseTensor tensor, DenseTensor subTensor) + { + TensorPrimitives.Subtract(tensor.Buffer.Span, subTensor.Buffer.Span, tensor.Buffer.Span); + return tensor; + } + + + /// + /// Reorders the tensor. + /// + /// The input tensor. + /// + public static DenseTensor ReorderTensor(this DenseTensor tensor, ReadOnlySpan dimensions) + { + //reorder from batch channel height width to batch height width channel + var inputImagesTensor = new DenseTensor(dimensions); + for (int y = 0; y < tensor.Dimensions[2]; y++) + { + for (int x = 0; x < tensor.Dimensions[3]; x++) + { + inputImagesTensor[0, y, x, 0] = tensor[0, 0, y, x]; + inputImagesTensor[0, y, x, 1] = tensor[0, 1, y, x]; + inputImagesTensor[0, y, x, 2] = tensor[0, 2, y, x]; + } + } + return inputImagesTensor; + } + + + /// + /// Clips the specified Tensor valuse to the specified minimum/maximum. + /// + /// The tensor. + /// The minimum value. + /// The maximum value. + /// + public static DenseTensor Clip(this DenseTensor tensor, float minValue, float maxValue) + { + Vector min = new Vector(minValue); + Vector max = new Vector(maxValue); + var clipTensor = new DenseTensor(tensor.Dimensions); for (int i = 0; i < tensor.Length / vectorSize; i++) { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) - / new Vector(divTensor.Buffer.Span.Slice(i * vectorSize, vectorSize))) - .CopyTo(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); + Vector.Min(min, + Vector.Max(max, + new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)))) + .CopyTo(clipTensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); } for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) { - tensor.Buffer.Span[i] = tensor.Buffer.Span[i] / divTensor.Buffer.Span[i]; + clipTensor.Buffer.Span[i] = Math.Clamp(tensor.Buffer.Span[i], minValue, maxValue); } - return tensor; + return clipTensor; + } @@ -283,6 +272,7 @@ public static DenseTensor Concatenate(this DenseTensor tensor1, De return new DenseTensor(buffer, dimensions); } + private static DenseTensor Concatenate(DenseTensor tensor1, DenseTensor tensor2) { var dimensions = new int[] { tensor1.Dimensions[0], tensor1.Dimensions[1], tensor1.Dimensions[2] + tensor2.Dimensions[2] }; @@ -304,7 +294,6 @@ private static DenseTensor Concatenate(DenseTensor tensor1, DenseT } - /// /// Repeats the specified Tensor along the 0 axis. /// @@ -408,82 +397,5 @@ public static DenseTensor Join(this IList> tensors, in } return new DenseTensor(buffer, dimensions); } - - - /// - /// Adds the tensors, mutates the original - /// - /// The tensor to mutate. - /// The tensor values to add to tensor. - /// - public static DenseTensor Add(this DenseTensor tensor, DenseTensor addTensor) - { - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) - + new Vector(addTensor.Buffer.Span.Slice(i * vectorSize, vectorSize))) - .CopyTo(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - tensor.Buffer.Span[i] = tensor.Buffer.Span[i] + addTensor.Buffer.Span[i]; - } - return tensor; - } - - - /// - /// Subtracts the tensors, mutates the original - /// - /// The tensor to mutate. - /// The tensor to subtract from tensor. - /// The dimensions. - /// - public static DenseTensor Subtract(this DenseTensor tensor, DenseTensor subTensor) - { - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) - - new Vector(subTensor.Buffer.Span.Slice(i * vectorSize, vectorSize))) - .CopyTo(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - tensor.Buffer.Span[i] = tensor.Buffer.Span[i] - subTensor.Buffer.Span[i]; - } - return tensor; - } - - - /// - /// Divides the tensor by float, mutates the original - /// - /// The tensor to mutate. - /// The value to divide by. - /// - public static DenseTensor DivideBy(this DenseTensor tensor, float value) - { - value = 1 / value; - var mullTensor = new DenseTensor(tensor.Dimensions); - for (int i = 0; i < tensor.Length / vectorSize; i++) - { - (new Vector(tensor.Buffer.Span.Slice(i * vectorSize, vectorSize)) * value) - .CopyTo(mullTensor.Buffer.Span.Slice(i * vectorSize, vectorSize)); - } - for (int i = (int)(tensor.Length - tensor.Length % vectorSize); i < tensor.Length; i++) - { - mullTensor.Buffer.Span[i] = tensor.Buffer.Span[i] * value; - } - return mullTensor; - } - - - /// - /// Multiples the tensor by float, mutates the original - /// - /// The tensor to mutate. - /// The value to multiply by. - /// - public static DenseTensor MultiplyBy(this DenseTensor tensor, float value) => DivideBy(tensor, 1 / value); } } From 59a54e06736756608b54a63b0b5b5d536ab8372f Mon Sep 17 00:00:00 2001 From: sa_ddam213 Date: Fri, 22 Dec 2023 13:08:32 +1300 Subject: [PATCH 15/15] Add TensorRT ExecutionProvider --- OnnxStack.Core/Config/ExecutionProvider.cs | 3 ++- OnnxStack.Core/Extensions/Extensions.cs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/OnnxStack.Core/Config/ExecutionProvider.cs b/OnnxStack.Core/Config/ExecutionProvider.cs index beccce8c..e108feac 100644 --- a/OnnxStack.Core/Config/ExecutionProvider.cs +++ b/OnnxStack.Core/Config/ExecutionProvider.cs @@ -6,6 +6,7 @@ public enum ExecutionProvider Cuda = 1, Cpu = 2, CoreML = 3, - OpenVino = 4 + OpenVino = 4, + TensorRT = 5 } } diff --git a/OnnxStack.Core/Extensions/Extensions.cs b/OnnxStack.Core/Extensions/Extensions.cs index 3cd55b9d..6359bc3c 100644 --- a/OnnxStack.Core/Extensions/Extensions.cs +++ b/OnnxStack.Core/Extensions/Extensions.cs @@ -51,6 +51,9 @@ public static SessionOptions GetSessionOptions(this OnnxModelConfig configuratio }; sessionOptions.AppendExecutionProvider_OpenVINO(deviceId); return sessionOptions; + case ExecutionProvider.TensorRT: + sessionOptions.AppendExecutionProvider_Tensorrt(configuration.DeviceId.Value); + return sessionOptions; } }