Finished update to latest sd.cpp

This commit is contained in:
DarthAffe 2025-10-25 17:19:11 +02:00
parent 1ec8d67357
commit 07a65ead6d
51 changed files with 1780 additions and 1545 deletions

View File

@ -1,42 +0,0 @@
using System.Windows.Input;
namespace ImageCreationUI;
public class ActionCommand(Action command, Func<bool>? canExecute = null) : ICommand
{
#region Events
public event EventHandler? CanExecuteChanged;
#endregion
#region Methods
public bool CanExecute(object? parameter) => canExecute?.Invoke() ?? true;
public void Execute(object? parameter) => command.Invoke();
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
#endregion
}
public class ActionCommand<T>(Action<T> command, Func<T, bool>? canExecute = null) : ICommand
where T : class
{
#region Events
public event EventHandler? CanExecuteChanged;
#endregion
#region Methods
public bool CanExecute(object? parameter) => canExecute?.Invoke((T)parameter!) ?? true;
public void Execute(object? parameter) => command.Invoke((T)parameter!);
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
#endregion
}

View File

@ -1,4 +0,0 @@
<Application x:Class="ImageCreationUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml" />

View File

@ -1,5 +0,0 @@
using System.Windows;
namespace ImageCreationUI;
public partial class App : Application;

View File

@ -1,34 +0,0 @@
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using HPPH;
using HPPH.System.Drawing;
namespace ImageCreationUI.Converter;
[ValueConversion(typeof(IImage), typeof(ImageSource))]
public class ImageToImageSourceConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
using Bitmap? bitmap = (value as IImage)?.ToBitmap();
if (bitmap == null) return null;
using MemoryStream ms = new();
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
ms.Position = 0;
BitmapImage bitmapImage = new();
bitmapImage.BeginInit();
bitmapImage.StreamSource = ms;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage;
}
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException();
}

View File

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net9.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HPPH.System.Drawing" Version="1.0.0" />
<PackageReference Include="StableDiffusion.NET.Backend.Cpu" Version="3.4.1" />
<PackageReference Include="StableDiffusion.NET.Backend.Cuda" Version="3.4.1" />
<PackageReference Include="StableDiffusion.NET.Backend.Rocm" Version="3.4.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\StableDiffusion.NET\StableDiffusion.NET.csproj" />
</ItemGroup>
</Project>

View File

@ -1,2 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=extensions/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,165 +0,0 @@
<Window x:Class="ImageCreationUI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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:ImageCreationUI"
xmlns:converter="clr-namespace:ImageCreationUI.Converter"
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
xmlns:sd="clr-namespace:StableDiffusion.NET;assembly=StableDiffusion.NET"
mc:Ignorable="d"
Title="StableDiffusion.NET" Width="1706" Height="960">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
<converter:ImageToImageSourceConverter x:Key="ImageToImageSourceConverter" />
<ObjectDataProvider x:Key="ScheduleDataSource"
ObjectType="{x:Type sys:Enum}"
MethodName="GetValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="sd:Schedule" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="SamplerDataSource"
ObjectType="{x:Type sys:Enum}"
MethodName="GetValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="sd:Sampler" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="400" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="400" />
</Grid.ColumnDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<StackPanel Margin="4,0" Orientation="Vertical">
<TextBlock Margin="8" Text="This is just an example - inputs are not validated!&#10;Make sure everything is correct before pressing 'Create Image'." />
<Separator />
<Label Content="Model-Type" />
<StackPanel Orientation="Horizontal" Margin="4,0,0,0">
<RadioButton Content="Stable Diffusion" IsChecked="{Binding IsStableDiffusionSelected}" GroupName="ModelType" />
<RadioButton Margin="16,0,0,0" Content="Flux" IsChecked="{Binding IsFluxSelected}" GroupName="ModelType" />
</StackPanel>
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsStableDiffusionSelected}">
<Label Content="Model-Path" />
<DockPanel>
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectModelCommand}" IsEnabled="{Binding IsReady}" />
<TextBox Text="{Binding ModelPath}" />
</DockPanel>
</StackPanel>
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsFluxSelected}">
<Label Content="DiffusionModel-Path" />
<DockPanel>
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectDiffusionModelCommand}" IsEnabled="{Binding IsReady}" />
<TextBox Text="{Binding DiffusionModelPath}" />
</DockPanel>
<Label Content="ClipL-Path" />
<DockPanel>
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectClipLCommand}" IsEnabled="{Binding IsReady}" />
<TextBox Text="{Binding ClipLPath}" />
</DockPanel>
<Label Content="T5xxl-Path" />
<DockPanel>
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectT5xxlCommand}" IsEnabled="{Binding IsReady}" />
<TextBox Text="{Binding T5xxlPath}" />
</DockPanel>
</StackPanel>
<Label Content="Vae-Path (Optional)" />
<DockPanel>
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectVaeCommand}" IsEnabled="{Binding IsReady}" />
<TextBox Text="{Binding VaePath}" />
</DockPanel>
<Label Content="Schedule" />
<ComboBox ItemsSource="{Binding Source={StaticResource ScheduleDataSource}}" SelectedItem="{Binding Schedule}" />
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
<Label Content="Flash Attention" />
<CheckBox VerticalAlignment="Center" IsChecked="{Binding FlashAttention}" />
</StackPanel>
<Button Margin="0,8" Content="Load Model" Command="{Binding LoadModelCommand}" IsEnabled="{Binding IsReady}" />
<Separator />
<Label Margin="0,8,0,0" Content="Prompt" />
<TextBox Height="80" TextWrapping="Wrap" Text="{Binding Prompt}" />
<Label Content="AntiPrompt" />
<TextBox Height="60" TextWrapping="Wrap" Text="{Binding AntiPrompt}" />
<DockPanel LastChildFill="True">
<StackPanel DockPanel.Dock="Left">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
<Label Width="50" Content="Width" />
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Width}" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
<Label Width="50" Content="Height" />
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Height}" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
<Label Width="50" Content="Cfg" />
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Cfg}" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
<Label Width="50" Content="Steps" />
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Steps}" />
</StackPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
<Label Width="50" Content="Seed" />
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Seed}" />
</StackPanel>
</StackPanel>
<DockPanel Margin="16,0,0,0" LastChildFill="True">
<Label DockPanel.Dock="Top" Content="Image2Image Source" />
<DockPanel DockPanel.Dock="Top" >
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectImage2ImageSourceCommand}" IsEnabled="{Binding IsReady}" />
<TextBox Text="{Binding Image2ImageSourcePath}" />
</DockPanel>
<Image Source="{Binding Image2ImageSource, Converter={StaticResource ImageToImageSourceConverter}}" />
</DockPanel>
</DockPanel>
<Label Content="Sample-Method" />
<ComboBox ItemsSource="{Binding Source={StaticResource SamplerDataSource}}" SelectedItem="{Binding SampleMethod}" />
<Button Margin="0,16,0,0" Content="Create Image" Command="{Binding CreateImageCommand}" IsEnabled="{Binding IsReady}" />
<Button Margin="0,16,0,0" Content="Save Image" Command="{Binding SaveImageCommand}" IsEnabled="{Binding IsReady}" />
</StackPanel>
</ScrollViewer>
<GridSplitter Grid.Column="1" Margin="2,0" Width="2" Background="DimGray" VerticalAlignment="Stretch" HorizontalAlignment="Center" />
<Image Grid.Column="2" Source="{Binding Image, Converter={StaticResource ImageToImageSourceConverter}}" />
<GridSplitter Grid.Column="3" Margin="2,0" Width="2" Background="DimGray" VerticalAlignment="Stretch" HorizontalAlignment="Center" />
<TextBox Grid.Column="4" IsReadOnly="True" BorderThickness="0" AcceptsReturn="True" Text="{Binding Log}" TextChanged="TextBoxBase_OnTextChanged" />
</Grid>
</Window>

View File

@ -1,11 +0,0 @@
using System.Windows;
using System.Windows.Controls;
namespace ImageCreationUI;
public partial class MainWindow : Window
{
public MainWindow() => InitializeComponent();
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs args) => (sender as TextBox)?.ScrollToEnd();
}

View File

@ -1,422 +0,0 @@
using System.ComponentModel;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.CompilerServices;
using HPPH;
using HPPH.System.Drawing;
using Microsoft.Win32;
using StableDiffusion.NET;
namespace ImageCreationUI;
public class MainWindowViewModel : INotifyPropertyChanged
{
#region Properties & Fields
private DiffusionModel? _model;
private bool _isStableDiffusionSelected = true;
public bool IsStableDiffusionSelected
{
get => _isStableDiffusionSelected;
set => SetProperty(ref _isStableDiffusionSelected, value);
}
private bool _isFluxSelected;
public bool IsFluxSelected
{
get => _isFluxSelected;
set => SetProperty(ref _isFluxSelected, value);
}
private string _modelPath = string.Empty;
public string ModelPath
{
get => _modelPath;
set => SetProperty(ref _modelPath, value);
}
private string _clipLPath;
public string ClipLPath
{
get => _clipLPath;
set => SetProperty(ref _clipLPath, value);
}
private string _t5xxlPath;
public string T5xxlPath
{
get => _t5xxlPath;
set => SetProperty(ref _t5xxlPath, value);
}
private string _diffusionModelPath;
public string DiffusionModelPath
{
get => _diffusionModelPath;
set => SetProperty(ref _diffusionModelPath, value);
}
private string _vaePath = string.Empty;
public string VaePath
{
get => _vaePath;
set => SetProperty(ref _vaePath, value);
}
private Schedule _schedule = Schedule.Default;
public Schedule Schedule
{
get => _schedule;
set => SetProperty(ref _schedule, value);
}
private bool _flashAttention = true;
public bool FlashAttention
{
get => _flashAttention;
set => SetProperty(ref _flashAttention, value);
}
private string _prompt = string.Empty;
public string Prompt
{
get => _prompt;
set => SetProperty(ref _prompt, value);
}
private string _antiPrompt = string.Empty;
public string AntiPrompt
{
get => _antiPrompt;
set => SetProperty(ref _antiPrompt, value);
}
private int _width = 1024;
public int Width
{
get => _width;
set => SetProperty(ref _width, value);
}
private int _height = 1024;
public int Height
{
get => _height;
set => SetProperty(ref _height, value);
}
private float _cfg = 5f;
public float Cfg
{
get => _cfg;
set => SetProperty(ref _cfg, value);
}
private int _steps = 28;
public int Steps
{
get => _steps;
set => SetProperty(ref _steps, value);
}
private long _seed = -1;
public long Seed
{
get => _seed;
set => SetProperty(ref _seed, value);
}
private Sampler _sampleMethod = Sampler.Euler_A;
public Sampler SampleMethod
{
get => _sampleMethod;
set => SetProperty(ref _sampleMethod, value);
}
private string _image2ImageSourcePath = string.Empty;
public string Image2ImageSourcePath
{
get => _image2ImageSourcePath;
set
{
if (SetProperty(ref _image2ImageSourcePath, value))
{
try
{
Image2ImageSource = ImageHelper.LoadImage(value).ConvertTo<ColorRGB>();
}
catch
{
Image2ImageSource = null;
}
}
}
}
private IImage<ColorRGB>? _image2ImageSource;
public IImage<ColorRGB>? Image2ImageSource
{
get => _image2ImageSource;
set => SetProperty(ref _image2ImageSource, value);
}
private IImage? _image;
public IImage? Image
{
get => _image;
set => SetProperty(ref _image, value);
}
private string _log = string.Empty;
public string Log
{
get => _log;
set => SetProperty(ref _log, value);
}
private bool _isReady = true;
public bool IsReady
{
get => _isReady;
set => SetProperty(ref _isReady, value);
}
#endregion
#region Commands
private ActionCommand? _loadModelCommand;
public ActionCommand LoadModelCommand => _loadModelCommand ??= new ActionCommand(LoadModel);
private ActionCommand? _createImageCommand;
public ActionCommand CreateImageCommand => _createImageCommand ??= new ActionCommand(CreateImage);
private ActionCommand? _saveImageCommand;
public ActionCommand SaveImageCommand => _saveImageCommand ??= new ActionCommand(SaveImage);
private ActionCommand? _selectModelCommand;
public ActionCommand SelectModelCommand => _selectModelCommand ??= new ActionCommand(SelectModel);
private ActionCommand? _selectDiffusionModelCommand;
public ActionCommand SelectDiffusionModelCommand => _selectDiffusionModelCommand ??= new ActionCommand(SelectDiffusionModel);
private ActionCommand? _selectClipLCommand;
public ActionCommand SelectClipLCommand => _selectClipLCommand ??= new ActionCommand(SelectClipL);
private ActionCommand? _selectT5xxlCommand;
public ActionCommand SelectT5xxlCommand => _selectT5xxlCommand ??= new ActionCommand(SelectT5xxl);
private ActionCommand? _selectVaeCommand;
public ActionCommand SelectVaeCommand => _selectVaeCommand ??= new ActionCommand(SelectVae);
private ActionCommand? _selectImage2ImageSourceCommand;
public ActionCommand SelectImage2ImageSourceCommand => _selectImage2ImageSourceCommand ??= new ActionCommand(SelectImage2ImageSource);
#endregion
#region Constructors
public MainWindowViewModel()
{
try
{
StableDiffusionCpp.Log += (_, args) => LogLine($"LOG [{args.Level}]: {args.Text}", false);
StableDiffusionCpp.Progress += (_, args) => LogLine($"PROGRESS {args.Step} / {args.Steps} ({(args.Progress * 100):N2} %) {args.IterationsPerSecond:N2} it/s ({args.Time})");
}
catch (Exception ex)
{
LogLine($"Failed to load stable-diffusion.cpp libraries!{Environment.NewLine}{ex.Message}");
}
}
#endregion
#region Methods
private async void LoadModel()
{
try
{
IsReady = false;
_model?.Dispose();
bool restoreDefaultParameters = false;
if (IsStableDiffusionSelected)
{
restoreDefaultParameters = _model?.ModelParameter.DiffusionModelType != DiffusionModelType.StableDiffusion;
LogLine($"Loading stable diffusion-model '{ModelPath}'");
_model = await Task.Run(() => ModelBuilder.StableDiffusion(ModelPath).WithMultithreading().WithVae(VaePath).WithSchedule(Schedule).WithFlashAttention(FlashAttention).Build());
}
else if (IsFluxSelected)
{
restoreDefaultParameters = _model?.ModelParameter.DiffusionModelType != DiffusionModelType.Flux;
LogLine($"Loading flux-model '{DiffusionModelPath}'");
_model = await Task.Run(() => ModelBuilder.Flux(DiffusionModelPath, ClipLPath, T5xxlPath, VaePath).WithMultithreading().WithSchedule(Schedule).WithFlashAttention(FlashAttention).Build());
}
else
{
LogLine("No model-type selected :(");
}
if (restoreDefaultParameters && (_model != null))
{
DiffusionParameter parameter = _model.GetDefaultParameter();
AntiPrompt = parameter.NegativePrompt;
Width = parameter.Width;
Height = parameter.Height;
Steps = parameter.SampleSteps;
Seed = parameter.Seed;
SampleMethod = parameter.SampleMethod;
Cfg = _model.ModelParameter.DiffusionModelType == DiffusionModelType.Flux ? parameter.Guidance : parameter.CfgScale;
}
}
catch (Exception ex)
{
LogLine($"Failed to load model ...{Environment.NewLine}{ex.Message}");
}
finally
{
IsReady = true;
}
}
private async void CreateImage()
{
if (_model == null) return;
try
{
IsReady = false;
DiffusionParameter parameter = _model.GetDefaultParameter()
.WithNegativePrompt(AntiPrompt)
.WithSize(Width, Height)
.WithSteps(Steps)
.WithSeed(Seed)
.WithSampler(SampleMethod);
if (_model.ModelParameter.DiffusionModelType == DiffusionModelType.StableDiffusion)
parameter = parameter.WithCfg(Cfg);
else if (_model.ModelParameter.DiffusionModelType == DiffusionModelType.Flux)
parameter = parameter.WithGuidance(Cfg);
if (Image2ImageSource == null)
{
LogLine("Creating image ...");
Image = await Task.Run(() => _model?.TextToImage(Prompt, parameter));
}
else
{
LogLine("Manipulating image ...");
Image = await Task.Run(() => _model?.ImageToImage(Prompt, Image2ImageSource, parameter));
}
LogLine("done!");
}
catch (Exception ex)
{
LogLine($"Failed to create image ...{Environment.NewLine}{ex.Message}");
}
finally
{
IsReady = true;
}
}
private void SaveImage()
{
try
{
if (Image == null) return;
SaveFileDialog saveFileDialog = new() { Filter = "PNG File (*.png)|*.png" };
if (saveFileDialog.ShowDialog() == true)
{
File.WriteAllBytes(saveFileDialog.FileName, Image.ToPng());
LogLine($"Image saved to '{saveFileDialog.FileName}'!");
}
}
catch (Exception ex)
{
LogLine($"Failed to save image ...{Environment.NewLine}{ex.Message}");
}
}
private void SelectModel()
{
OpenFileDialog openFileDialog = new() { Filter = "Stable Diffusion Model|*.*" };
if (openFileDialog.ShowDialog() == true)
ModelPath = openFileDialog.FileName;
}
private void SelectDiffusionModel()
{
OpenFileDialog openFileDialog = new() { Filter = "Diffusion Model|*.*" };
if (openFileDialog.ShowDialog() == true)
DiffusionModelPath = openFileDialog.FileName;
}
private void SelectClipL()
{
OpenFileDialog openFileDialog = new() { Filter = "ClipL|*.*" };
if (openFileDialog.ShowDialog() == true)
ClipLPath = openFileDialog.FileName;
}
private void SelectT5xxl()
{
OpenFileDialog openFileDialog = new() { Filter = "T5xxl|*.*" };
if (openFileDialog.ShowDialog() == true)
T5xxlPath = openFileDialog.FileName;
}
private void SelectVae()
{
OpenFileDialog openFileDialog = new() { Filter = "VAE|*.*" };
if (openFileDialog.ShowDialog() == true)
VaePath = openFileDialog.FileName;
}
private void SelectImage2ImageSource()
{
IEnumerable<string> codecs = ["All Files (*.*)|*.*", .. ImageCodecInfo.GetImageDecoders().Select(c =>
{
string codecName = c.CodecName![8..].Replace("Codec", "Files").Trim();
return $"{codecName} ({c.FilenameExtension})|{c.FilenameExtension}";
})];
OpenFileDialog openFileDialog = new() { Filter = string.Join('|', codecs) };
if (openFileDialog.ShowDialog() == true)
Image2ImageSourcePath = openFileDialog.FileName;
}
private void LogLine(string line, bool appendNewLine = true)
{
if (appendNewLine)
Log += line + Environment.NewLine;
else
Log += line;
}
#endregion
#region NotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private bool SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
#endregion
}

322
Header/stable-diffusion.h Normal file
View File

@ -0,0 +1,322 @@
#ifndef __STABLE_DIFFUSION_H__
#define __STABLE_DIFFUSION_H__
#if defined(_WIN32) || defined(__CYGWIN__)
#ifndef SD_BUILD_SHARED_LIB
#define SD_API
#else
#ifdef SD_BUILD_DLL
#define SD_API __declspec(dllexport)
#else
#define SD_API __declspec(dllimport)
#endif
#endif
#else
#if __GNUC__ >= 4
#define SD_API __attribute__((visibility("default")))
#else
#define SD_API
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
enum rng_type_t {
STD_DEFAULT_RNG,
CUDA_RNG,
RNG_TYPE_COUNT
};
enum sample_method_t {
SAMPLE_METHOD_DEFAULT,
EULER,
HEUN,
DPM2,
DPMPP2S_A,
DPMPP2M,
DPMPP2Mv2,
IPNDM,
IPNDM_V,
LCM,
DDIM_TRAILING,
TCD,
EULER_A,
SAMPLE_METHOD_COUNT
};
enum scheduler_t {
DEFAULT,
DISCRETE,
KARRAS,
EXPONENTIAL,
AYS,
GITS,
SGM_UNIFORM,
SIMPLE,
SMOOTHSTEP,
SCHEDULE_COUNT
};
enum prediction_t {
DEFAULT_PRED,
EPS_PRED,
V_PRED,
EDM_V_PRED,
SD3_FLOW_PRED,
FLUX_FLOW_PRED,
PREDICTION_COUNT
};
// same as enum ggml_type
enum sd_type_t {
SD_TYPE_F32 = 0,
SD_TYPE_F16 = 1,
SD_TYPE_Q4_0 = 2,
SD_TYPE_Q4_1 = 3,
// SD_TYPE_Q4_2 = 4, support has been removed
// SD_TYPE_Q4_3 = 5, support has been removed
SD_TYPE_Q5_0 = 6,
SD_TYPE_Q5_1 = 7,
SD_TYPE_Q8_0 = 8,
SD_TYPE_Q8_1 = 9,
SD_TYPE_Q2_K = 10,
SD_TYPE_Q3_K = 11,
SD_TYPE_Q4_K = 12,
SD_TYPE_Q5_K = 13,
SD_TYPE_Q6_K = 14,
SD_TYPE_Q8_K = 15,
SD_TYPE_IQ2_XXS = 16,
SD_TYPE_IQ2_XS = 17,
SD_TYPE_IQ3_XXS = 18,
SD_TYPE_IQ1_S = 19,
SD_TYPE_IQ4_NL = 20,
SD_TYPE_IQ3_S = 21,
SD_TYPE_IQ2_S = 22,
SD_TYPE_IQ4_XS = 23,
SD_TYPE_I8 = 24,
SD_TYPE_I16 = 25,
SD_TYPE_I32 = 26,
SD_TYPE_I64 = 27,
SD_TYPE_F64 = 28,
SD_TYPE_IQ1_M = 29,
SD_TYPE_BF16 = 30,
// SD_TYPE_Q4_0_4_4 = 31, support has been removed from gguf files
// SD_TYPE_Q4_0_4_8 = 32,
// SD_TYPE_Q4_0_8_8 = 33,
SD_TYPE_TQ1_0 = 34,
SD_TYPE_TQ2_0 = 35,
// SD_TYPE_IQ4_NL_4_4 = 36,
// SD_TYPE_IQ4_NL_4_8 = 37,
// SD_TYPE_IQ4_NL_8_8 = 38,
SD_TYPE_MXFP4 = 39, // MXFP4 (1 block)
SD_TYPE_COUNT = 40,
};
enum sd_log_level_t {
SD_LOG_DEBUG,
SD_LOG_INFO,
SD_LOG_WARN,
SD_LOG_ERROR
};
typedef struct {
bool enabled;
int tile_size_x;
int tile_size_y;
float target_overlap;
float rel_size_x;
float rel_size_y;
} sd_tiling_params_t;
typedef struct {
const char* model_path;
const char* clip_l_path;
const char* clip_g_path;
const char* clip_vision_path;
const char* t5xxl_path;
const char* qwen2vl_path;
const char* qwen2vl_vision_path;
const char* diffusion_model_path;
const char* high_noise_diffusion_model_path;
const char* vae_path;
const char* taesd_path;
const char* control_net_path;
const char* lora_model_dir;
const char* embedding_dir;
const char* photo_maker_path;
bool vae_decode_only;
bool free_params_immediately;
int n_threads;
enum sd_type_t wtype;
enum rng_type_t rng_type;
enum prediction_t prediction;
bool offload_params_to_cpu;
bool keep_clip_on_cpu;
bool keep_control_net_on_cpu;
bool keep_vae_on_cpu;
bool diffusion_flash_attn;
bool diffusion_conv_direct;
bool vae_conv_direct;
bool force_sdxl_vae_conv_scale;
bool chroma_use_dit_mask;
bool chroma_use_t5_mask;
int chroma_t5_mask_pad;
float flow_shift;
} sd_ctx_params_t;
typedef struct {
uint32_t width;
uint32_t height;
uint32_t channel;
uint8_t* data;
} sd_image_t;
typedef struct {
int* layers;
size_t layer_count;
float layer_start;
float layer_end;
float scale;
} sd_slg_params_t;
typedef struct {
float txt_cfg;
float img_cfg;
float distilled_guidance;
sd_slg_params_t slg;
} sd_guidance_params_t;
typedef struct {
sd_guidance_params_t guidance;
enum scheduler_t scheduler;
enum sample_method_t sample_method;
int sample_steps;
float eta;
int shifted_timestep;
} sd_sample_params_t;
typedef struct {
sd_image_t* id_images;
int id_images_count;
const char* id_embed_path;
float style_strength;
} sd_pm_params_t; // photo maker
typedef struct {
const char* prompt;
const char* negative_prompt;
int clip_skip;
sd_image_t init_image;
sd_image_t* ref_images;
int ref_images_count;
bool auto_resize_ref_image;
bool increase_ref_index;
sd_image_t mask_image;
int width;
int height;
sd_sample_params_t sample_params;
float strength;
int64_t seed;
int batch_count;
sd_image_t control_image;
float control_strength;
sd_pm_params_t pm_params;
sd_tiling_params_t vae_tiling_params;
} sd_img_gen_params_t;
typedef struct {
const char* prompt;
const char* negative_prompt;
int clip_skip;
sd_image_t init_image;
sd_image_t end_image;
sd_image_t* control_frames;
int control_frames_size;
int width;
int height;
sd_sample_params_t sample_params;
sd_sample_params_t high_noise_sample_params;
float moe_boundary;
float strength;
int64_t seed;
int video_frames;
float vace_strength;
} sd_vid_gen_params_t;
typedef struct sd_ctx_t sd_ctx_t;
typedef void (*sd_log_cb_t)(enum sd_log_level_t level, const char* text, void* data);
typedef void (*sd_progress_cb_t)(int step, int steps, float time, void* data);
SD_API void sd_set_log_callback(sd_log_cb_t sd_log_cb, void* data);
SD_API void sd_set_progress_callback(sd_progress_cb_t cb, void* data);
SD_API int32_t get_num_physical_cores();
SD_API const char* sd_get_system_info();
SD_API const char* sd_type_name(enum sd_type_t type);
SD_API enum sd_type_t str_to_sd_type(const char* str);
SD_API const char* sd_rng_type_name(enum rng_type_t rng_type);
SD_API enum rng_type_t str_to_rng_type(const char* str);
SD_API const char* sd_sample_method_name(enum sample_method_t sample_method);
SD_API enum sample_method_t str_to_sample_method(const char* str);
SD_API const char* sd_schedule_name(enum scheduler_t scheduler);
SD_API enum scheduler_t str_to_schedule(const char* str);
SD_API const char* sd_prediction_name(enum prediction_t prediction);
SD_API enum prediction_t str_to_prediction(const char* str);
SD_API void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params);
SD_API char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params);
SD_API sd_ctx_t* new_sd_ctx(const sd_ctx_params_t* sd_ctx_params);
SD_API void free_sd_ctx(sd_ctx_t* sd_ctx);
SD_API enum sample_method_t sd_get_default_sample_method(const sd_ctx_t* sd_ctx);
SD_API void sd_sample_params_init(sd_sample_params_t* sample_params);
SD_API char* sd_sample_params_to_str(const sd_sample_params_t* sample_params);
SD_API void sd_img_gen_params_init(sd_img_gen_params_t* sd_img_gen_params);
SD_API char* sd_img_gen_params_to_str(const sd_img_gen_params_t* sd_img_gen_params);
SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* sd_img_gen_params);
SD_API void sd_vid_gen_params_init(sd_vid_gen_params_t* sd_vid_gen_params);
SD_API sd_image_t* generate_video(sd_ctx_t* sd_ctx, const sd_vid_gen_params_t* sd_vid_gen_params, int* num_frames_out);
typedef struct upscaler_ctx_t upscaler_ctx_t;
SD_API upscaler_ctx_t* new_upscaler_ctx(const char* esrgan_path,
bool offload_params_to_cpu,
bool direct,
int n_threads);
SD_API void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx);
SD_API sd_image_t upscale(upscaler_ctx_t* upscaler_ctx,
sd_image_t input_image,
uint32_t upscale_factor);
SD_API int get_upscale_factor(upscaler_ctx_t* upscaler_ctx);
SD_API bool convert(const char* input_path,
const char* vae_path,
const char* output_path,
enum sd_type_t output_type,
const char* tensor_type_rules);
SD_API bool preprocess_canny(sd_image_t image,
float high_threshold,
float low_threshold,
float weak,
float strong,
bool inverse);
#ifdef __cplusplus
}
#endif
#endif // __STABLE_DIFFUSION_H__

View File

@ -5,10 +5,7 @@ VisualStudioVersion = 17.8.34322.80
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StableDiffusion.NET", "StableDiffusion.NET\StableDiffusion.NET.csproj", "{ED9336F9-7C5F-47DD-A120-272F4835E95F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StableDiffusion.NET", "StableDiffusion.NET\StableDiffusion.NET.csproj", "{ED9336F9-7C5F-47DD-A120-272F4835E95F}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{8961F5D8-3F50-4027-8862-635FCA1E1568}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageCreationUI", "Examples\ImageCreationUI\ImageCreationUI.csproj", "{EB73E250-D2F7-469A-80BF-02C5078546A7}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -19,17 +16,10 @@ Global
{ED9336F9-7C5F-47DD-A120-272F4835E95F}.Debug|Any CPU.Build.0 = Debug|Any CPU {ED9336F9-7C5F-47DD-A120-272F4835E95F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED9336F9-7C5F-47DD-A120-272F4835E95F}.Release|Any CPU.ActiveCfg = Release|Any CPU {ED9336F9-7C5F-47DD-A120-272F4835E95F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED9336F9-7C5F-47DD-A120-272F4835E95F}.Release|Any CPU.Build.0 = Release|Any CPU {ED9336F9-7C5F-47DD-A120-272F4835E95F}.Release|Any CPU.Build.0 = Release|Any CPU
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{EB73E250-D2F7-469A-80BF-02C5078546A7} = {8961F5D8-3F50-4027-8862-635FCA1E1568}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8DD53974-8766-4659-97B6-4AEDF4323F65} SolutionGuid = {8DD53974-8766-4659-97B6-4AEDF4323F65}
EndGlobalSection EndGlobalSection

View File

@ -0,0 +1,11 @@
namespace StableDiffusion.NET;
public enum Prediction
{
Default,
EPS,
V,
EDM_V,
SD3Flow,
FluxFlow
}

View File

@ -42,6 +42,7 @@ public enum Quantization
// SD_TYPE_IQ4_NL_4_4 = 36, // SD_TYPE_IQ4_NL_4_4 = 36,
// SD_TYPE_IQ4_NL_4_8 = 37, // SD_TYPE_IQ4_NL_4_8 = 37,
// SD_TYPE_IQ4_NL_8_8 = 38, // SD_TYPE_IQ4_NL_8_8 = 38,
SD_TYPE_MXFP4 = 39,
Unspecified = 39 Unspecified = 40
} }

View File

@ -2,7 +2,7 @@
public enum Sampler public enum Sampler
{ {
Euler_A, Default,
Euler, Euler,
Heun, Heun,
DPM2, DPM2,
@ -13,5 +13,6 @@ public enum Sampler
IPNDM_V, IPNDM_V,
LCM, LCM,
DDIM_Trailing, DDIM_Trailing,
TCD TCD,
Euler_A,
} }

View File

@ -1,11 +1,14 @@
namespace StableDiffusion.NET; namespace StableDiffusion.NET;
public enum Schedule public enum Scheduler
{ {
Default, Default,
Discrete, Discrete,
Karras, Karras,
Exponential, Exponential,
AYS, AYS,
GITS GITS,
SGM_Uniform,
Simple,
Smoothstep
} }

View File

@ -28,7 +28,6 @@ public static class ParameterExtension
if (!string.IsNullOrWhiteSpace(parameter.VaePath) && !string.IsNullOrWhiteSpace(parameter.TaesdPath)) throw new ArgumentException("VAE and TAESD are mutually exclusive."); if (!string.IsNullOrWhiteSpace(parameter.VaePath) && !string.IsNullOrWhiteSpace(parameter.TaesdPath)) throw new ArgumentException("VAE and TAESD are mutually exclusive.");
if (!Enum.IsDefined(parameter.RngType)) throw new ArgumentOutOfRangeException(nameof(DiffusionModelParameter.RngType)); if (!Enum.IsDefined(parameter.RngType)) throw new ArgumentOutOfRangeException(nameof(DiffusionModelParameter.RngType));
if (!Enum.IsDefined(parameter.Schedule)) throw new ArgumentOutOfRangeException(nameof(DiffusionModelParameter.Schedule));
} }
public static void Validate(this ImageGenerationParameter parameter) public static void Validate(this ImageGenerationParameter parameter)
@ -36,19 +35,31 @@ public static class ParameterExtension
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter)); ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
ArgumentNullException.ThrowIfNull(parameter.ControlNet, nameof(ImageGenerationParameter.ControlNet)); ArgumentNullException.ThrowIfNull(parameter.ControlNet, nameof(ImageGenerationParameter.ControlNet));
ArgumentNullException.ThrowIfNull(parameter.PhotoMaker, nameof(ImageGenerationParameter.PhotoMaker)); ArgumentNullException.ThrowIfNull(parameter.PhotoMaker, nameof(ImageGenerationParameter.PhotoMaker));
ArgumentNullException.ThrowIfNull(parameter.Prompt, nameof(ImageGenerationParameter.Prompt));
ArgumentNullException.ThrowIfNull(parameter.NegativePrompt, nameof(ImageGenerationParameter.NegativePrompt)); ArgumentNullException.ThrowIfNull(parameter.NegativePrompt, nameof(ImageGenerationParameter.NegativePrompt));
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Width, nameof(ImageGenerationParameter.Width)); ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Width, nameof(ImageGenerationParameter.Width));
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Height, nameof(ImageGenerationParameter.Height)); ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Height, nameof(ImageGenerationParameter.Height));
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.SampleSteps, nameof(ImageGenerationParameter.SampleSteps));
if (!Enum.IsDefined(parameter.SampleMethod)) throw new ArgumentOutOfRangeException(nameof(ImageGenerationParameter.SampleMethod)); parameter.SampleParameter.Validate();
parameter.Guidance.Validate();
parameter.ControlNet.Validate(); parameter.ControlNet.Validate();
parameter.PhotoMaker.Validate(); parameter.PhotoMaker.Validate();
} }
public static void Validate(this VideoGenerationParameter parameter)
{
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
ArgumentNullException.ThrowIfNull(parameter.Prompt, nameof(VideoGenerationParameter.Prompt));
ArgumentNullException.ThrowIfNull(parameter.NegativePrompt, nameof(VideoGenerationParameter.NegativePrompt));
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Width, nameof(VideoGenerationParameter.Width));
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Height, nameof(VideoGenerationParameter.Height));
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.FrameCount, nameof(VideoGenerationParameter.FrameCount));
parameter.SampleParameter.Validate();
parameter.HighNoiseSampleParameter.Validate();
}
public static void Validate(this ControlNetParameter parameter) public static void Validate(this ControlNetParameter parameter)
{ {
ArgumentNullException.ThrowIfNull(parameter, nameof(ImageGenerationParameter.ControlNet)); ArgumentNullException.ThrowIfNull(parameter, nameof(ImageGenerationParameter.ControlNet));
@ -59,11 +70,23 @@ public static class ParameterExtension
public static void Validate(this PhotoMakerParameter parameter) public static void Validate(this PhotoMakerParameter parameter)
{ {
ArgumentNullException.ThrowIfNull(parameter, nameof(ImageGenerationParameter.PhotoMaker)); ArgumentNullException.ThrowIfNull(parameter, nameof(ImageGenerationParameter.PhotoMaker));
ArgumentNullException.ThrowIfNull(parameter.InputIdImageDirectory, nameof(PhotoMakerParameter.InputIdImageDirectory)); ArgumentNullException.ThrowIfNull(parameter.IdEmbedPath, nameof(PhotoMakerParameter.IdEmbedPath));
ArgumentOutOfRangeException.ThrowIfNegative(parameter.StyleStrength, nameof(PhotoMakerParameter.StyleStrength)); ArgumentOutOfRangeException.ThrowIfNegative(parameter.StyleStrength, nameof(PhotoMakerParameter.StyleStrength));
} }
public static void Validate(this SampleParameter parameter)
{
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.SampleSteps, nameof(ImageGenerationParameter.SampleParameter.SampleSteps));
if (!Enum.IsDefined(parameter.Scheduler)) throw new ArgumentOutOfRangeException(nameof(ImageGenerationParameter.SampleParameter.Scheduler));
if (!Enum.IsDefined(parameter.SampleMethod)) throw new ArgumentOutOfRangeException(nameof(ImageGenerationParameter.SampleParameter.SampleMethod));
parameter.Guidance.Validate();
}
public static void Validate(this GuidanceParameter parameter) public static void Validate(this GuidanceParameter parameter)
{ {
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter)); ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));

View File

@ -111,6 +111,8 @@ internal static class ImageHelper
internal static unsafe IImage[] ToImageArrayIFace(Native.Types.sd_image_t* sdImage, int count) internal static unsafe IImage[] ToImageArrayIFace(Native.Types.sd_image_t* sdImage, int count)
{ {
if (sdImage == null) return [];
IImage[] images = new IImage[count]; IImage[] images = new IImage[count];
for (int i = 0; i < images.Length; i++) for (int i = 0; i < images.Length; i++)

View File

@ -1,30 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public sealed class ESRGANModelBuilder : IUpscaleModelBuilder
{
#region Properties & Fields
public UpscaleModelParameter Parameter { get; }
IUpscaleModelParameter IUpscaleModelBuilder.Parameter => Parameter;
IModelParameter IModelBuilder.Parameter => Parameter;
#endregion
#region Constructors
public ESRGANModelBuilder(string modelPath)
{
Parameter = new UpscaleModelParameter { ModelPath = modelPath };
}
#endregion
#region Methods
public UpscaleModel Build() => new(Parameter);
#endregion
}

View File

@ -1,240 +0,0 @@
using System;
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public static class DiffusionModelBuilderExtension
{
public static T WithVae<T>(this T builder, string vaePath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(vaePath);
if (!string.IsNullOrWhiteSpace(builder.Parameter.TaesdPath)) throw new ArgumentException("TAESD is already enabled. VAE and TAESD are mutually exclusive.", nameof(vaePath));
builder.Parameter.VaePath = vaePath;
return builder;
}
public static T WithTaesd<T>(this T builder, string taesdPath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(taesdPath);
if (!string.IsNullOrWhiteSpace(builder.Parameter.VaePath)) throw new ArgumentException("VAE is already enabled. TAESD and VAE are mutually exclusive.", nameof(taesdPath));
builder.Parameter.TaesdPath = taesdPath;
return builder;
}
public static T WithLoraSupport<T>(this T builder, string loraModelDirectory)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(loraModelDirectory);
builder.Parameter.LoraModelDirectory = loraModelDirectory;
return builder;
}
public static T WithEmbeddingSupport<T>(this T builder, string embeddingsDirectory)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(embeddingsDirectory);
builder.Parameter.EmbeddingsDirectory = embeddingsDirectory;
return builder;
}
public static T WithControlNet<T>(this T builder, string controlNetPath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(controlNetPath);
builder.Parameter.ControlNetPath = controlNetPath;
return builder;
}
public static T WithVaeDecodeOnly<T>(this T builder, bool vaeDecodeOnly = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.VaeDecodeOnly = vaeDecodeOnly;
return builder;
}
public static T WithVaeTiling<T>(this T builder, bool vaeTiling = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.VaeTiling = vaeTiling;
return builder;
}
public static T KeepControlNetOnCpu<T>(this T builder, bool keepControlNetOnCpu = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.KeepControlNetOnCPU = keepControlNetOnCpu;
return builder;
}
public static T KeepClipNetOnCpu<T>(this T builder, bool keepClipNetOnCpu = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.KeepClipOnCPU = keepClipNetOnCpu;
return builder;
}
public static T KeepVaeOnCpu<T>(this T builder, bool keepVaeOnCpu = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.KeepVaeOnCPU = keepVaeOnCpu;
return builder;
}
public static T WithFlashAttention<T>(this T builder, bool flashAttention = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.FlashAttention = flashAttention;
return builder;
}
public static T WithDiffusionConvDirect<T>(this T builder, bool diffusionConfDirect = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.DiffusionConvDirect = diffusionConfDirect;
return builder;
}
public static T WithVaeConvDirect<T>(this T builder, bool vaeConfDirect = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.VaeConfDirect = vaeConfDirect;
return builder;
}
public static T WithRngType<T>(this T builder, RngType rngType)
where T : IDiffusionModelBuilder
{
if (!Enum.IsDefined(rngType)) throw new ArgumentOutOfRangeException(nameof(rngType));
builder.Parameter.RngType = rngType;
return builder;
}
public static T WithSchedule<T>(this T builder, Schedule schedule)
where T : IDiffusionModelBuilder
{
if (!Enum.IsDefined(schedule)) throw new ArgumentOutOfRangeException(nameof(schedule));
builder.Parameter.Schedule = schedule;
return builder;
}
public static T WithQuantization<T>(this T builder, Quantization quantization)
where T : IDiffusionModelBuilder
{
if (!Enum.IsDefined(quantization)) throw new ArgumentOutOfRangeException(nameof(quantization));
builder.Parameter.Quantization = quantization;
return builder;
}
public static T WithPhotomaker<T>(this T builder, string stackedIdEmbeddingsDirectory)
where T : IDiffusionModelBuilder
{
ArgumentException.ThrowIfNullOrWhiteSpace(stackedIdEmbeddingsDirectory, nameof(stackedIdEmbeddingsDirectory));
builder.Parameter.StackedIdEmbeddingsDirectory = stackedIdEmbeddingsDirectory;
return builder;
}
public static T WithModelPath<T>(this T builder, string modelPath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(modelPath);
builder.Parameter.ModelPath = modelPath;
return builder;
}
public static T WithDiffusionModelPath<T>(this T builder, string diffusionModelPath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(diffusionModelPath);
builder.Parameter.DiffusionModelPath = diffusionModelPath;
return builder;
}
public static T WithClipLPath<T>(this T builder, string clipLPath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(clipLPath);
builder.Parameter.ClipLPath = clipLPath;
return builder;
}
public static T WithT5xxlPath<T>(this T builder, string t5xxlPath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(t5xxlPath);
builder.Parameter.T5xxlPath = t5xxlPath;
return builder;
}
public static T UseChromaDitMap<T>(this T builder, bool useChromaDitMap = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.ChromaUseDitMap = useChromaDitMap;
return builder;
}
public static T EnableChromaT5Map<T>(this T builder, bool enableChromaT5Map = true)
where T : IDiffusionModelBuilder
{
builder.Parameter.ChromaEnableT5Map = enableChromaT5Map;
return builder;
}
public static T WithChromaT5MaskPad<T>(this T builder, int chromaT5MaskPad)
where T : IDiffusionModelBuilder
{
builder.Parameter.ChromaT5MaskPad = chromaT5MaskPad;
return builder;
}
public static T WithClipGPath<T>(this T builder, string clipGPath)
where T : IDiffusionModelBuilder
{
ArgumentNullException.ThrowIfNull(clipGPath);
builder.Parameter.ClipGPath = clipGPath;
return builder;
}
}

View File

@ -1,28 +0,0 @@
using System;
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public static class ModelBuilderExtension
{
public static T WithoutMultithreading<T>(this T builder)
where T : IModelBuilder
{
builder.Parameter.ThreadCount = 1;
return builder;
}
public static T WithMultithreading<T>(this T builder, int threadCount = 0)
where T : IModelBuilder
{
ArgumentOutOfRangeException.ThrowIfLessThan(threadCount, 0, nameof(threadCount));
if (threadCount == 0) threadCount = Environment.ProcessorCount;
builder.Parameter.ThreadCount = threadCount;
return builder;
}
}

View File

@ -1,27 +0,0 @@
using System;
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public static class UpscaleModelBuilderExtension
{
public static T WithModelPath<T>(this T builder, string modelPath)
where T : IUpscaleModelBuilder
{
ArgumentNullException.ThrowIfNull(modelPath);
builder.Parameter.ModelPath = modelPath;
return builder;
}
public static T WithConvDirect<T>(this T builder, bool confDirect = true)
where T : IUpscaleModelBuilder
{
builder.Parameter.ConvDirect = confDirect;
return builder;
}
}

View File

@ -1,30 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public sealed class FluxModelBuilder : IDiffusionModelBuilder
{
#region Properties & Fields
public DiffusionModelParameter Parameter { get; }
IDiffusionModelParameter IDiffusionModelBuilder.Parameter => Parameter;
IModelParameter IModelBuilder.Parameter => Parameter;
#endregion
#region Constructors
public FluxModelBuilder(string diffusionModelPath, string clipLPath, string t5xxlPath, string vaePath)
{
Parameter = new DiffusionModelParameter { DiffusionModelPath = diffusionModelPath, ClipLPath = clipLPath, T5xxlPath = t5xxlPath, VaePath = vaePath };
}
#endregion
#region Methods
public DiffusionModel Build() => new(Parameter);
#endregion
}

View File

@ -1,11 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public interface IDiffusionModelBuilder : IModelBuilder
{
IDiffusionModelParameter Parameter { get; }
DiffusionModel Build();
}

View File

@ -1,9 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public interface IModelBuilder
{
IModelParameter Parameter { get; }
}

View File

@ -1,11 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public interface IUpscaleModelBuilder : IModelBuilder
{
IUpscaleModelParameter Parameter { get; }
UpscaleModel Build();
}

View File

@ -1,12 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public static class ModelBuilder
{
public static StableDiffusionModelBuilder StableDiffusion(string modelPath) => new(modelPath);
public static StableDiffusion3_5ModelBuilder StableDiffusion3_5(string modelPath, string clipLPath, string clipGPath, string t5xxlPath) => new(modelPath, clipLPath, clipGPath, t5xxlPath);
public static FluxModelBuilder Flux(string diffusionModelPath, string clipLPath, string t5xxlPath, string vaePath) => new(diffusionModelPath, clipLPath, t5xxlPath, vaePath);
public static ESRGANModelBuilder ESRGAN(string modelPath) => new(modelPath);
}

View File

@ -1,37 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public sealed class StableDiffusion3_5ModelBuilder : IDiffusionModelBuilder
{
#region Properties & Fields
public DiffusionModelParameter Parameter { get; }
IDiffusionModelParameter IDiffusionModelBuilder.Parameter => Parameter;
IModelParameter IModelBuilder.Parameter => Parameter;
#endregion
#region Constructors
public StableDiffusion3_5ModelBuilder(string modelPath, string clipLPath, string clipGPath, string t5xxlPath)
{
Parameter = new DiffusionModelParameter
{
ModelPath = modelPath,
ClipLPath = clipLPath,
ClipGPath = clipGPath,
T5xxlPath = t5xxlPath,
};
}
#endregion
#region Methods
public DiffusionModel Build() => new(Parameter);
#endregion
}

View File

@ -1,31 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public sealed class StableDiffusionModelBuilder : IDiffusionModelBuilder
{
#region Properties & Fields
public DiffusionModelParameter Parameter { get; }
IDiffusionModelParameter IDiffusionModelBuilder.Parameter => Parameter;
IModelParameter IModelBuilder.Parameter => Parameter;
#endregion
#region Constructors
public StableDiffusionModelBuilder(string modelPath)
{
Parameter = new DiffusionModelParameter { ModelPath = modelPath };
}
#endregion
#region Methods
public DiffusionModel Build() => new(Parameter);
#endregion
}

View File

@ -64,25 +64,24 @@ public sealed unsafe class DiffusionModel : IDisposable
} }
} }
// TODO DarthAffe 09.08.2025: Implement when no longer marked as broken public Image<ColorRGB>[] GenerateVideo(VideoGenerationParameter parameter)
//public Image<ColorRGB>[] GenerateVideo() {
//{ ObjectDisposedException.ThrowIf(_disposed, this);
// ObjectDisposedException.ThrowIf(_disposed, this);
// //parameter.Validate(); parameter.Validate();
// int imageCount = 0; // TODO DarthAffe 09.08.2025: Set correct count Native.Types.sd_image_t* result = Native.generate_video(_ctx, parameter, out int frameCount);
if (result == null) return [];
// Native.Types.sd_image_t* result = Native.generate_video(_ctx, new Native.Types.sd_vid_gen_params_t()); // TODO DarthAffe 09.08.2025: Add Parameter try
// try {
// { return ImageHelper.ToImageArray(result, frameCount);
// return ImageHelper.ToImageArray(result, imageCount); }
// } finally
// finally {
// { ImageHelper.Free(result, frameCount);
// ImageHelper.Free(result, imageCount); }
// } }
//}
public void Dispose() public void Dispose()
{ {

View File

@ -3,7 +3,7 @@
namespace StableDiffusion.NET; namespace StableDiffusion.NET;
[PublicAPI] [PublicAPI]
public sealed class DiffusionModelParameter : IDiffusionModelParameter public sealed class DiffusionModelParameter
{ {
/// <summary> /// <summary>
/// path to vae /// path to vae
@ -46,16 +46,18 @@ public sealed class DiffusionModelParameter : IDiffusionModelParameter
/// </summary> /// </summary>
public bool VaeTiling { get; set; } = false; public bool VaeTiling { get; set; } = false;
/// <summary> public bool OffloadParamsToCPU { get; set; } = false;
/// keep controlnet in cpu
/// </summary>
public bool KeepControlNetOnCPU { get; set; } = false;
/// <summary> /// <summary>
/// keep clip in cpu (for low vram) /// keep clip in cpu (for low vram)
/// </summary> /// </summary>
public bool KeepClipOnCPU { get; set; } = false; public bool KeepClipOnCPU { get; set; } = false;
/// <summary>
/// keep controlnet in cpu
/// </summary>
public bool KeepControlNetOnCPU { get; set; } = false;
/// <summary> /// <summary>
/// keep vae in cpu (for low vram) /// keep vae in cpu (for low vram)
/// </summary> /// </summary>
@ -78,17 +80,14 @@ public sealed class DiffusionModelParameter : IDiffusionModelParameter
/// use Conv2d direct in the vae model (should improve the performance) /// use Conv2d direct in the vae model (should improve the performance)
/// This might crash if it is not supported by the backend. /// This might crash if it is not supported by the backend.
/// </summary> /// </summary>
public bool VaeConfDirect { get; set; } = false; public bool VaeConvDirect { get; set; } = false;
/// <summary> /// <summary>
/// RNG (default: Standard) /// RNG (default: Standard)
/// </summary> /// </summary>
public RngType RngType { get; set; } = RngType.Standard; public RngType RngType { get; set; } = RngType.Standard;
/// <summary> public Prediction Prediction { get; set; } = Prediction.Default;
/// Denoiser sigma schedule (default: Default)
/// </summary>
public Schedule Schedule { get; set; } = Schedule.Default;
/// <summary> /// <summary>
/// quantizes on load /// quantizes on load
@ -96,18 +95,20 @@ public sealed class DiffusionModelParameter : IDiffusionModelParameter
/// </summary> /// </summary>
public Quantization Quantization { get; set; } = Quantization.Unspecified; public Quantization Quantization { get; set; } = Quantization.Unspecified;
// SD <= 3 only public float FlowShift { get; set; } = 0;
/// <summary>
/// path to full model public bool ForceSdxlVaeConvScale { get; set; } = false;
/// </summary>
public string ModelPath { get; set; } = string.Empty;
/// <summary> /// <summary>
/// path to PHOTOMAKER stacked id embeddings /// path to PHOTOMAKER stacked id embeddings
/// </summary> /// </summary>
public string StackedIdEmbeddingsDirectory { get; set; } = string.Empty; public string StackedIdEmbeddingsDirectory { get; set; } = string.Empty;
// Flux & SD3.5 only /// <summary>
/// path to full model
/// </summary>
public string ModelPath { get; set; } = string.Empty;
/// <summary> /// <summary>
/// path to the standalone diffusion model /// path to the standalone diffusion model
/// </summary> /// </summary>
@ -118,21 +119,26 @@ public sealed class DiffusionModelParameter : IDiffusionModelParameter
/// </summary> /// </summary>
public string ClipLPath { get; set; } = string.Empty; public string ClipLPath { get; set; } = string.Empty;
/// <summary>
/// path to the the t5xxl text encoder
/// </summary>
public string T5xxlPath { get; set; } = string.Empty;
// Flux Chroma specific
public bool ChromaUseDitMap { get; set; } = true;
public bool ChromaEnableT5Map { get; set; } = false;
public int ChromaT5MaskPad { get; set; } = 1;
// SD3.5 only
/// <summary> /// <summary>
/// path to the clip-g text encoder /// path to the clip-g text encoder
/// </summary> /// </summary>
public string ClipGPath { get; set; } = string.Empty; public string ClipGPath { get; set; } = string.Empty;
/// <summary>
/// path to the the t5xxl text encoder
/// </summary>
public string T5xxlPath { get; set; } = string.Empty;
public string Qwen2VLPath { get; set; } = string.Empty;
public string Qwen2VLVisionPath { get; set; } = string.Empty;
public string ClipVisionPath { get; set; } = string.Empty;
public string HighNoiseDiffusionModelPath { get; set; } = string.Empty;
public bool ChromaUseDitMap { get; set; } = true;
public bool ChromaEnableT5Map { get; set; } = false;
public int ChromaT5MaskPad { get; set; } = 1;
public static DiffusionModelParameter Create() => new(); public static DiffusionModelParameter Create() => new();
} }

View File

@ -0,0 +1,280 @@
using System;
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public static class DiffusionModelBuilderExtension
{
public static DiffusionModelParameter WithVae(this DiffusionModelParameter parameter, string vaePath)
{
ArgumentNullException.ThrowIfNull(vaePath);
if (!string.IsNullOrWhiteSpace(parameter.TaesdPath)) throw new ArgumentException("TAESD is already enabled. VAE and TAESD are mutually exclusive.", nameof(vaePath));
parameter.VaePath = vaePath;
return parameter;
}
public static DiffusionModelParameter WithTaesd(this DiffusionModelParameter parameter, string taesdPath)
{
ArgumentNullException.ThrowIfNull(taesdPath);
if (!string.IsNullOrWhiteSpace(parameter.VaePath)) throw new ArgumentException("VAE is already enabled. TAESD and VAE are mutually exclusive.", nameof(taesdPath));
parameter.TaesdPath = taesdPath;
return parameter;
}
public static DiffusionModelParameter WithLoraSupport(this DiffusionModelParameter parameter, string loraModelDirectory)
{
ArgumentNullException.ThrowIfNull(loraModelDirectory);
parameter.LoraModelDirectory = loraModelDirectory;
return parameter;
}
public static DiffusionModelParameter WithEmbeddingSupport(this DiffusionModelParameter parameter, string embeddingsDirectory)
{
ArgumentNullException.ThrowIfNull(embeddingsDirectory);
parameter.EmbeddingsDirectory = embeddingsDirectory;
return parameter;
}
public static DiffusionModelParameter WithControlNet(this DiffusionModelParameter parameter, string controlNetPath)
{
ArgumentNullException.ThrowIfNull(controlNetPath);
parameter.ControlNetPath = controlNetPath;
return parameter;
}
public static DiffusionModelParameter WithoutMultithreading(this DiffusionModelParameter parameter)
{
parameter.ThreadCount = 1;
return parameter;
}
public static DiffusionModelParameter WithMultithreading(this DiffusionModelParameter parameter, int threadCount = 0)
{
ArgumentOutOfRangeException.ThrowIfLessThan(threadCount, 0, nameof(threadCount));
if (threadCount == 0) threadCount = Environment.ProcessorCount;
parameter.ThreadCount = threadCount;
return parameter;
}
public static DiffusionModelParameter WithVaeDecodeOnly(this DiffusionModelParameter parameter, bool vaeDecodeOnly = true)
{
parameter.VaeDecodeOnly = vaeDecodeOnly;
return parameter;
}
public static DiffusionModelParameter WithVaeTiling(this DiffusionModelParameter parameter, bool vaeTiling = true)
{
parameter.VaeTiling = vaeTiling;
return parameter;
}
public static DiffusionModelParameter WithOffloadedParamsToCPU(this DiffusionModelParameter parameter, bool offloadParamsToCPU = true)
{
parameter.OffloadParamsToCPU = offloadParamsToCPU;
return parameter;
}
public static DiffusionModelParameter WithClipNetOnCpu(this DiffusionModelParameter parameter, bool keepClipNetOnCpu = true)
{
parameter.KeepClipOnCPU = keepClipNetOnCpu;
return parameter;
}
public static DiffusionModelParameter WithControlNetOnCpu(this DiffusionModelParameter parameter, bool keepControlNetOnCpu = true)
{
parameter.KeepControlNetOnCPU = keepControlNetOnCpu;
return parameter;
}
public static DiffusionModelParameter WithVaeOnCpu(this DiffusionModelParameter parameter, bool keepVaeOnCpu = true)
{
parameter.KeepVaeOnCPU = keepVaeOnCpu;
return parameter;
}
public static DiffusionModelParameter WithFlashAttention(this DiffusionModelParameter parameter, bool flashAttention = true)
{
parameter.FlashAttention = flashAttention;
return parameter;
}
public static DiffusionModelParameter WithDiffusionConvDirect(this DiffusionModelParameter parameter, bool diffusionConvDirect = true)
{
parameter.DiffusionConvDirect = diffusionConvDirect;
return parameter;
}
public static DiffusionModelParameter WithVaeConvDirect(this DiffusionModelParameter parameter, bool vaeConvDirect = true)
{
parameter.VaeConvDirect = vaeConvDirect;
return parameter;
}
public static DiffusionModelParameter WithRngType(this DiffusionModelParameter parameter, RngType rngType)
{
if (!Enum.IsDefined(rngType)) throw new ArgumentOutOfRangeException(nameof(rngType));
parameter.RngType = rngType;
return parameter;
}
public static DiffusionModelParameter WithPrediction(this DiffusionModelParameter parameter, Prediction prediction)
{
parameter.Prediction = prediction;
return parameter;
}
public static DiffusionModelParameter WithQuantization(this DiffusionModelParameter parameter, Quantization quantization)
{
if (!Enum.IsDefined(quantization)) throw new ArgumentOutOfRangeException(nameof(quantization));
parameter.Quantization = quantization;
return parameter;
}
public static DiffusionModelParameter WithFlowShift(this DiffusionModelParameter parameter, float flowShift)
{
parameter.FlowShift = flowShift;
return parameter;
}
public static DiffusionModelParameter WithForcedSdxlVaeConvScale(this DiffusionModelParameter parameter, bool forcedScale = true)
{
parameter.ForceSdxlVaeConvScale = forcedScale;
return parameter;
}
public static DiffusionModelParameter WithPhotomaker(this DiffusionModelParameter parameter, string stackedIdEmbeddingsDirectory)
{
ArgumentException.ThrowIfNullOrWhiteSpace(stackedIdEmbeddingsDirectory, nameof(stackedIdEmbeddingsDirectory));
parameter.StackedIdEmbeddingsDirectory = stackedIdEmbeddingsDirectory;
return parameter;
}
public static DiffusionModelParameter WithModelPath(this DiffusionModelParameter parameter, string modelPath)
{
ArgumentNullException.ThrowIfNull(modelPath);
parameter.ModelPath = modelPath;
return parameter;
}
public static DiffusionModelParameter WithDiffusionModelPath(this DiffusionModelParameter parameter, string diffusionModelPath)
{
ArgumentNullException.ThrowIfNull(diffusionModelPath);
parameter.DiffusionModelPath = diffusionModelPath;
return parameter;
}
public static DiffusionModelParameter WithClipLPath(this DiffusionModelParameter parameter, string clipLPath)
{
ArgumentNullException.ThrowIfNull(clipLPath);
parameter.ClipLPath = clipLPath;
return parameter;
}
public static DiffusionModelParameter WithClipGPath(this DiffusionModelParameter parameter, string clipGPath)
{
ArgumentNullException.ThrowIfNull(clipGPath);
parameter.ClipGPath = clipGPath;
return parameter;
}
public static DiffusionModelParameter WithT5xxlPath(this DiffusionModelParameter parameter, string t5xxlPath)
{
ArgumentNullException.ThrowIfNull(t5xxlPath);
parameter.T5xxlPath = t5xxlPath;
return parameter;
}
public static DiffusionModelParameter WithQwen2VLPath(this DiffusionModelParameter parameter, string qwen2VLPath)
{
parameter.Qwen2VLPath = qwen2VLPath;
return parameter;
}
public static DiffusionModelParameter WithQwen2VLVisionPath(this DiffusionModelParameter parameter, string qwen2VLVisionPath)
{
parameter.Qwen2VLVisionPath = qwen2VLVisionPath;
return parameter;
}
public static DiffusionModelParameter WithClipVisionPath(this DiffusionModelParameter parameter, string clipVisionPath)
{
parameter.ClipVisionPath = clipVisionPath;
return parameter;
}
public static DiffusionModelParameter WithHighNoiseDiffusionModelPath(this DiffusionModelParameter parameter, string highNoiseDiffusionModelPath)
{
parameter.HighNoiseDiffusionModelPath = highNoiseDiffusionModelPath;
return parameter;
}
public static DiffusionModelParameter UseChromaDitMap(this DiffusionModelParameter parameter, bool useChromaDitMap = true)
{
parameter.ChromaUseDitMap = useChromaDitMap;
return parameter;
}
public static DiffusionModelParameter EnableChromaT5Map(this DiffusionModelParameter parameter, bool enableChromaT5Map = true)
{
parameter.ChromaEnableT5Map = enableChromaT5Map;
return parameter;
}
public static DiffusionModelParameter WithChromaT5MaskPad(this DiffusionModelParameter parameter, int chromaT5MaskPad)
{
parameter.ChromaT5MaskPad = chromaT5MaskPad;
return parameter;
}
}

View File

@ -27,70 +27,6 @@ public static class ImageGenerationParameterExtension
return parameter; return parameter;
} }
public static ImageGenerationParameter WithCfg(this ImageGenerationParameter parameter, float cfg)
{
parameter.WithTxtCfg(cfg);
parameter.WithImgCfg(cfg);
return parameter;
}
public static ImageGenerationParameter WithTxtCfg(this ImageGenerationParameter parameter, float txtCfg)
{
parameter.Guidance.TxtCfg = txtCfg;
return parameter;
}
public static ImageGenerationParameter WithImgCfg(this ImageGenerationParameter parameter, float imgCfg)
{
parameter.Guidance.ImgCfg = imgCfg;
return parameter;
}
public static ImageGenerationParameter WithMinCfg(this ImageGenerationParameter parameter, float minCfg)
{
parameter.Guidance.MinCfg = minCfg;
return parameter;
}
public static ImageGenerationParameter WithGuidance(this ImageGenerationParameter parameter, float guidance)
{
parameter.Guidance.DistilledGuidance = guidance;
return parameter;
}
public static ImageGenerationParameter WithSlgScale(this ImageGenerationParameter parameter, float slgScale)
{
parameter.Guidance.Slg.Scale = slgScale;
return parameter;
}
public static ImageGenerationParameter WithSkipLayers(this ImageGenerationParameter parameter, int[] layers)
{
parameter.Guidance.Slg.Layers = layers;
return parameter;
}
public static ImageGenerationParameter WithSkipLayerStart(this ImageGenerationParameter parameter, float skipLayerStart)
{
parameter.Guidance.Slg.SkipLayerStart = skipLayerStart;
return parameter;
}
public static ImageGenerationParameter WithSkipLayerEnd(this ImageGenerationParameter parameter, float skipLayerEnd)
{
parameter.Guidance.Slg.SkipLayerEnd = skipLayerEnd;
return parameter;
}
public static ImageGenerationParameter WithInitImage(this ImageGenerationParameter parameter, IImage image) public static ImageGenerationParameter WithInitImage(this ImageGenerationParameter parameter, IImage image)
{ {
parameter.InitImage = image; parameter.InitImage = image;
@ -112,6 +48,20 @@ public static class ImageGenerationParameterExtension
return parameter; return parameter;
} }
public static ImageGenerationParameter WithRefIndexIncrease(this ImageGenerationParameter parameter, bool refIndexIncrease = true)
{
parameter.IncreaseRefIndex = refIndexIncrease;
return parameter;
}
public static ImageGenerationParameter WithRefImageAutoResize(this ImageGenerationParameter parameter, bool refImageAutoResize = true)
{
parameter.AutoResizeRefImage = refImageAutoResize;
return parameter;
}
public static ImageGenerationParameter WithSize(this ImageGenerationParameter parameter, int? width = null, int? height = null) public static ImageGenerationParameter WithSize(this ImageGenerationParameter parameter, int? width = null, int? height = null)
{ {
if (width != null) if (width != null)
@ -123,27 +73,117 @@ public static class ImageGenerationParameterExtension
return parameter; return parameter;
} }
#region SampleParameter
#region Guidance
public static ImageGenerationParameter WithCfg(this ImageGenerationParameter parameter, float cfg)
{
parameter.WithTxtCfg(cfg);
parameter.WithImgCfg(cfg);
return parameter;
}
public static ImageGenerationParameter WithTxtCfg(this ImageGenerationParameter parameter, float txtCfg)
{
parameter.SampleParameter.Guidance.TxtCfg = txtCfg;
return parameter;
}
public static ImageGenerationParameter WithImgCfg(this ImageGenerationParameter parameter, float imgCfg)
{
parameter.SampleParameter.Guidance.ImgCfg = imgCfg;
return parameter;
}
public static ImageGenerationParameter WithMinCfg(this ImageGenerationParameter parameter, float minCfg)
{
parameter.SampleParameter.Guidance.MinCfg = minCfg;
return parameter;
}
public static ImageGenerationParameter WithGuidance(this ImageGenerationParameter parameter, float guidance)
{
parameter.SampleParameter.Guidance.DistilledGuidance = guidance;
return parameter;
}
#region Slg
public static ImageGenerationParameter WithSkipLayers(this ImageGenerationParameter parameter, int[] layers)
{
parameter.SampleParameter.Guidance.Slg.Layers = layers;
return parameter;
}
public static ImageGenerationParameter WithSkipLayerStart(this ImageGenerationParameter parameter, float skipLayerStart)
{
parameter.SampleParameter.Guidance.Slg.SkipLayerStart = skipLayerStart;
return parameter;
}
public static ImageGenerationParameter WithSkipLayerEnd(this ImageGenerationParameter parameter, float skipLayerEnd)
{
parameter.SampleParameter.Guidance.Slg.SkipLayerEnd = skipLayerEnd;
return parameter;
}
public static ImageGenerationParameter WithSlgScale(this ImageGenerationParameter parameter, float slgScale)
{
parameter.SampleParameter.Guidance.Slg.Scale = slgScale;
return parameter;
}
#endregion
#endregion
public static ImageGenerationParameter WithScheduler(this ImageGenerationParameter parameter, Scheduler scheduler)
{
parameter.SampleParameter.Scheduler = scheduler;
return parameter;
}
public static ImageGenerationParameter WithSampler(this ImageGenerationParameter parameter, Sampler sampler) public static ImageGenerationParameter WithSampler(this ImageGenerationParameter parameter, Sampler sampler)
{ {
parameter.SampleMethod = sampler; parameter.SampleParameter.SampleMethod = sampler;
return parameter; return parameter;
} }
public static ImageGenerationParameter WithSteps(this ImageGenerationParameter parameter, int steps) public static ImageGenerationParameter WithSteps(this ImageGenerationParameter parameter, int steps)
{ {
parameter.SampleSteps = steps; parameter.SampleParameter.SampleSteps = steps;
return parameter; return parameter;
} }
public static ImageGenerationParameter WithEta(this ImageGenerationParameter parameter, float eta) public static ImageGenerationParameter WithEta(this ImageGenerationParameter parameter, float eta)
{ {
parameter.Eta = eta; parameter.SampleParameter.Eta = eta;
return parameter; return parameter;
} }
public static ImageGenerationParameter WithShiftedTimestep(this ImageGenerationParameter parameter, int shiftedTimestep)
{
parameter.SampleParameter.ShiftedTimestep = shiftedTimestep;
return parameter;
}
#endregion
public static ImageGenerationParameter WithStrength(this ImageGenerationParameter parameter, float strength) public static ImageGenerationParameter WithStrength(this ImageGenerationParameter parameter, float strength)
{ {
parameter.Strength = strength; parameter.Strength = strength;
@ -170,17 +210,64 @@ public static class ImageGenerationParameterExtension
public static ImageGenerationParameter WithPhotomaker(this ImageGenerationParameter parameter, string inputIdImageDirectory, float? styleStrength = null, bool? normalizeInput = null) public static ImageGenerationParameter WithPhotomaker(this ImageGenerationParameter parameter, string inputIdImageDirectory, float? styleStrength = null, bool? normalizeInput = null)
{ {
parameter.PhotoMaker.InputIdImageDirectory = inputIdImageDirectory; //todo
//parameter.PhotoMaker.InputIdImageDirectory = inputIdImageDirectory;
if (styleStrength != null) //if (styleStrength != null)
parameter.PhotoMaker.StyleStrength = styleStrength.Value; // parameter.PhotoMaker.StyleStrength = styleStrength.Value;
if (normalizeInput != null) //if (normalizeInput != null)
parameter.PhotoMaker.NormalizeInput = normalizeInput.Value; // parameter.PhotoMaker.NormalizeInput = normalizeInput.Value;
return parameter; return parameter;
} }
#region VaeTiling
public static ImageGenerationParameter WithVaeTiling(this ImageGenerationParameter parameter, bool tiling = true)
{
parameter.VaeTiling.IsEnabled = tiling;
return parameter;
}
public static ImageGenerationParameter WithVaeTileSizeX(this ImageGenerationParameter parameter, int tileSizeX)
{
parameter.VaeTiling.TileSizeX = tileSizeX;
return parameter;
}
public static ImageGenerationParameter WithVaeTileSizeY(this ImageGenerationParameter parameter, int tileSizeY)
{
parameter.VaeTiling.TileSizeY = tileSizeY;
return parameter;
}
public static ImageGenerationParameter WithVaeTargetOverlap(this ImageGenerationParameter parameter, float targetOverlap)
{
parameter.VaeTiling.TargetOverlap = targetOverlap;
return parameter;
}
public static ImageGenerationParameter WithVaeRelSizeX(this ImageGenerationParameter parameter, float relSizeX)
{
parameter.VaeTiling.RelSizeX = relSizeX;
return parameter;
}
public static ImageGenerationParameter WithVaeRelSizeY(this ImageGenerationParameter parameter, float relSizeY)
{
parameter.VaeTiling.RelSizeY = relSizeY;
return parameter;
}
#endregion
#region Defaults #region Defaults
public static ImageGenerationParameter WithSd1Defaults(this ImageGenerationParameter parameter) public static ImageGenerationParameter WithSd1Defaults(this ImageGenerationParameter parameter)

View File

@ -0,0 +1,49 @@
using System;
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public static class UpscaleModelBuilderExtension
{
public static UpscaleModelParameter WithModelPath(this UpscaleModelParameter parameter, string modelPath)
{
ArgumentNullException.ThrowIfNull(modelPath);
parameter.ModelPath = modelPath;
return parameter;
}
public static UpscaleModelParameter WithOffloadedParamsToCPU(this UpscaleModelParameter parameter, bool offloadParamsToCPU = true)
{
parameter.OffloadParamsToCPU = offloadParamsToCPU;
return parameter;
}
public static UpscaleModelParameter WithoutMultithreading(this UpscaleModelParameter parameter)
{
parameter.ThreadCount = 1;
return parameter;
}
public static UpscaleModelParameter WithMultithreading(this UpscaleModelParameter parameter, int threadCount = 0)
{
ArgumentOutOfRangeException.ThrowIfLessThan(threadCount, 0, nameof(threadCount));
if (threadCount == 0) threadCount = Environment.ProcessorCount;
parameter.ThreadCount = threadCount;
return parameter;
}
public static UpscaleModelParameter WithConvDirect(this UpscaleModelParameter parameter, bool convDirect = true)
{
parameter.ConvDirect = convDirect;
return parameter;
}
}

View File

@ -0,0 +1,318 @@
using HPPH;
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public static class VideoGenerationParameterExtension
{
public static VideoGenerationParameter WithPrompt(this VideoGenerationParameter parameter, string prompt)
{
parameter.Prompt = prompt;
return parameter;
}
public static VideoGenerationParameter WithNegativePrompt(this VideoGenerationParameter parameter, string negativePrompt)
{
parameter.NegativePrompt = negativePrompt;
return parameter;
}
public static VideoGenerationParameter WithClipSkip(this VideoGenerationParameter parameter, int clipSkip)
{
parameter.ClipSkip = clipSkip;
return parameter;
}
public static VideoGenerationParameter WithSize(this VideoGenerationParameter parameter, int? width = null, int? height = null)
{
if (width != null)
parameter.Width = width.Value;
if (height != null)
parameter.Height = height.Value;
return parameter;
}
public static VideoGenerationParameter WithInitImage(this VideoGenerationParameter parameter, IImage image)
{
parameter.InitImage = image;
return parameter;
}
public static VideoGenerationParameter WithEndImage(this VideoGenerationParameter parameter, IImage image)
{
parameter.EndImage = image;
return parameter;
}
public static VideoGenerationParameter WithControlFrames(this VideoGenerationParameter parameter, params IImage[] images)
{
parameter.ControlFrames = images;
return parameter;
}
#region SampleParameter
#region Guidance
public static VideoGenerationParameter WithCfg(this VideoGenerationParameter parameter, float cfg)
{
parameter.WithTxtCfg(cfg);
parameter.WithImgCfg(cfg);
return parameter;
}
public static VideoGenerationParameter WithTxtCfg(this VideoGenerationParameter parameter, float txtCfg)
{
parameter.SampleParameter.Guidance.TxtCfg = txtCfg;
return parameter;
}
public static VideoGenerationParameter WithImgCfg(this VideoGenerationParameter parameter, float imgCfg)
{
parameter.SampleParameter.Guidance.ImgCfg = imgCfg;
return parameter;
}
public static VideoGenerationParameter WithMinCfg(this VideoGenerationParameter parameter, float minCfg)
{
parameter.SampleParameter.Guidance.MinCfg = minCfg;
return parameter;
}
public static VideoGenerationParameter WithGuidance(this VideoGenerationParameter parameter, float guidance)
{
parameter.SampleParameter.Guidance.DistilledGuidance = guidance;
return parameter;
}
#region Slg
public static VideoGenerationParameter WithSkipLayers(this VideoGenerationParameter parameter, int[] layers)
{
parameter.SampleParameter.Guidance.Slg.Layers = layers;
return parameter;
}
public static VideoGenerationParameter WithSkipLayerStart(this VideoGenerationParameter parameter, float skipLayerStart)
{
parameter.SampleParameter.Guidance.Slg.SkipLayerStart = skipLayerStart;
return parameter;
}
public static VideoGenerationParameter WithSkipLayerEnd(this VideoGenerationParameter parameter, float skipLayerEnd)
{
parameter.SampleParameter.Guidance.Slg.SkipLayerEnd = skipLayerEnd;
return parameter;
}
public static VideoGenerationParameter WithSlgScale(this VideoGenerationParameter parameter, float slgScale)
{
parameter.SampleParameter.Guidance.Slg.Scale = slgScale;
return parameter;
}
#endregion
#endregion
public static VideoGenerationParameter WithScheduler(this VideoGenerationParameter parameter, Scheduler scheduler)
{
parameter.SampleParameter.Scheduler = scheduler;
return parameter;
}
public static VideoGenerationParameter WithSampler(this VideoGenerationParameter parameter, Sampler sampler)
{
parameter.SampleParameter.SampleMethod = sampler;
return parameter;
}
public static VideoGenerationParameter WithSteps(this VideoGenerationParameter parameter, int steps)
{
parameter.SampleParameter.SampleSteps = steps;
return parameter;
}
public static VideoGenerationParameter WithEta(this VideoGenerationParameter parameter, float eta)
{
parameter.SampleParameter.Eta = eta;
return parameter;
}
public static VideoGenerationParameter WithShiftedTimestep(this VideoGenerationParameter parameter, int shiftedTimestep)
{
parameter.SampleParameter.ShiftedTimestep = shiftedTimestep;
return parameter;
}
#endregion
#region HighNoiseSampleParameter
#region Guidance
public static VideoGenerationParameter WithHighNoiseCfg(this VideoGenerationParameter parameter, float cfg)
{
parameter.WithTxtCfg(cfg);
parameter.WithImgCfg(cfg);
return parameter;
}
public static VideoGenerationParameter WithHighNoiseTxtCfg(this VideoGenerationParameter parameter, float txtCfg)
{
parameter.HighNoiseSampleParameter.Guidance.TxtCfg = txtCfg;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseImgCfg(this VideoGenerationParameter parameter, float imgCfg)
{
parameter.HighNoiseSampleParameter.Guidance.ImgCfg = imgCfg;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseMinCfg(this VideoGenerationParameter parameter, float minCfg)
{
parameter.HighNoiseSampleParameter.Guidance.MinCfg = minCfg;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseGuidance(this VideoGenerationParameter parameter, float guidance)
{
parameter.HighNoiseSampleParameter.Guidance.DistilledGuidance = guidance;
return parameter;
}
#region Slg
public static VideoGenerationParameter WithHighNoiseSkipLayers(this VideoGenerationParameter parameter, int[] layers)
{
parameter.HighNoiseSampleParameter.Guidance.Slg.Layers = layers;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseSkipLayerStart(this VideoGenerationParameter parameter, float skipLayerStart)
{
parameter.HighNoiseSampleParameter.Guidance.Slg.SkipLayerStart = skipLayerStart;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseSkipLayerEnd(this VideoGenerationParameter parameter, float skipLayerEnd)
{
parameter.HighNoiseSampleParameter.Guidance.Slg.SkipLayerEnd = skipLayerEnd;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseSlgScale(this VideoGenerationParameter parameter, float slgScale)
{
parameter.HighNoiseSampleParameter.Guidance.Slg.Scale = slgScale;
return parameter;
}
#endregion
#endregion
public static VideoGenerationParameter WithHighNoiseScheduler(this VideoGenerationParameter parameter, Scheduler scheduler)
{
parameter.HighNoiseSampleParameter.Scheduler = scheduler;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseSampler(this VideoGenerationParameter parameter, Sampler sampler)
{
parameter.HighNoiseSampleParameter.SampleMethod = sampler;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseSteps(this VideoGenerationParameter parameter, int steps)
{
parameter.HighNoiseSampleParameter.SampleSteps = steps;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseEta(this VideoGenerationParameter parameter, float eta)
{
parameter.HighNoiseSampleParameter.Eta = eta;
return parameter;
}
public static VideoGenerationParameter WithHighNoiseShiftedTimestep(this VideoGenerationParameter parameter, int shiftedTimestep)
{
parameter.HighNoiseSampleParameter.ShiftedTimestep = shiftedTimestep;
return parameter;
}
#endregion
public static VideoGenerationParameter WithMoeBoundry(this VideoGenerationParameter parameter, float moeBoundry)
{
parameter.MoeBoundry = moeBoundry;
return parameter;
}
public static VideoGenerationParameter WithStrength(this VideoGenerationParameter parameter, float strength)
{
parameter.Strength = strength;
return parameter;
}
public static VideoGenerationParameter WithSeed(this VideoGenerationParameter parameter, long seed)
{
parameter.Seed = seed;
return parameter;
}
public static VideoGenerationParameter WithFrameCount(this VideoGenerationParameter parameter, int frameCount)
{
parameter.FrameCount = frameCount;
return parameter;
}
public static VideoGenerationParameter WithVaceStrength(this VideoGenerationParameter parameter, float vaceStrength)
{
parameter.VaceStrength = vaceStrength;
return parameter;
}
}

View File

@ -21,12 +21,14 @@ public sealed class ImageGenerationParameter
/// </summary> /// </summary>
public int ClipSkip { get; set; } = -1; public int ClipSkip { get; set; } = -1;
public GuidanceParameter Guidance { get; } = new();
public IImage? InitImage { get; set; } public IImage? InitImage { get; set; }
public IImage[]? RefImages { get; set; } public IImage[]? RefImages { get; set; }
public bool IncreaseRefIndex { get; set; } = false;
public bool AutoResizeRefImage { get; set; } = false;
public IImage? MaskImage { get; set; } public IImage? MaskImage { get; set; }
/// <summary> /// <summary>
@ -39,20 +41,7 @@ public sealed class ImageGenerationParameter
/// </summary> /// </summary>
public int Height { get; set; } = 512; public int Height { get; set; } = 512;
/// <summary> public SampleParameter SampleParameter { get; internal init; } = new();
/// sampling method (default: Euler_A)
/// </summary>
public Sampler SampleMethod { get; set; } = Sampler.Euler_A;
/// <summary>
/// number of sample steps (default: 25)
/// </summary>
public int SampleSteps { get; set; } = 25;
/// <summary>
/// eta in DDIM, only for DDIM and TCD (default: 0)
/// </summary>
public float Eta { get; set; } = 0f;
/// <summary> /// <summary>
/// strength for noising/unnoising (default: 0.7) /// strength for noising/unnoising (default: 0.7)
@ -68,10 +57,12 @@ public sealed class ImageGenerationParameter
public PhotoMakerParameter PhotoMaker { get; } = new(); public PhotoMakerParameter PhotoMaker { get; } = new();
public TilingParameter VaeTiling { get; } = new();
#endregion
public static ImageGenerationParameter Create() => new(); public static ImageGenerationParameter Create() => new();
public static ImageGenerationParameter TextToImage(string prompt) => Create().WithPrompt(prompt); public static ImageGenerationParameter TextToImage(string prompt) => Create().WithPrompt(prompt);
public static ImageGenerationParameter ImageToImage(string prompt, IImage image) => Create().WithPrompt(prompt).WithInitImage(image); public static ImageGenerationParameter ImageToImage(string prompt, IImage image) => Create().WithPrompt(prompt).WithInitImage(image);
#endregion
} }

View File

@ -1,41 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public interface IDiffusionModelParameter : IModelParameter
{
string VaePath { get; set; }
string TaesdPath { get; set; }
string LoraModelDirectory { get; set; }
string EmbeddingsDirectory { get; set; }
string ControlNetPath { get; set; }
bool VaeDecodeOnly { get; set; }
bool VaeTiling { get; set; }
bool KeepControlNetOnCPU { get; set; }
bool KeepClipOnCPU { get; set; }
bool KeepVaeOnCPU { get; set; }
bool FlashAttention { get; set; }
bool DiffusionConvDirect { get; set; }
bool VaeConfDirect { get; set; }
RngType RngType { get; set; }
Schedule Schedule { get; set; }
Quantization Quantization { get; set; }
string ModelPath { get; set; }
string StackedIdEmbeddingsDirectory { get; set; }
string DiffusionModelPath { get; set; }
string ClipLPath { get; set; }
string T5xxlPath { get; set; }
bool ChromaUseDitMap { get; set; }
bool ChromaEnableT5Map { get; set; }
int ChromaT5MaskPad { get; set; }
string ClipGPath { get; set; }
}

View File

@ -1,9 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public interface IModelParameter
{
int ThreadCount { get; set; }
}

View File

@ -1,10 +0,0 @@
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public interface IUpscaleModelParameter : IModelParameter
{
string ModelPath { get; set; }
bool ConvDirect { get; set; }
}

View File

@ -1,21 +1,17 @@
namespace StableDiffusion.NET; using HPPH;
namespace StableDiffusion.NET;
public sealed class PhotoMakerParameter public sealed class PhotoMakerParameter
{ {
/// <summary> public IImage[]? IdImages { get; set; }
/// path to PHOTOMAKER input id images dir
/// </summary> public string IdEmbedPath { get; set; } = string.Empty;
public string InputIdImageDirectory { get; set; } = string.Empty;
/// <summary> /// <summary>
/// strength for keeping input identity (default: 20) /// strength for keeping input identity (default: 20)
/// </summary> /// </summary>
public float StyleStrength { get; set; } = 20f; public float StyleStrength { get; set; } = 20f;
/// <summary>
/// normalize PHOTOMAKER input id images
/// </summary>
public bool NormalizeInput { get; set; } = false;
internal PhotoMakerParameter() { } internal PhotoMakerParameter() { }
} }

View File

@ -0,0 +1,30 @@
namespace StableDiffusion.NET;
public sealed class SampleParameter
{
public GuidanceParameter Guidance { get; } = new();
/// <summary>
/// Denoiser sigma schedule (default: Default)
/// </summary>
public Scheduler Scheduler { get; set; } = Scheduler.Default;
/// <summary>
/// sampling method (default: Euler_A)
/// </summary>
public Sampler SampleMethod { get; set; } = Sampler.Euler_A;
/// <summary>
/// number of sample steps (default: 25)
/// </summary>
public int SampleSteps { get; set; } = 25;
/// <summary>
/// eta in DDIM, only for DDIM and TCD (default: 0)
/// </summary>
public float Eta { get; set; } = 0f;
public int ShiftedTimestep { get; set; } = 0;
internal SampleParameter() { }
}

View File

@ -0,0 +1,14 @@
namespace StableDiffusion.NET;
public sealed class TilingParameter
{
public bool IsEnabled { get; set; }
public int TileSizeX { get; set; }
public int TileSizeY { get; set; }
public float TargetOverlap { get; set; }
public float RelSizeX { get; set; }
public float RelSizeY { get; set; }
internal TilingParameter() { }
}

View File

@ -3,13 +3,15 @@
namespace StableDiffusion.NET; namespace StableDiffusion.NET;
[PublicAPI] [PublicAPI]
public sealed class UpscaleModelParameter : IUpscaleModelParameter public sealed class UpscaleModelParameter
{ {
/// <summary> /// <summary>
/// path to esrgan model. Upscale images after generate, just RealESRGAN_x4plus_anime_6B supported by now /// path to esrgan model. Upscale images after generate, just RealESRGAN_x4plus_anime_6B supported by now
/// </summary> /// </summary>
public string ModelPath { get; set; } = string.Empty; public string ModelPath { get; set; } = string.Empty;
public bool OffloadParamsToCPU { get; set; } = false;
/// <summary> /// <summary>
/// number of threads to use during computation (default: -1) /// number of threads to use during computation (default: -1)
/// If threads = -1, then threads will be set to the number of CPU physical cores /// If threads = -1, then threads will be set to the number of CPU physical cores

View File

@ -0,0 +1,46 @@
using HPPH;
using JetBrains.Annotations;
namespace StableDiffusion.NET;
[PublicAPI]
public sealed class VideoGenerationParameter
{
#region Properties & Fields
public string Prompt { get; set; } = string.Empty;
public string NegativePrompt { get; set; } = string.Empty;
public int ClipSkip { get; set; } = -1;
public IImage? InitImage { get; set; }
public IImage? EndImage { get; set; }
public IImage[]? ControlFrames { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public SampleParameter SampleParameter { get; internal init; } = new();
public SampleParameter HighNoiseSampleParameter { get; internal init; } = new();
public float MoeBoundry { get; set; }
public float Strength { get; set; }
public long Seed { get; set; }
public int FrameCount { get; set; }
public float VaceStrength { get; set; }
#endregion
public static VideoGenerationParameter Create() => new();
public static VideoGenerationParameter TextToVideo(string prompt) => Create().WithPrompt(prompt);
}

View File

@ -39,8 +39,9 @@ public sealed unsafe class UpscaleModel : IDisposable
private void Initialize() private void Initialize()
{ {
_ctx = Native.new_upscaler_ctx(ModelParameter.ModelPath, _ctx = Native.new_upscaler_ctx(ModelParameter.ModelPath,
ModelParameter.ThreadCount, ModelParameter.OffloadParamsToCPU,
ModelParameter.ConvDirect); ModelParameter.ConvDirect,
ModelParameter.ThreadCount);
if (_ctx == null) throw new NullReferenceException("Failed to initialize upscale-model."); if (_ctx == null) throw new NullReferenceException("Failed to initialize upscale-model.");
} }

View File

@ -12,30 +12,36 @@ internal static unsafe class DiffusionModelParameterMarshaller
model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ModelPath), model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ModelPath),
clip_l_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipLPath), clip_l_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipLPath),
clip_g_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipGPath), clip_g_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipGPath),
clip_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipVisionPath),
t5xxl_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.T5xxlPath), t5xxl_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.T5xxlPath),
qwen2vl_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.Qwen2VLPath),
qwen2vl_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.Qwen2VLVisionPath),
diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.DiffusionModelPath), diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.DiffusionModelPath),
high_noise_diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.HighNoiseDiffusionModelPath),
vae_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.VaePath), vae_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.VaePath),
taesd_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.TaesdPath), taesd_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.TaesdPath),
control_net_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ControlNetPath), control_net_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ControlNetPath),
lora_model_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.LoraModelDirectory), lora_model_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.LoraModelDirectory),
embedding_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.EmbeddingsDirectory), embedding_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.EmbeddingsDirectory),
stacked_id_embed_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.StackedIdEmbeddingsDirectory), photo_maker_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.StackedIdEmbeddingsDirectory),
vae_decode_only = (sbyte)(managed.VaeDecodeOnly ? 1 : 0), vae_decode_only = (sbyte)(managed.VaeDecodeOnly ? 1 : 0),
vae_tiling = (sbyte)(managed.VaeTiling ? 1 : 0),
free_params_immediately = 0, // DarthAffe 06.08.2025: Static value free_params_immediately = 0, // DarthAffe 06.08.2025: Static value
n_threads = managed.ThreadCount, n_threads = managed.ThreadCount,
wtype = managed.Quantization, wtype = managed.Quantization,
rng_type = managed.RngType, rng_type = managed.RngType,
schedule = managed.Schedule, prediction = managed.Prediction,
offload_params_to_cpu = (sbyte)(managed.OffloadParamsToCPU ? 1 : 0),
keep_clip_on_cpu = (sbyte)(managed.KeepClipOnCPU ? 1 : 0), keep_clip_on_cpu = (sbyte)(managed.KeepClipOnCPU ? 1 : 0),
keep_control_net_on_cpu = (sbyte)(managed.KeepControlNetOnCPU ? 1 : 0), keep_control_net_on_cpu = (sbyte)(managed.KeepControlNetOnCPU ? 1 : 0),
keep_vae_on_cpu = (sbyte)(managed.KeepVaeOnCPU ? 1 : 0), keep_vae_on_cpu = (sbyte)(managed.KeepVaeOnCPU ? 1 : 0),
diffusion_flash_attn = (sbyte)(managed.FlashAttention ? 1 : 0), diffusion_flash_attn = (sbyte)(managed.FlashAttention ? 1 : 0),
diffusion_conv_direct = (sbyte)(managed.DiffusionConvDirect ? 1 : 0), diffusion_conv_direct = (sbyte)(managed.DiffusionConvDirect ? 1 : 0),
vae_conv_direct = (sbyte)(managed.VaeConfDirect ? 1 : 0), vae_conv_direct = (sbyte)(managed.VaeConvDirect ? 1 : 0),
force_sdxl_vae_conv_scale = (sbyte)(managed.ForceSdxlVaeConvScale ? 1 : 0),
chroma_use_dit_mask = (sbyte)(managed.ChromaUseDitMap ? 1 : 0), chroma_use_dit_mask = (sbyte)(managed.ChromaUseDitMap ? 1 : 0),
chroma_use_t5_mask = (sbyte)(managed.ChromaEnableT5Map ? 1 : 0), chroma_use_t5_mask = (sbyte)(managed.ChromaEnableT5Map ? 1 : 0),
chroma_t5_mask_pad = managed.ChromaT5MaskPad chroma_t5_mask_pad = managed.ChromaT5MaskPad,
flow_shift = managed.FlowShift
}; };
public static DiffusionModelParameter ConvertToManaged(Native.Types.sd_ctx_params_t unmanaged) public static DiffusionModelParameter ConvertToManaged(Native.Types.sd_ctx_params_t unmanaged)
@ -44,29 +50,35 @@ internal static unsafe class DiffusionModelParameterMarshaller
ModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.model_path) ?? string.Empty, ModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.model_path) ?? string.Empty,
ClipLPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_l_path) ?? string.Empty, ClipLPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_l_path) ?? string.Empty,
ClipGPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_g_path) ?? string.Empty, ClipGPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_g_path) ?? string.Empty,
ClipVisionPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_vision_path) ?? string.Empty,
T5xxlPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.t5xxl_path) ?? string.Empty, T5xxlPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.t5xxl_path) ?? string.Empty,
Qwen2VLPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.qwen2vl_path) ?? string.Empty,
Qwen2VLVisionPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.qwen2vl_vision_path) ?? string.Empty,
DiffusionModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.diffusion_model_path) ?? string.Empty, DiffusionModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.diffusion_model_path) ?? string.Empty,
HighNoiseDiffusionModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.high_noise_diffusion_model_path) ?? string.Empty,
VaePath = AnsiStringMarshaller.ConvertToManaged(unmanaged.vae_path) ?? string.Empty, VaePath = AnsiStringMarshaller.ConvertToManaged(unmanaged.vae_path) ?? string.Empty,
TaesdPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.taesd_path) ?? string.Empty, TaesdPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.taesd_path) ?? string.Empty,
ControlNetPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.control_net_path) ?? string.Empty, ControlNetPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.control_net_path) ?? string.Empty,
LoraModelDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.lora_model_dir) ?? string.Empty, LoraModelDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.lora_model_dir) ?? string.Empty,
EmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.embedding_dir) ?? string.Empty, EmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.embedding_dir) ?? string.Empty,
StackedIdEmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.stacked_id_embed_dir) ?? string.Empty, StackedIdEmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.photo_maker_path) ?? string.Empty,
VaeDecodeOnly = unmanaged.vae_decode_only == 1, VaeDecodeOnly = unmanaged.vae_decode_only == 1,
VaeTiling = unmanaged.vae_tiling == 1,
ThreadCount = unmanaged.n_threads, ThreadCount = unmanaged.n_threads,
Quantization = unmanaged.wtype, Quantization = unmanaged.wtype,
RngType = unmanaged.rng_type, RngType = unmanaged.rng_type,
Schedule = unmanaged.schedule, Prediction = unmanaged.prediction,
OffloadParamsToCPU = unmanaged.offload_params_to_cpu == 1,
KeepClipOnCPU = unmanaged.keep_clip_on_cpu == 1, KeepClipOnCPU = unmanaged.keep_clip_on_cpu == 1,
KeepControlNetOnCPU = unmanaged.keep_control_net_on_cpu == 1, KeepControlNetOnCPU = unmanaged.keep_control_net_on_cpu == 1,
KeepVaeOnCPU = unmanaged.keep_vae_on_cpu == 1, KeepVaeOnCPU = unmanaged.keep_vae_on_cpu == 1,
FlashAttention = unmanaged.diffusion_flash_attn == 1, FlashAttention = unmanaged.diffusion_flash_attn == 1,
DiffusionConvDirect = unmanaged.diffusion_conv_direct == 1, DiffusionConvDirect = unmanaged.diffusion_conv_direct == 1,
VaeConfDirect = unmanaged.vae_conv_direct == 1, VaeConvDirect = unmanaged.vae_conv_direct == 1,
ForceSdxlVaeConvScale = unmanaged.force_sdxl_vae_conv_scale == 1,
ChromaUseDitMap = unmanaged.chroma_use_dit_mask == 1, ChromaUseDitMap = unmanaged.chroma_use_dit_mask == 1,
ChromaEnableT5Map = unmanaged.chroma_use_t5_mask == 1, ChromaEnableT5Map = unmanaged.chroma_use_t5_mask == 1,
ChromaT5MaskPad = unmanaged.chroma_t5_mask_pad ChromaT5MaskPad = unmanaged.chroma_t5_mask_pad,
FlowShift = unmanaged.flow_shift
}; };
public static void Free(Native.Types.sd_ctx_params_t unmanaged) public static void Free(Native.Types.sd_ctx_params_t unmanaged)
@ -75,12 +87,14 @@ internal static unsafe class DiffusionModelParameterMarshaller
AnsiStringMarshaller.Free(unmanaged.clip_l_path); AnsiStringMarshaller.Free(unmanaged.clip_l_path);
AnsiStringMarshaller.Free(unmanaged.clip_g_path); AnsiStringMarshaller.Free(unmanaged.clip_g_path);
AnsiStringMarshaller.Free(unmanaged.t5xxl_path); AnsiStringMarshaller.Free(unmanaged.t5xxl_path);
AnsiStringMarshaller.Free(unmanaged.qwen2vl_path);
AnsiStringMarshaller.Free(unmanaged.qwen2vl_vision_path);
AnsiStringMarshaller.Free(unmanaged.diffusion_model_path); AnsiStringMarshaller.Free(unmanaged.diffusion_model_path);
AnsiStringMarshaller.Free(unmanaged.vae_path); AnsiStringMarshaller.Free(unmanaged.vae_path);
AnsiStringMarshaller.Free(unmanaged.taesd_path); AnsiStringMarshaller.Free(unmanaged.taesd_path);
AnsiStringMarshaller.Free(unmanaged.control_net_path); AnsiStringMarshaller.Free(unmanaged.control_net_path);
AnsiStringMarshaller.Free(unmanaged.lora_model_dir); AnsiStringMarshaller.Free(unmanaged.lora_model_dir);
AnsiStringMarshaller.Free(unmanaged.embedding_dir); AnsiStringMarshaller.Free(unmanaged.embedding_dir);
AnsiStringMarshaller.Free(unmanaged.stacked_id_embed_dir); AnsiStringMarshaller.Free(unmanaged.photo_maker_path);
} }
} }

View File

@ -18,46 +18,37 @@ internal static class ImageGenerationParameterMarshaller
Prompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.prompt) ?? string.Empty, Prompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.prompt) ?? string.Empty,
NegativePrompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.negative_prompt) ?? string.Empty, NegativePrompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.negative_prompt) ?? string.Empty,
ClipSkip = unmanaged.clip_skip, ClipSkip = unmanaged.clip_skip,
Guidance = SampleParameter = SampleParameterMarshaller.ConvertToManaged(unmanaged.sample_params),
{
TxtCfg = unmanaged.guidance.txt_cfg,
ImgCfg = unmanaged.guidance.img_cfg,
MinCfg = unmanaged.guidance.min_cfg,
DistilledGuidance = unmanaged.guidance.distilled_guidance,
Slg =
{
Layers = new int[unmanaged.guidance.slg.layer_count],
SkipLayerStart = unmanaged.guidance.slg.layer_start,
SkipLayerEnd = unmanaged.guidance.slg.layer_end,
Scale = unmanaged.guidance.slg.scale
}
},
InitImage = unmanaged.init_image.data == null ? null : unmanaged.init_image.ToImage(), InitImage = unmanaged.init_image.data == null ? null : unmanaged.init_image.ToImage(),
RefImages = unmanaged.ref_images == null ? null : ImageHelper.ToImageArrayIFace(unmanaged.ref_images, unmanaged.ref_images_count), RefImages = unmanaged.ref_images == null ? null : ImageHelper.ToImageArrayIFace(unmanaged.ref_images, unmanaged.ref_images_count),
AutoResizeRefImage = unmanaged.auto_resize_ref_image == 1,
MaskImage = unmanaged.mask_image.data == null ? null : unmanaged.mask_image.ToImage(), MaskImage = unmanaged.mask_image.data == null ? null : unmanaged.mask_image.ToImage(),
Width = unmanaged.width, Width = unmanaged.width,
Height = unmanaged.height, Height = unmanaged.height,
SampleMethod = unmanaged.sample_method,
SampleSteps = unmanaged.sample_steps,
Eta = unmanaged.eta,
Strength = unmanaged.strength, Strength = unmanaged.strength,
Seed = unmanaged.seed, Seed = unmanaged.seed,
ControlNet = ControlNet =
{ {
Image = unmanaged.control_cond == null ? null : ImageHelper.GetImage(unmanaged.control_cond, 0), Image = unmanaged.control_image.ToImage(),
Strength = unmanaged.control_strength, Strength = unmanaged.control_strength,
}, },
PhotoMaker = PhotoMaker =
{ {
StyleStrength = unmanaged.style_strength, IdImages = unmanaged.pm_params.id_images == null ? null : ImageHelper.ToImageArrayIFace(unmanaged.pm_params.id_images, unmanaged.pm_params.id_images_count),
NormalizeInput = unmanaged.normalize_input == 1, IdEmbedPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.pm_params.id_embed_path) ?? string.Empty,
InputIdImageDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.input_id_images_path) ?? string.Empty, StyleStrength = unmanaged.pm_params.style_strength,
},
VaeTiling =
{
IsEnabled = unmanaged.vae_tiling_params.enabled == 1,
TileSizeX = unmanaged.vae_tiling_params.tile_size_x,
TileSizeY = unmanaged.vae_tiling_params.tile_size_y,
TargetOverlap = unmanaged.vae_tiling_params.target_overlap,
RelSizeX = unmanaged.vae_tiling_params.rel_size_x,
RelSizeY = unmanaged.vae_tiling_params.rel_size_y
} }
}; };
if (unmanaged.guidance.slg.layers != null)
new Span<int>(unmanaged.guidance.slg.layers, (int)unmanaged.guidance.slg.layer_count).CopyTo(parameter.Guidance.Slg.Layers);
return parameter; return parameter;
} }
@ -65,39 +56,41 @@ internal static class ImageGenerationParameterMarshaller
{ {
AnsiStringMarshaller.Free(unmanaged.prompt); AnsiStringMarshaller.Free(unmanaged.prompt);
AnsiStringMarshaller.Free(unmanaged.negative_prompt); AnsiStringMarshaller.Free(unmanaged.negative_prompt);
AnsiStringMarshaller.Free(unmanaged.input_id_images_path);
unmanaged.init_image.Free(); unmanaged.init_image.Free();
unmanaged.mask_image.Free(); unmanaged.mask_image.Free();
unmanaged.control_image.Free();
if (unmanaged.ref_images != null) if (unmanaged.ref_images != null)
ImageHelper.Free(unmanaged.ref_images, unmanaged.ref_images_count); ImageHelper.Free(unmanaged.ref_images, unmanaged.ref_images_count);
if (unmanaged.control_cond != null) if (unmanaged.pm_params.id_images != null)
ImageHelper.Free(unmanaged.control_cond, 1); ImageHelper.Free(unmanaged.pm_params.id_images, unmanaged.pm_params.id_images_count);
if (unmanaged.guidance.slg.layers != null) SampleParameterMarshaller.Free(unmanaged.sample_params);
NativeMemory.Free(unmanaged.guidance.slg.layers);
} }
internal unsafe ref struct ImageGenerationParameterMarshallerIn internal unsafe ref struct ImageGenerationParameterMarshallerIn
{ {
private SampleParameterMarshaller.SampleParameterMarshallerIn _sampleParameterMarshaller = new();
private Native.Types.sd_img_gen_params_t _imgGenParams; private Native.Types.sd_img_gen_params_t _imgGenParams;
private Native.Types.sd_image_t _initImage; private Native.Types.sd_image_t _initImage;
private Native.Types.sd_image_t _maskImage; private Native.Types.sd_image_t _maskImage;
private Native.Types.sd_image_t _controlNetImage;
private Native.Types.sd_image_t* _refImages; private Native.Types.sd_image_t* _refImages;
private Native.Types.sd_image_t* _controlNetImage; private Native.Types.sd_image_t* _pmIdImages;
private int* _slgLayers;
public ImageGenerationParameterMarshallerIn() { }
public void FromManaged(ImageGenerationParameter managed) public void FromManaged(ImageGenerationParameter managed)
{ {
_initImage = managed.InitImage?.ToSdImage() ?? new Native.Types.sd_image_t(); _sampleParameterMarshaller.FromManaged(managed.SampleParameter);
_refImages = managed.RefImages == null ? null : managed.RefImages.ToSdImage();
_controlNetImage = managed.ControlNet.Image == null ? null : managed.ControlNet.Image.ToSdImagePtr();
_slgLayers = (int*)NativeMemory.Alloc((nuint)managed.Guidance.Slg.Layers.Length, (nuint)Marshal.SizeOf<int>()); _initImage = managed.InitImage?.ToSdImage() ?? new Native.Types.sd_image_t();
managed.Guidance.Slg.Layers.AsSpan().CopyTo(new Span<int>(_slgLayers, managed.Guidance.Slg.Layers.Length)); _controlNetImage = managed.ControlNet.Image?.ToSdImage() ?? new Native.Types.sd_image_t();
_refImages = managed.RefImages == null ? null : managed.RefImages.ToSdImage();
_pmIdImages = managed.PhotoMaker.IdImages == null ? null : managed.PhotoMaker.IdImages.ToSdImage();
if (managed.MaskImage != null) if (managed.MaskImage != null)
_maskImage = managed.MaskImage.ToSdImage(true); _maskImage = managed.MaskImage.ToSdImage(true);
@ -115,22 +108,22 @@ internal static class ImageGenerationParameterMarshaller
new Span<byte>(_maskImage.data, (int)maskImageByteSize).Fill(byte.MaxValue); new Span<byte>(_maskImage.data, (int)maskImageByteSize).Fill(byte.MaxValue);
} }
Native.Types.sd_slg_params_t slg = new() Native.Types.sd_pm_params_t photoMakerParams = new()
{ {
layers = _slgLayers, id_images = _pmIdImages,
layer_count = (uint)managed.Guidance.Slg.Layers.Length, id_images_count = managed.PhotoMaker.IdImages?.Length ?? 0,
layer_start = managed.Guidance.Slg.SkipLayerStart, id_embed_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.PhotoMaker.IdEmbedPath),
layer_end = managed.Guidance.Slg.SkipLayerEnd, style_strength = managed.PhotoMaker.StyleStrength
scale = managed.Guidance.Slg.Scale,
}; };
Native.Types.sd_guidance_params_t guidance = new() Native.Types.sd_tiling_params_t tilingParams = new()
{ {
txt_cfg = managed.Guidance.TxtCfg, enabled = (sbyte)(managed.VaeTiling.IsEnabled ? 1 : 0),
img_cfg = managed.Guidance.ImgCfg, tile_size_x = managed.VaeTiling.TileSizeX,
min_cfg = managed.Guidance.MinCfg, tile_size_y = managed.VaeTiling.TileSizeY,
distilled_guidance = managed.Guidance.DistilledGuidance, target_overlap = managed.VaeTiling.TargetOverlap,
slg = slg rel_size_x = managed.VaeTiling.RelSizeX,
rel_size_y = managed.VaeTiling.RelSizeY
}; };
_imgGenParams = new Native.Types.sd_img_gen_params_t _imgGenParams = new Native.Types.sd_img_gen_params_t
@ -138,24 +131,21 @@ internal static class ImageGenerationParameterMarshaller
prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.Prompt), prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.Prompt),
negative_prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.NegativePrompt), negative_prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.NegativePrompt),
clip_skip = managed.ClipSkip, clip_skip = managed.ClipSkip,
guidance = guidance, sample_params = _sampleParameterMarshaller.ToUnmanaged(),
init_image = _initImage, init_image = _initImage,
ref_images = _refImages, ref_images = _refImages,
ref_images_count = managed.RefImages?.Length ?? 0, ref_images_count = managed.RefImages?.Length ?? 0,
auto_resize_ref_image = (sbyte)(managed.AutoResizeRefImage ? 1 : 0),
mask_image = _maskImage, mask_image = _maskImage,
width = managed.Width, width = managed.Width,
height = managed.Height, height = managed.Height,
sample_method = managed.SampleMethod,
sample_steps = managed.SampleSteps,
eta = managed.Eta,
strength = managed.Strength, strength = managed.Strength,
seed = managed.Seed, seed = managed.Seed,
batch_count = 1, batch_count = 1,
control_cond = _controlNetImage, control_image = _controlNetImage,
control_strength = managed.ControlNet.Strength, control_strength = managed.ControlNet.Strength,
style_strength = managed.PhotoMaker.StyleStrength, pm_params = photoMakerParams,
normalize_input = (sbyte)(managed.PhotoMaker.NormalizeInput ? 1 : 0), vae_tiling_params = tilingParams
input_id_images_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.PhotoMaker.InputIdImageDirectory),
}; };
} }
@ -165,32 +155,32 @@ internal static class ImageGenerationParameterMarshaller
{ {
AnsiStringMarshaller.Free(_imgGenParams.prompt); AnsiStringMarshaller.Free(_imgGenParams.prompt);
AnsiStringMarshaller.Free(_imgGenParams.negative_prompt); AnsiStringMarshaller.Free(_imgGenParams.negative_prompt);
AnsiStringMarshaller.Free(_imgGenParams.input_id_images_path); AnsiStringMarshaller.Free(_imgGenParams.pm_params.id_embed_path);
_initImage.Free(); _initImage.Free();
_maskImage.Free(); _maskImage.Free();
_controlNetImage.Free();
if (_refImages != null) if (_refImages != null)
ImageHelper.Free(_refImages, _imgGenParams.ref_images_count); ImageHelper.Free(_refImages, _imgGenParams.ref_images_count);
if (_controlNetImage != null) if (_pmIdImages != null)
ImageHelper.Free(_controlNetImage, 1); ImageHelper.Free(_pmIdImages, _imgGenParams.pm_params.id_images_count);
if (_slgLayers != null) _sampleParameterMarshaller.Free();
NativeMemory.Free(_slgLayers);
} }
} }
internal ref struct ImageGenerationParameterMarshallerRef() internal ref struct ImageGenerationParameterMarshallerRef()
{ {
private ImageGenerationParameterMarshallerIn _inMarshaller = new(); private ImageGenerationParameterMarshallerIn _inMarshaller = new();
private ImageGenerationParameter _parameter; private ImageGenerationParameter? _parameter;
public void FromManaged(ImageGenerationParameter managed) => _inMarshaller.FromManaged(managed); public void FromManaged(ImageGenerationParameter managed) => _inMarshaller.FromManaged(managed);
public Native.Types.sd_img_gen_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged(); public Native.Types.sd_img_gen_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged();
public void FromUnmanaged(Native.Types.sd_img_gen_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged); public void FromUnmanaged(Native.Types.sd_img_gen_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged);
public ImageGenerationParameter ToManaged() => _parameter; public ImageGenerationParameter ToManaged() => _parameter!;
public void Free() => _inMarshaller.Free(); public void Free() => _inMarshaller.Free();
} }

View File

@ -0,0 +1,113 @@
// ReSharper disable MemberCanBeMadeStatic.Global
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
namespace StableDiffusion.NET;
[CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedIn, typeof(SampleParameterMarshallerIn))]
[CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedOut, typeof(SampleParameterMarshaller))]
[CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedRef, typeof(SampleParameterMarshallerRef))]
internal static class SampleParameterMarshaller
{
public static unsafe SampleParameter ConvertToManaged(Native.Types.sd_sample_params_t unmanaged)
{
SampleParameter parameter = new()
{
Guidance =
{
TxtCfg = unmanaged.guidance.txt_cfg,
ImgCfg = unmanaged.guidance.img_cfg,
MinCfg = unmanaged.guidance.min_cfg,
DistilledGuidance = unmanaged.guidance.distilled_guidance,
Slg =
{
Layers = new int[unmanaged.guidance.slg.layer_count],
SkipLayerStart = unmanaged.guidance.slg.layer_start,
SkipLayerEnd = unmanaged.guidance.slg.layer_end,
Scale = unmanaged.guidance.slg.scale
}
},
Scheduler = unmanaged.scheduler,
SampleMethod = unmanaged.sample_method,
SampleSteps = unmanaged.sample_steps,
Eta = unmanaged.eta,
ShiftedTimestep = unmanaged.shifted_timestep
};
if (unmanaged.guidance.slg.layers != null)
new Span<int>(unmanaged.guidance.slg.layers, (int)unmanaged.guidance.slg.layer_count).CopyTo(parameter.Guidance.Slg.Layers);
return parameter;
}
public static unsafe void Free(Native.Types.sd_sample_params_t unmanaged)
{
if (unmanaged.guidance.slg.layers != null)
NativeMemory.Free(unmanaged.guidance.slg.layers);
}
internal unsafe ref struct SampleParameterMarshallerIn
{
private Native.Types.sd_sample_params_t _sampleParams;
private int* _slgLayers;
public void FromManaged(SampleParameter managed)
{
_slgLayers = (int*)NativeMemory.Alloc((nuint)managed.Guidance.Slg.Layers.Length, (nuint)Marshal.SizeOf<int>());
managed.Guidance.Slg.Layers.AsSpan().CopyTo(new Span<int>(_slgLayers, managed.Guidance.Slg.Layers.Length));
Native.Types.sd_slg_params_t slg = new()
{
layers = _slgLayers,
layer_count = (uint)managed.Guidance.Slg.Layers.Length,
layer_start = managed.Guidance.Slg.SkipLayerStart,
layer_end = managed.Guidance.Slg.SkipLayerEnd,
scale = managed.Guidance.Slg.Scale,
};
Native.Types.sd_guidance_params_t guidance = new()
{
txt_cfg = managed.Guidance.TxtCfg,
img_cfg = managed.Guidance.ImgCfg,
min_cfg = managed.Guidance.MinCfg,
distilled_guidance = managed.Guidance.DistilledGuidance,
slg = slg
};
_sampleParams = new Native.Types.sd_sample_params_t
{
guidance = guidance,
scheduler = managed.Scheduler,
sample_method = managed.SampleMethod,
sample_steps = managed.SampleSteps,
eta = managed.Eta,
shifted_timestep = managed.ShiftedTimestep
};
}
public Native.Types.sd_sample_params_t ToUnmanaged() => _sampleParams;
public void Free()
{
if (_slgLayers != null)
NativeMemory.Free(_slgLayers);
}
}
internal ref struct SampleParameterMarshallerRef()
{
private SampleParameterMarshallerIn _inMarshaller = new();
private SampleParameter? _parameter;
public void FromManaged(SampleParameter managed) => _inMarshaller.FromManaged(managed);
public Native.Types.sd_sample_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged();
public void FromUnmanaged(Native.Types.sd_sample_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged);
public SampleParameter ToManaged() => _parameter ?? throw new NullReferenceException($"{nameof(FromUnmanaged)} needs to be called before ToManaged.");
public void Free() => _inMarshaller.Free();
}
}

View File

@ -0,0 +1,124 @@
// ReSharper disable MemberCanBeMadeStatic.Global
using System.Runtime.InteropServices.Marshalling;
namespace StableDiffusion.NET;
[CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedIn, typeof(VideoGenerationParameterMarshallerIn))]
[CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedOut, typeof(VideoGenerationParameterMarshaller))]
[CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedRef, typeof(VideoGenerationParameterMarshallerRef))]
internal static class VideoGenerationParameterMarshaller
{
public static unsafe VideoGenerationParameter ConvertToManaged(Native.Types.sd_vid_gen_params_t unmanaged)
{
VideoGenerationParameter parameter = new()
{
Prompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.prompt) ?? string.Empty,
NegativePrompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.negative_prompt) ?? string.Empty,
ClipSkip = unmanaged.clip_skip,
InitImage = unmanaged.init_image.data == null ? null : unmanaged.init_image.ToImage(),
EndImage = unmanaged.end_image.data == null ? null : unmanaged.end_image.ToImage(),
ControlFrames = unmanaged.control_frames == null ? null : ImageHelper.ToImageArrayIFace(unmanaged.control_frames, unmanaged.control_frames_size),
Width = unmanaged.width,
Height = unmanaged.height,
SampleParameter = SampleParameterMarshaller.ConvertToManaged(unmanaged.sample_params),
HighNoiseSampleParameter = SampleParameterMarshaller.ConvertToManaged(unmanaged.high_noise_sample_params),
MoeBoundry = unmanaged.moe_boundary,
Strength = unmanaged.strength,
Seed = unmanaged.seed,
FrameCount = unmanaged.video_frames,
VaceStrength = unmanaged.vace_strength
};
return parameter;
}
public static unsafe void Free(Native.Types.sd_vid_gen_params_t unmanaged)
{
AnsiStringMarshaller.Free(unmanaged.prompt);
AnsiStringMarshaller.Free(unmanaged.negative_prompt);
unmanaged.init_image.Free();
unmanaged.end_image.Free();
if (unmanaged.control_frames != null)
ImageHelper.Free(unmanaged.control_frames, unmanaged.control_frames_size);
SampleParameterMarshaller.Free(unmanaged.sample_params);
SampleParameterMarshaller.Free(unmanaged.high_noise_sample_params);
}
internal unsafe ref struct VideoGenerationParameterMarshallerIn
{
private SampleParameterMarshaller.SampleParameterMarshallerIn _sampleParameterMarshaller = new();
private SampleParameterMarshaller.SampleParameterMarshallerIn _highNoiseSampleParameterMarshaller = new();
private Native.Types.sd_vid_gen_params_t _vidGenParams;
private Native.Types.sd_image_t _initImage;
private Native.Types.sd_image_t _endImage;
private Native.Types.sd_image_t* _controlFrames;
public VideoGenerationParameterMarshallerIn() { }
public void FromManaged(VideoGenerationParameter managed)
{
_sampleParameterMarshaller.FromManaged(managed.SampleParameter);
_highNoiseSampleParameterMarshaller.FromManaged(managed.HighNoiseSampleParameter);
_initImage = managed.InitImage?.ToSdImage() ?? new Native.Types.sd_image_t();
_endImage = managed.EndImage?.ToSdImage() ?? new Native.Types.sd_image_t();
_controlFrames = managed.ControlFrames == null ? null : managed.ControlFrames.ToSdImage();
_vidGenParams = new Native.Types.sd_vid_gen_params_t
{
prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.Prompt),
negative_prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.NegativePrompt),
clip_skip = managed.ClipSkip,
init_image = _initImage,
end_image = _endImage,
control_frames = _controlFrames,
control_frames_size = managed.ControlFrames?.Length ?? 0,
width = managed.Width,
height = managed.Height,
sample_params = _sampleParameterMarshaller.ToUnmanaged(),
high_noise_sample_params = _highNoiseSampleParameterMarshaller.ToUnmanaged(),
moe_boundary = managed.MoeBoundry,
strength = managed.Strength,
seed = managed.Seed,
video_frames = managed.FrameCount,
vace_strength = managed.VaceStrength,
};
}
public Native.Types.sd_vid_gen_params_t ToUnmanaged() => _vidGenParams;
public void Free()
{
AnsiStringMarshaller.Free(_vidGenParams.prompt);
AnsiStringMarshaller.Free(_vidGenParams.negative_prompt);
_initImage.Free();
_endImage.Free();
if (_controlFrames != null)
ImageHelper.Free(_controlFrames, _vidGenParams.control_frames_size);
_sampleParameterMarshaller.Free();
_highNoiseSampleParameterMarshaller.Free();
}
}
internal ref struct VideoGenerationParameterMarshallerRef()
{
private VideoGenerationParameterMarshallerIn _inMarshaller = new();
private VideoGenerationParameter? _parameter;
public void FromManaged(VideoGenerationParameter managed) => _inMarshaller.FromManaged(managed);
public Native.Types.sd_vid_gen_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged();
public void FromUnmanaged(Native.Types.sd_vid_gen_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged);
public VideoGenerationParameter ToManaged() => _parameter!;
public void Free() => _inMarshaller.Free();
}
}

View File

@ -1,30 +1,31 @@
#pragma warning disable CS0169 // Field is never used #pragma warning disable IDE1006
#pragma warning disable IDE1006
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
// ReSharper disable ArrangeTypeMemberModifiers // ReSharper disable ArrangeTypeMemberModifiers
// ReSharper disable UseSymbolAlias // ReSharper disable UseSymbolAlias
using HPPH;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling; using System.Runtime.InteropServices.Marshalling;
using HPPH;
namespace StableDiffusion.NET; namespace StableDiffusion.NET;
using int32_t = int;
using int64_t = long;
using rng_type_t = RngType; using rng_type_t = RngType;
using sample_method_t = Sampler; using sample_method_t = Sampler;
using schedule_t = Schedule; using scheduler_t = Scheduler;
using sd_type_t = Quantization; using prediction_t = Prediction;
using sd_ctx_params_t = DiffusionModelParameter;
using sd_ctx_t = Native.Types.sd_ctx_t;
using sd_image_t = Native.Types.sd_image_t;
using sd_sample_params_t = SampleParameter;
using sd_img_gen_params_t = ImageGenerationParameter;
using sd_log_level_t = LogLevel; using sd_log_level_t = LogLevel;
using sd_type_t = Quantization;
using sd_vid_gen_params_t = VideoGenerationParameter;
using size_t = nuint;
using uint32_t = uint; using uint32_t = uint;
using uint8_t = byte; using uint8_t = byte;
using int64_t = long;
using size_t = nuint;
using int32_t = int;
using sd_ctx_params_t = DiffusionModelParameter;
using sd_img_gen_params_t = ImageGenerationParameter;
using sd_vid_gen_params_t = Native.Types.sd_vid_gen_params_t;
using sd_image_t = Native.Types.sd_image_t;
using sd_ctx_t = Native.Types.sd_ctx_t;
using upscaler_ctx_t = Native.Types.upscaler_ctx_t; using upscaler_ctx_t = Native.Types.upscaler_ctx_t;
internal unsafe partial class Native internal unsafe partial class Native
@ -37,36 +38,53 @@ internal unsafe partial class Native
internal static class Types internal static class Types
{ {
[StructLayout(LayoutKind.Sequential)]
public struct sd_tiling_params_t
{
public sbyte enabled;
public int tile_size_x;
public int tile_size_y;
public float target_overlap;
public float rel_size_x;
public float rel_size_y;
}
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct sd_ctx_params_t internal struct sd_ctx_params_t
{ {
public byte* model_path; public byte* model_path;
public byte* clip_l_path; public byte* clip_l_path;
public byte* clip_g_path; public byte* clip_g_path;
public byte* clip_vision_path;
public byte* t5xxl_path; public byte* t5xxl_path;
public byte* qwen2vl_path;
public byte* qwen2vl_vision_path;
public byte* diffusion_model_path; public byte* diffusion_model_path;
public byte* high_noise_diffusion_model_path;
public byte* vae_path; public byte* vae_path;
public byte* taesd_path; public byte* taesd_path;
public byte* control_net_path; public byte* control_net_path;
public byte* lora_model_dir; public byte* lora_model_dir;
public byte* embedding_dir; public byte* embedding_dir;
public byte* stacked_id_embed_dir; public byte* photo_maker_path;
public sbyte vae_decode_only; public sbyte vae_decode_only;
public sbyte vae_tiling;
public sbyte free_params_immediately; public sbyte free_params_immediately;
public int n_threads; public int n_threads;
public sd_type_t wtype; public sd_type_t wtype;
public rng_type_t rng_type; public rng_type_t rng_type;
public schedule_t schedule; public prediction_t prediction;
public sbyte offload_params_to_cpu;
public sbyte keep_clip_on_cpu; public sbyte keep_clip_on_cpu;
public sbyte keep_control_net_on_cpu; public sbyte keep_control_net_on_cpu;
public sbyte keep_vae_on_cpu; public sbyte keep_vae_on_cpu;
public sbyte diffusion_flash_attn; public sbyte diffusion_flash_attn;
public sbyte diffusion_conv_direct; public sbyte diffusion_conv_direct;
public sbyte vae_conv_direct; public sbyte vae_conv_direct;
public sbyte force_sdxl_vae_conv_scale;
public sbyte chroma_use_dit_mask; public sbyte chroma_use_dit_mask;
public sbyte chroma_use_t5_mask; public sbyte chroma_use_t5_mask;
public int chroma_t5_mask_pad; public int chroma_t5_mask_pad;
public float flow_shift;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
@ -98,47 +116,68 @@ internal unsafe partial class Native
public sd_slg_params_t slg; public sd_slg_params_t slg;
} }
[StructLayout(LayoutKind.Sequential)]
internal struct sd_sample_params_t
{
public sd_guidance_params_t guidance;
public scheduler_t scheduler;
public sample_method_t sample_method;
public int sample_steps;
public float eta;
public int shifted_timestep;
}
internal struct sd_pm_params_t
{
public sd_image_t* id_images;
public int id_images_count;
public byte* id_embed_path;
public float style_strength;
}
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct sd_img_gen_params_t internal struct sd_img_gen_params_t
{ {
public byte* prompt; public byte* prompt;
public byte* negative_prompt; public byte* negative_prompt;
public int clip_skip; public int clip_skip;
public sd_guidance_params_t guidance;
public sd_image_t init_image; public sd_image_t init_image;
public sd_image_t* ref_images; public sd_image_t* ref_images;
public int ref_images_count; public int ref_images_count;
public sbyte auto_resize_ref_image;
public sbyte increase_ref_index;
public sd_image_t mask_image; public sd_image_t mask_image;
public int width; public int width;
public int height; public int height;
public sample_method_t sample_method; public sd_sample_params_t sample_params;
public int sample_steps;
public float eta;
public float strength; public float strength;
public int64_t seed; public int64_t seed;
public int batch_count; public int batch_count;
public sd_image_t* control_cond; public sd_image_t control_image;
public float control_strength; public float control_strength;
public float style_strength; public sd_pm_params_t pm_params;
public sbyte normalize_input; public sd_tiling_params_t vae_tiling_params;
public byte* input_id_images_path;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal struct sd_vid_gen_params_t internal struct sd_vid_gen_params_t
{ {
public byte* prompt;
public byte* negative_prompt;
public int clip_skip;
public sd_image_t init_image; public sd_image_t init_image;
public sd_image_t end_image;
public sd_image_t* control_frames;
public int control_frames_size;
public int width; public int width;
public int height; public int height;
public sd_guidance_params_t guidance; public sd_sample_params_t sample_params;
public sample_method_t sample_method; public sd_sample_params_t high_noise_sample_params;
public int sample_steps; public float moe_boundary;
public float strength; public float strength;
public int64_t seed; public int64_t seed;
public int video_frames; public int video_frames;
public int motion_bucket_id; public float vace_strength;
public int fps;
public float augmentation_level;
} }
internal struct sd_ctx_t; internal struct sd_ctx_t;
@ -192,10 +231,17 @@ internal unsafe partial class Native
[LibraryImport(LIB_NAME, EntryPoint = "sd_schedule_name")] [LibraryImport(LIB_NAME, EntryPoint = "sd_schedule_name")]
[return: MarshalAs(UnmanagedType.LPStr)] [return: MarshalAs(UnmanagedType.LPStr)]
internal static partial string sd_schedule_name(schedule_t schedule); internal static partial string sd_schedule_name(scheduler_t schedule);
[LibraryImport(LIB_NAME, EntryPoint = "str_to_schedule")] [LibraryImport(LIB_NAME, EntryPoint = "str_to_schedule")]
internal static partial schedule_t str_to_schedule([MarshalAs(UnmanagedType.LPStr)] string str); internal static partial scheduler_t str_to_schedule([MarshalAs(UnmanagedType.LPStr)] string str);
[LibraryImport(LIB_NAME, EntryPoint = "sd_prediction_name")]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static partial string sd_prediction_name(prediction_t prediction);
[LibraryImport(LIB_NAME, EntryPoint = "str_to_prediction")]
internal static partial prediction_t str_to_prediction([MarshalAs(UnmanagedType.LPStr)] string str);
// //
@ -214,6 +260,16 @@ internal unsafe partial class Native
[LibraryImport(LIB_NAME, EntryPoint = "free_sd_ctx")] [LibraryImport(LIB_NAME, EntryPoint = "free_sd_ctx")]
internal static partial void free_sd_ctx(sd_ctx_t* sd_ctx); internal static partial void free_sd_ctx(sd_ctx_t* sd_ctx);
[LibraryImport(LIB_NAME, EntryPoint = "sd_get_default_sample_method")]
internal static partial sample_method_t sd_get_default_sample_method(sd_ctx_t* sd_ctx);
//
[LibraryImport(LIB_NAME, EntryPoint = "sd_sample_params_init")]
internal static partial void sd_sample_params_init([MarshalUsing(typeof(SampleParameterMarshaller))] ref sd_sample_params_t sample_params);
[LibraryImport(LIB_NAME, EntryPoint = "sd_sample_params_to_str")]
internal static partial char* sd_sample_params_to_str([MarshalUsing(typeof(SampleParameterMarshaller))] in sd_sample_params_t sample_params);
// //
[LibraryImport(LIB_NAME, EntryPoint = "sd_img_gen_params_init")] [LibraryImport(LIB_NAME, EntryPoint = "sd_img_gen_params_init")]
@ -229,16 +285,18 @@ internal unsafe partial class Native
// //
[LibraryImport(LIB_NAME, EntryPoint = "sd_vid_gen_params_init")] [LibraryImport(LIB_NAME, EntryPoint = "sd_vid_gen_params_init")]
internal static partial void sd_vid_gen_params_init(ref sd_vid_gen_params_t sd_vid_gen_params); internal static partial void sd_vid_gen_params_init([MarshalUsing(typeof(VideoGenerationParameterMarshaller))] ref sd_vid_gen_params_t sd_vid_gen_params);
[LibraryImport(LIB_NAME, EntryPoint = "generate_video")] [LibraryImport(LIB_NAME, EntryPoint = "generate_video")]
[return: MarshalUsing(typeof(ImageMarshaller))] internal static partial sd_image_t* generate_video(sd_ctx_t* sd_ctx, [MarshalUsing(typeof(VideoGenerationParameterMarshaller))] in sd_vid_gen_params_t sd_vid_gen_params, out int num_frames_out);
internal static partial sd_image_t* generate_video(sd_ctx_t* sd_ctx, in sd_vid_gen_params_t sd_vid_gen_params); // broken
// //
[LibraryImport(LIB_NAME, EntryPoint = "new_upscaler_ctx")] [LibraryImport(LIB_NAME, EntryPoint = "new_upscaler_ctx")]
internal static partial upscaler_ctx_t* new_upscaler_ctx([MarshalAs(UnmanagedType.LPStr)] string esrgan_path, int n_threads, [MarshalAs(UnmanagedType.I1)] bool direct); internal static partial upscaler_ctx_t* new_upscaler_ctx([MarshalAs(UnmanagedType.LPStr)] string esrgan_path,
[MarshalAs(UnmanagedType.I1)] bool offload_params_to_cpu,
[MarshalAs(UnmanagedType.I1)] bool direct,
int n_threads);
[LibraryImport(LIB_NAME, EntryPoint = "free_upscaler_ctx")] [LibraryImport(LIB_NAME, EntryPoint = "free_upscaler_ctx")]
internal static partial void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx); internal static partial void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx);
@ -249,6 +307,9 @@ internal unsafe partial class Native
[return: MarshalUsing(typeof(ImageMarshaller))] [return: MarshalUsing(typeof(ImageMarshaller))]
internal static partial Image<ColorRGB> upscale(upscaler_ctx_t* upscaler_ctx, [MarshalUsing(typeof(ImageMarshaller))] IImage input_image, uint32_t upscale_factor); internal static partial Image<ColorRGB> upscale(upscaler_ctx_t* upscaler_ctx, [MarshalUsing(typeof(ImageMarshaller))] IImage input_image, uint32_t upscale_factor);
[LibraryImport(LIB_NAME, EntryPoint = "get_upscale_factor")]
internal static partial int get_upscale_factor(upscaler_ctx_t* upscaler_ctx);
// //
[LibraryImport(LIB_NAME, EntryPoint = "convert")] [LibraryImport(LIB_NAME, EntryPoint = "convert")]
@ -262,14 +323,13 @@ internal unsafe partial class Native
// //
[LibraryImport(LIB_NAME, EntryPoint = "preprocess_canny")] [LibraryImport(LIB_NAME, EntryPoint = "preprocess_canny")]
internal static partial uint8_t* preprocess_canny(uint8_t* img, [return: MarshalAs(UnmanagedType.I1)]
int width, internal static partial bool preprocess_canny(sd_image_t image,
int height, float high_threshold,
float high_threshold, float low_threshold,
float low_threshold, float weak,
float weak, float strong,
float strong, [MarshalAs(UnmanagedType.I1)] bool inverse);
[MarshalAs(UnmanagedType.I1)] bool inverse);
#endregion #endregion
} }

View File

@ -10,6 +10,8 @@
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder_005Cextensions/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder_005Cextensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder_005Cinterfaces/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cextensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter_005Cextensions/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter_005Cextensions/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter_005Cinterfaces/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>

View File

@ -11,8 +11,8 @@ public static unsafe class StableDiffusionCpp
#region Properties & Fields #region Properties & Fields
// ReSharper disable NotAccessedField.Local - They are important, the delegate can be collected if it's not stored! // ReSharper disable NotAccessedField.Local - They are important, the delegate can be collected if it's not stored!
private static Native.sd_log_cb_t LOG_CALLBACK; private static Native.sd_log_cb_t? _logCallback;
private static Native.sd_progress_cb_t PROGRESS_CALLBACK; private static Native.sd_progress_cb_t? _progressCallback;
// ReSharper restore NotAccessedField.Local // ReSharper restore NotAccessedField.Local
#endregion #endregion
@ -30,8 +30,8 @@ public static unsafe class StableDiffusionCpp
public static void InitializeEvents() public static void InitializeEvents()
{ {
Native.sd_set_log_callback(LOG_CALLBACK = OnNativeLog, null); Native.sd_set_log_callback(_logCallback = OnNativeLog, null);
Native.sd_set_progress_callback(PROGRESS_CALLBACK = OnNativeProgress, null); Native.sd_set_progress_callback(_progressCallback = OnNativeProgress, null);
} }
public static void Convert(string modelPath, string vaePath, Quantization quantization, string outputPath, string tensorTypeRules = "") public static void Convert(string modelPath, string vaePath, Quantization quantization, string outputPath, string tensorTypeRules = "")
@ -54,27 +54,21 @@ public static unsafe class StableDiffusionCpp
IImage<ColorRGB> controlImage = parameter.Image as IImage<ColorRGB> ?? parameter.Image!.ConvertTo<ColorRGB>(); IImage<ColorRGB> controlImage = parameter.Image as IImage<ColorRGB> ?? parameter.Image!.ConvertTo<ColorRGB>();
byte[] controlImageData = controlImage.ToRawArray(); Native.Types.sd_image_t sdImage = controlImage.ToSdImage();
fixed (byte* controlImagePtr = controlImageData) try
{ {
byte* result = Native.preprocess_canny(controlImagePtr, bool result = Native.preprocess_canny(sdImage,
controlImage.Width, parameter.HighThreshold,
controlImage.Height, parameter.LowThreshold,
parameter.HighThreshold, parameter.Weak,
parameter.LowThreshold, parameter.Strong,
parameter.Weak, parameter.Inverse);
parameter.Strong,
parameter.Inverse);
try return sdImage.ToImage();
{ }
return Image<ColorRGB>.Create(new ReadOnlySpan<ColorRGB>(result, controlImageData.Length), finally
controlImage.Width, controlImage.Height); {
} sdImage.Free();
finally
{
NativeMemory.Free(result);
}
} }
} }