From 1b8c2fce9d0eccd0691ffc7253c77d9faf3811be Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Tue, 2 Jan 2024 15:16:24 +0100 Subject: [PATCH] Updated to stable-diffusion.cpp 2c5f3fc and moved to the now included C-API --- StableDiffusion.NET/Attributes/NativeName.cs | 22 -- StableDiffusion.NET/Enums/LogLevel.cs | 7 - StableDiffusion.NET/Enums/Quantization.cs | 42 ++-- StableDiffusion.NET/Enums/RngType.cs | 3 - StableDiffusion.NET/Enums/Sampler.cs | 17 -- StableDiffusion.NET/Enums/Schedule.cs | 7 - .../Extensions/EnumExtension.cs | 18 -- StableDiffusion.NET/ModelParameter.cs | 7 +- StableDiffusion.NET/Native.cs | 134 ++++++------ StableDiffusion.NET/StableDiffusion.cs | 78 ------- StableDiffusion.NET/StableDiffusionImage.cs | 29 +-- StableDiffusion.NET/StableDiffusionModel.cs | 181 ++++++++++++++++ .../StableDiffusionParameter.cs | 201 +----------------- StableDiffusion.NET/UpscalerModelParameter.cs | 14 ++ build.bat | 14 +- 15 files changed, 321 insertions(+), 453 deletions(-) delete mode 100644 StableDiffusion.NET/Attributes/NativeName.cs delete mode 100644 StableDiffusion.NET/Extensions/EnumExtension.cs delete mode 100644 StableDiffusion.NET/StableDiffusion.cs create mode 100644 StableDiffusion.NET/StableDiffusionModel.cs create mode 100644 StableDiffusion.NET/UpscalerModelParameter.cs diff --git a/StableDiffusion.NET/Attributes/NativeName.cs b/StableDiffusion.NET/Attributes/NativeName.cs deleted file mode 100644 index ac02cb3..0000000 --- a/StableDiffusion.NET/Attributes/NativeName.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; - -namespace StableDiffusion.NET; - -[AttributeUsage(AttributeTargets.Field)] -internal class NativeName : Attribute -{ - #region Properties & Fields - - public string Name { get; set; } - - #endregion - - #region Constructors - - public NativeName(string name) - { - this.Name = name; - } - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Enums/LogLevel.cs b/StableDiffusion.NET/Enums/LogLevel.cs index d126512..0ab50f3 100644 --- a/StableDiffusion.NET/Enums/LogLevel.cs +++ b/StableDiffusion.NET/Enums/LogLevel.cs @@ -2,15 +2,8 @@ public enum LogLevel { - [NativeName("DEBUG")] Debug, - - [NativeName("INFO")] Info, - - [NativeName("WARN")] Warn, - - [NativeName("ERROR")] Error } \ No newline at end of file diff --git a/StableDiffusion.NET/Enums/Quantization.cs b/StableDiffusion.NET/Enums/Quantization.cs index 1a6b02f..e32f880 100644 --- a/StableDiffusion.NET/Enums/Quantization.cs +++ b/StableDiffusion.NET/Enums/Quantization.cs @@ -2,27 +2,23 @@ public enum Quantization { - [NativeName("DEFAULT")] - Default, - - [NativeName("F32")] - F32, - - [NativeName("F16")] - F16, - - [NativeName("Q4_0")] - Q4_0, - - [NativeName("Q4_1")] - Q4_1, - - [NativeName("Q5_0")] - Q5_0, - - [NativeName("Q5_1")] - Q5_1, - - [NativeName("Q8_0")] - Q8_0 + F32 = 0, + F16 = 1, + Q4_0 = 2, + Q4_1 = 3, + // Q4_2 = 4, support has been removed + // Q4_3 (5) support has been removed + Q5_0 = 6, + Q5_1 = 7, + Q8_0 = 8, + Q8_1 = 9, + Q2_K = 10, + Q3_K = 11, + Q4_K = 12, + Q5_K = 13, + Q6_K = 14, + Q8_K = 15, + I8, + I16, + I32, } \ No newline at end of file diff --git a/StableDiffusion.NET/Enums/RngType.cs b/StableDiffusion.NET/Enums/RngType.cs index e8c8381..a00d866 100644 --- a/StableDiffusion.NET/Enums/RngType.cs +++ b/StableDiffusion.NET/Enums/RngType.cs @@ -2,9 +2,6 @@ public enum RngType { - [NativeName("STD_DEFAULT_RNG")] Standard, - - [NativeName("CUDA_RNG")] Cuda } \ No newline at end of file diff --git a/StableDiffusion.NET/Enums/Sampler.cs b/StableDiffusion.NET/Enums/Sampler.cs index d1ccc45..83fe468 100644 --- a/StableDiffusion.NET/Enums/Sampler.cs +++ b/StableDiffusion.NET/Enums/Sampler.cs @@ -2,30 +2,13 @@ public enum Sampler { - [NativeName("EULER_A")] Euler_A, - - [NativeName("EULER")] Euler, - - [NativeName("HEUN")] Heun, - - [NativeName("DPM2")] DPM2, - - [NativeName("DPMPP2S_A")] DPMPP2SA, - - [NativeName("DPMPP2M")] DPMPP2M, - - [NativeName("DPMPP2Mv2")] DPMPP2Mv2, - - [NativeName("LCM")] LCM, - - [NativeName("N_SAMPLE_METHODS")] N_Sample_Methods } \ No newline at end of file diff --git a/StableDiffusion.NET/Enums/Schedule.cs b/StableDiffusion.NET/Enums/Schedule.cs index a6ea523..51904de 100644 --- a/StableDiffusion.NET/Enums/Schedule.cs +++ b/StableDiffusion.NET/Enums/Schedule.cs @@ -2,15 +2,8 @@ public enum Schedule { - [NativeName("DEFAULT")] Default, - - [NativeName("DISCRETE")] Discrete, - - [NativeName("KARRAS")] Karras, - - [NativeName("N_SCHEDULES")] N_Schedules } \ No newline at end of file diff --git a/StableDiffusion.NET/Extensions/EnumExtension.cs b/StableDiffusion.NET/Extensions/EnumExtension.cs deleted file mode 100644 index 319cf76..0000000 --- a/StableDiffusion.NET/Extensions/EnumExtension.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Reflection; - -namespace StableDiffusion.NET; - -internal static class EnumExtension -{ - #region Methods - - public static string? GetNativeName(this Enum value) - { - FieldInfo? fieldInfo = value.GetType().GetField(value.ToString()); - NativeName? nativeName = fieldInfo?.GetCustomAttribute(); - return nativeName?.Name; - } - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/ModelParameter.cs b/StableDiffusion.NET/ModelParameter.cs index 7d7eec0..dff426b 100644 --- a/StableDiffusion.NET/ModelParameter.cs +++ b/StableDiffusion.NET/ModelParameter.cs @@ -8,13 +8,14 @@ public class ModelParameter public bool VaeDecodeOnly { get; set; } = false; public bool VaeTiling { get; set; } = false; public string TaesdPath { get; set; } = string.Empty; - public string ESRGANPath { get; set; } = string.Empty; public string LoraModelDir { get; set; } = string.Empty; public RngType RngType { get; set; } = RngType.Standard; public string VaePath { get; set; } = string.Empty; - public Quantization Quantization { get; set; } = Quantization.Default; + + //TODO DarthAffe 01.01.2024: K-Quants doesn't seem to work so far + public Quantization Quantization { get; set; } = Quantization.F16; + public Schedule Schedule { get; set; } = Schedule.Default; - public int ClipSkip { get; set; } = -1; #endregion } diff --git a/StableDiffusion.NET/Native.cs b/StableDiffusion.NET/Native.cs index 1ecf1a5..caac38f 100644 --- a/StableDiffusion.NET/Native.cs +++ b/StableDiffusion.NET/Native.cs @@ -1,8 +1,5 @@ #pragma warning disable CS0169 // Field is never used -#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type #pragma warning disable IDE1006 -#pragma warning disable IDE0051 -#pragma warning disable IDE0044 // ReSharper disable InconsistentNaming // ReSharper disable ArrangeTypeMemberModifiers @@ -10,89 +7,96 @@ using System.Runtime.InteropServices; namespace StableDiffusion.NET; +using rng_type_t = RngType; +using sample_method_t = Sampler; +using schedule_t = Schedule; +using sd_type_t = Quantization; +using sd_log_level_t = LogLevel; + internal unsafe partial class Native { #region Constants - private const string LIB_NAME = "sd-abi"; + private const string LIB_NAME = "stable-diffusion"; #endregion #region DLL-Import - internal struct stable_diffusion_ctx; + internal struct sd_ctx_t; + internal struct upscaler_ctx_t; - internal struct stable_diffusion_full_params + [StructLayout(LayoutKind.Sequential)] + internal struct sd_image_t { - string negative_prompt; - float cfg_scale; - int width; - int height; - int sample_method; - int sample_steps; - long seed; - int batch_count; - float strength; + internal uint width; + internal uint height; + internal uint channel; + internal byte* data; } - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_default_params_ref")] - internal static partial stable_diffusion_full_params* stable_diffusion_full_default_params_ref(); + [LibraryImport(LIB_NAME, EntryPoint = "get_num_physical_cores")] + internal static partial int get_num_physical_cores(); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_negative_prompt")] - internal static partial void stable_diffusion_full_params_set_negative_prompt(stable_diffusion_full_params* @params, [MarshalAs(UnmanagedType.LPStr)] string negative_prompt); + [LibraryImport(LIB_NAME, EntryPoint = "sd_get_system_info")] + internal static partial void* sd_get_system_info(); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_cfg_scale")] - internal static partial void stable_diffusion_full_params_set_cfg_scale(stable_diffusion_full_params* @params, float cfg_scale); + [LibraryImport(LIB_NAME, EntryPoint = "new_sd_ctx")] + internal static partial sd_ctx_t* new_sd_ctx([MarshalAs(UnmanagedType.LPStr)] string model_path, + [MarshalAs(UnmanagedType.LPStr)] string vae_path, + [MarshalAs(UnmanagedType.LPStr)] string taesd_path, + [MarshalAs(UnmanagedType.LPStr)] string lora_model_dir, + [MarshalAs(UnmanagedType.I1)] bool vae_decode_only, + [MarshalAs(UnmanagedType.I1)] bool vae_tiling, + [MarshalAs(UnmanagedType.I1)] bool free_params_immediately, + int n_threads, + sd_type_t wtype, + rng_type_t rng_type, + schedule_t s); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_width")] - internal static partial void stable_diffusion_full_params_set_width(stable_diffusion_full_params* @params, int width); + [LibraryImport(LIB_NAME, EntryPoint = "free_sd_ctx")] + internal static partial void free_sd_ctx(sd_ctx_t* sd_ctx); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_height")] - internal static partial void stable_diffusion_full_params_set_height(stable_diffusion_full_params* @params, int height); + [LibraryImport(LIB_NAME, EntryPoint = "txt2img")] + internal static partial sd_image_t* txt2img(sd_ctx_t* sd_ctx, + [MarshalAs(UnmanagedType.LPStr)] string prompt, + [MarshalAs(UnmanagedType.LPStr)] string negative_prompt, + int clip_skip, + float cfg_scale, + int width, + int height, + sample_method_t sample_method, + int sample_steps, + long seed, + int batch_count); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_sample_method")] - internal static partial void stable_diffusion_full_params_set_sample_method(stable_diffusion_full_params* @params, [MarshalAs(UnmanagedType.LPStr)] string sample_method); + [LibraryImport(LIB_NAME, EntryPoint = "img2img")] + internal static partial sd_image_t* img2img(sd_ctx_t* sd_ctx, + sd_image_t init_image, + [MarshalAs(UnmanagedType.LPStr)] string prompt, + [MarshalAs(UnmanagedType.LPStr)] string negative_prompt, + int clip_skip, + float cfg_scale, + int width, + int height, + sample_method_t sample_method, + int sample_steps, + float strength, + long seed, + int batch_count); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_sample_steps")] - internal static partial void stable_diffusion_full_params_set_sample_steps(stable_diffusion_full_params* @params, int sample_steps); + [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, + sd_type_t wtype); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_seed")] - internal static partial void stable_diffusion_full_params_set_seed(stable_diffusion_full_params* @params, long seed); + [LibraryImport(LIB_NAME, EntryPoint = "free_upscaler_ctx")] + internal static partial void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx); - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_batch_count")] - internal static partial void stable_diffusion_full_params_set_batch_count(stable_diffusion_full_params* @params, int batch_count); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_strength")] - internal static partial void stable_diffusion_full_params_set_strength(stable_diffusion_full_params* @params, float strength); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_init")] - internal static partial stable_diffusion_ctx* stable_diffusion_init(int n_threads, [MarshalAs(UnmanagedType.I1)] bool vae_decode_only, [MarshalAs(UnmanagedType.LPStr)] string taesd_path, [MarshalAs(UnmanagedType.LPStr)] string esrgan_path, [MarshalAs(UnmanagedType.I1)] bool free_params_immediately, [MarshalAs(UnmanagedType.I1)] bool vae_tiling, [MarshalAs(UnmanagedType.LPStr)] string lora_model_dir, [MarshalAs(UnmanagedType.LPStr)] string rng_type); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_load_from_file")] - [return: MarshalAs(UnmanagedType.I1)] - internal static partial bool stable_diffusion_load_from_file(stable_diffusion_ctx* ctx, [MarshalAs(UnmanagedType.LPStr)] string file_path, [MarshalAs(UnmanagedType.LPStr)] string vae_path, [MarshalAs(UnmanagedType.LPStr)] string wtype, [MarshalAs(UnmanagedType.LPStr)] string schedule, int clip_skip); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_predict_image")] - internal static partial byte* stable_diffusion_predict_image(stable_diffusion_ctx* ctx, stable_diffusion_full_params* @params, [MarshalAs(UnmanagedType.LPStr)] string prompt); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_image_predict_image")] - internal static partial byte* stable_diffusion_image_predict_image(stable_diffusion_ctx* ctx, stable_diffusion_full_params* @params, byte* init_image, [MarshalAs(UnmanagedType.LPStr)] string prompt); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_set_log_level")] - internal static partial void stable_diffusion_set_log_level([MarshalAs(UnmanagedType.LPStr)] string level); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_get_system_info")] - [return: MarshalAs(UnmanagedType.LPStr)] - internal static partial string stable_diffusion_get_system_info(); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_free")] - internal static partial void stable_diffusion_free(stable_diffusion_ctx* ctx); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_free_full_params")] - internal static partial void stable_diffusion_free_full_params(stable_diffusion_full_params* @params); - - [LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_free_buffer")] - internal static partial void stable_diffusion_free_buffer(byte* buffer); + [LibraryImport(LIB_NAME, EntryPoint = "upscale")] + internal static partial sd_image_t upscale(upscaler_ctx_t* upscaler_ctx, + sd_image_t input_image, + int upscale_factor); #endregion } \ No newline at end of file diff --git a/StableDiffusion.NET/StableDiffusion.cs b/StableDiffusion.NET/StableDiffusion.cs deleted file mode 100644 index d206bcd..0000000 --- a/StableDiffusion.NET/StableDiffusion.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.IO; - -namespace StableDiffusion.NET; - -public sealed unsafe class StableDiffusionModel : IDisposable -{ - #region Properties & Fields - - private bool _disposed; - - private readonly string _modelPath; - private readonly ModelParameter _parameter; - - private Native.stable_diffusion_ctx* _ctx; - - #endregion - - #region Constructors - - public StableDiffusionModel(string modelPath, ModelParameter parameter) - { - this._modelPath = modelPath; - this._parameter = parameter; - - Initialize(); - } - - ~StableDiffusionModel() => Dispose(); - - #endregion - - #region Methods - - private void Initialize() - { - _ctx = Native.stable_diffusion_init(_parameter.ThreadCount, _parameter.VaeDecodeOnly, _parameter.TaesdPath, _parameter.ESRGANPath, false, _parameter.VaeTiling, _parameter.LoraModelDir, _parameter.RngType.GetNativeName() ?? "STD_DEFAULT_RNG"); - if (_ctx == null) throw new NullReferenceException("Failed to initialize Stable Diffusion"); - - bool success = Native.stable_diffusion_load_from_file(_ctx, _modelPath, _parameter.VaePath, _parameter.Quantization.GetNativeName() ?? "DEFAULT", _parameter.Schedule.GetNativeName() ?? "DEFAULT", _parameter.ClipSkip); - if (!success) throw new IOException("Failed to load model"); - } - - public StableDiffusionImage TextToImage(string prompt, StableDiffusionParameter parameter) - { - ObjectDisposedException.ThrowIf(_disposed, this); - - byte* result = Native.stable_diffusion_predict_image(_ctx, parameter.ParamPtr, prompt); - return new StableDiffusionImage(result, parameter.Width, parameter.Height); - } - - public StableDiffusionImage ImageToImage(string prompt, Span image, StableDiffusionParameter parameter) - { - ObjectDisposedException.ThrowIf(_disposed, this); - - fixed (byte* imagePtr = image) - { - byte* result = Native.stable_diffusion_image_predict_image(_ctx, parameter.ParamPtr, imagePtr, prompt); - return new StableDiffusionImage(result, parameter.Width, parameter.Height); - } - } - - public void Dispose() - { - if (_disposed) return; - - Native.stable_diffusion_free(_ctx); - - GC.SuppressFinalize(this); - _disposed = true; - } - - public static string GetSystemInfo() => Native.stable_diffusion_get_system_info(); - - public static void SetLogLevel(LogLevel level) => Native.stable_diffusion_set_log_level(level.GetNativeName() ?? "ERROR"); - - #endregion -} diff --git a/StableDiffusion.NET/StableDiffusionImage.cs b/StableDiffusion.NET/StableDiffusionImage.cs index 5219e31..70dc6b1 100644 --- a/StableDiffusion.NET/StableDiffusionImage.cs +++ b/StableDiffusion.NET/StableDiffusionImage.cs @@ -1,23 +1,20 @@ using System; +using System.Runtime.InteropServices; namespace StableDiffusion.NET; public sealed unsafe class StableDiffusionImage : IDisposable { - #region Constants - - public const int BPP = 3; - - #endregion - #region Properties & Fields private bool _disposed; - private readonly byte* _imagePtr; + internal readonly Native.sd_image_t* Image; public int Width { get; } public int Height { get; } + public int Bpp { get; } + public int Stride { get; } public ReadOnlySpan Data { @@ -25,7 +22,7 @@ public sealed unsafe class StableDiffusionImage : IDisposable { ObjectDisposedException.ThrowIf(_disposed, this); - return new ReadOnlySpan(_imagePtr, Width * Height * BPP); + return new ReadOnlySpan(Image->data, Width * Height * Bpp); } } @@ -33,11 +30,14 @@ public sealed unsafe class StableDiffusionImage : IDisposable #region Constructors - internal StableDiffusionImage(byte* ptr, int width, int height) + internal unsafe StableDiffusionImage(Native.sd_image_t* image) { - this._imagePtr = ptr; - this.Width = width; - this.Height = height; + this.Image = image; + + Width = (int)image->width; + Height = (int)image->height; + Bpp = (int)image->channel; + Stride = Width * Bpp; } ~StableDiffusionImage() => Dispose(); @@ -50,8 +50,9 @@ public sealed unsafe class StableDiffusionImage : IDisposable { if (_disposed) return; - Native.stable_diffusion_free_buffer(_imagePtr); - + Marshal.FreeHGlobal((nint)Image->data); + Marshal.FreeHGlobal((nint)Image); + GC.SuppressFinalize(this); _disposed = true; } diff --git a/StableDiffusion.NET/StableDiffusionModel.cs b/StableDiffusion.NET/StableDiffusionModel.cs new file mode 100644 index 0000000..bd77a0f --- /dev/null +++ b/StableDiffusion.NET/StableDiffusionModel.cs @@ -0,0 +1,181 @@ +using System; +using System.Runtime.InteropServices; + +namespace StableDiffusion.NET; + +public sealed unsafe class StableDiffusionModel : IDisposable +{ + #region Properties & Fields + + private bool _disposed; + + private readonly string _modelPath; + private readonly ModelParameter _parameter; + private readonly UpscalerModelParameter? _upscalerParameter; + + private Native.sd_ctx_t* _ctx; + private Native.upscaler_ctx_t* _upscalerCtx; + + #endregion + + #region Constructors + + public StableDiffusionModel(string modelPath, ModelParameter parameter, UpscalerModelParameter? upscalerParameter = null) + { + this._modelPath = modelPath; + this._parameter = parameter; + this._upscalerParameter = upscalerParameter; + + Initialize(); + } + + ~StableDiffusionModel() => Dispose(); + + #endregion + + #region Methods + + private void Initialize() + { + _ctx = Native.new_sd_ctx(_modelPath, + _parameter.VaePath, + _parameter.TaesdPath, + _parameter.LoraModelDir, + _parameter.VaeDecodeOnly, + _parameter.VaeTiling, + false, + _parameter.ThreadCount, + _parameter.Quantization, + _parameter.RngType, + _parameter.Schedule); + if (_ctx == null) throw new NullReferenceException("Failed to initialize Stable Diffusion"); + + if (_upscalerParameter != null) + { + _upscalerCtx = Native.new_upscaler_ctx(_upscalerParameter.ESRGANPath, + _upscalerParameter.ThreadCount, + _upscalerParameter.Quantization); + if (_upscalerCtx == null) throw new NullReferenceException("Failed to initialize Stable Diffusion"); + } + } + + public StableDiffusionImage TextToImage(string prompt, StableDiffusionParameter parameter) + { + ObjectDisposedException.ThrowIf(_disposed, this); + + Native.sd_image_t* result = Native.txt2img(_ctx, + prompt, + parameter.NegativePrompt, + parameter.ClipSkip, + parameter.CfgScale, + parameter.Width, + parameter.Height, + parameter.SampleMethod, + parameter.SampleSteps, + parameter.Seed, + 1); + + return new StableDiffusionImage(result); + } + + public StableDiffusionImage ImageToImage(string prompt, in ReadOnlySpan image, StableDiffusionParameter parameter) + { + fixed (byte* imagePtr = image) + { + Native.sd_image_t img = new() + { + width = (uint)parameter.Width, + height = (uint)parameter.Height, + channel = 3, + data = imagePtr + }; + + return ImageToImage(prompt, img, parameter); + } + } + + public StableDiffusionImage ImageToImage(string prompt, StableDiffusionImage image, StableDiffusionParameter parameter) + => ImageToImage(prompt, *image.Image, parameter); + + private StableDiffusionImage ImageToImage(string prompt, Native.sd_image_t image, StableDiffusionParameter parameter) + { + Native.sd_image_t* result = Native.img2img(_ctx, + image, + prompt, + parameter.NegativePrompt, + parameter.ClipSkip, + parameter.CfgScale, + parameter.Width, + parameter.Height, + parameter.SampleMethod, + parameter.SampleSteps, + parameter.Strength, + parameter.Seed, + 1); + + + return new StableDiffusionImage(result); + } + + public StableDiffusionImage Upscale(StableDiffusionImage image, int upscaleFactor) + { + ObjectDisposedException.ThrowIf(_disposed, this); + ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(upscaleFactor, 0, nameof(upscaleFactor)); + + if (_upscalerCtx == null) throw new NullReferenceException("The upscaler is not initialized."); + + return Upscale(*image.Image, upscaleFactor); + } + + public StableDiffusionImage Upscale(in ReadOnlySpan image, int width, int height, int upscaleFactor) + { + ObjectDisposedException.ThrowIf(_disposed, this); + ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(upscaleFactor, 0, nameof(upscaleFactor)); + ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(width, 0, nameof(upscaleFactor)); + ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(height, 0, nameof(upscaleFactor)); + + if (_upscalerCtx == null) throw new NullReferenceException("The upscaler is not initialized."); + + fixed (byte* imagePtr = image) + { + Native.sd_image_t srcImage = new() + { + width = (uint)width, + height = (uint)height, + channel = 3, + data = imagePtr + }; + + return Upscale(srcImage, upscaleFactor); + } + } + + private StableDiffusionImage Upscale(Native.sd_image_t image, int upscaleFactor) + { + Native.sd_image_t result = Native.upscale(_upscalerCtx, image, upscaleFactor); + return new StableDiffusionImage(&result); + } + + public void Dispose() + { + if (_disposed) return; + + Native.free_sd_ctx(_ctx); + + if (_upscalerCtx != null) + Native.free_upscaler_ctx(_upscalerCtx); + + GC.SuppressFinalize(this); + _disposed = true; + } + + public static string GetSystemInfo() + { + void* s = Native.sd_get_system_info(); + return Marshal.PtrToStringUTF8((nint)s) ?? ""; + } + + public static int GetNumPhysicalCores() => Native.get_num_physical_cores(); + + #endregion +} diff --git a/StableDiffusion.NET/StableDiffusionParameter.cs b/StableDiffusion.NET/StableDiffusionParameter.cs index 38f6db2..886a908 100644 --- a/StableDiffusion.NET/StableDiffusionParameter.cs +++ b/StableDiffusion.NET/StableDiffusionParameter.cs @@ -1,197 +1,18 @@ -using System; +namespace StableDiffusion.NET; -namespace StableDiffusion.NET; - -public sealed unsafe class StableDiffusionParameter : IDisposable +public sealed class StableDiffusionParameter { #region Properties & Fields - private bool _disposed; - -#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type - internal readonly Native.stable_diffusion_full_params* ParamPtr; -#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type - - private string _negativePrompt; - public string NegativePrompt - { - get => _negativePrompt; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (_negativePrompt != value) - { - _negativePrompt = value; - Native.stable_diffusion_full_params_set_negative_prompt(ParamPtr, _negativePrompt); - } - } - } - - private float _cfgScale; - public float CfgScale - { - get => _cfgScale; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (Math.Abs(_cfgScale - value) > 0.0001) - { - _cfgScale = value; - Native.stable_diffusion_full_params_set_cfg_scale(ParamPtr, _cfgScale); - } - } - } - - private int _width; - public int Width - { - get => _width; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (_width != value) - { - _width = value; - Native.stable_diffusion_full_params_set_width(ParamPtr, _width); - } - } - } - - private int _height; - public int Height - { - get => _height; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (_height != value) - { - _height = value; - Native.stable_diffusion_full_params_set_height(ParamPtr, _height); - } - } - } - - private Sampler _sampleMethod; - public Sampler SampleMethod - { - get => _sampleMethod; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (_sampleMethod != value) - { - _sampleMethod = value; - Native.stable_diffusion_full_params_set_sample_method(ParamPtr, _sampleMethod.GetNativeName() ?? "EULER_A"); - } - } - } - - private int _sampleSteps; - public int SampleSteps - { - get => _sampleSteps; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (_sampleSteps != value) - { - _sampleSteps = value; - Native.stable_diffusion_full_params_set_sample_steps(ParamPtr, _sampleSteps); - } - } - } - - private long _seed; - public long Seed - { - get => _seed; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (_seed != value) - { - _seed = value; - Native.stable_diffusion_full_params_set_seed(ParamPtr, _seed); - } - } - } - - private int _batchCount; - public int BatchCount - { - get => _batchCount; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (_batchCount != value) - { - _batchCount = value; - Native.stable_diffusion_full_params_set_batch_count(ParamPtr, _batchCount); - } - } - } - - private float _strength; - public float Strength - { - get => _strength; - set - { - ObjectDisposedException.ThrowIf(_disposed, this); - - if (Math.Abs(_strength - value) > 0.0001) - { - _strength = value; - Native.stable_diffusion_full_params_set_strength(ParamPtr, _strength); - } - } - } - - #endregion - - #region Constructors - -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public StableDiffusionParameter() - { - ParamPtr = Native.stable_diffusion_full_default_params_ref(); - - NegativePrompt = string.Empty; - CfgScale = 7.5f; - Width = 512; - Height = 512; - SampleMethod = Sampler.Euler_A; - SampleSteps = 25; - Seed = -1; - BatchCount = 1; - Strength = 0.7f; - } -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - - ~StableDiffusionParameter() => Dispose(); - - #endregion - - #region Methods - - public void Dispose() - { - if (_disposed) return; - - Native.stable_diffusion_free_full_params(ParamPtr); - - GC.SuppressFinalize(this); - _disposed = true; - } + public string NegativePrompt { get; set; } = string.Empty; + public float CfgScale { get; set; } = 7.5f; + public int Width { get; set; } = 512; + public int Height { get; set; } = 512; + public Sampler SampleMethod { get; set; } = Sampler.Euler_A; + public int SampleSteps { get; set; } = 25; + public long Seed { get; set; } = -1; + public float Strength { get; set; } = 0.7f; + public int ClipSkip { get; set; } = -1; #endregion } \ No newline at end of file diff --git a/StableDiffusion.NET/UpscalerModelParameter.cs b/StableDiffusion.NET/UpscalerModelParameter.cs new file mode 100644 index 0000000..577751d --- /dev/null +++ b/StableDiffusion.NET/UpscalerModelParameter.cs @@ -0,0 +1,14 @@ +namespace StableDiffusion.NET; + +public class UpscalerModelParameter +{ + #region Properties & Fields + + public int ThreadCount { get; set; } = 8; + public string ESRGANPath { get; set; } = string.Empty; + + //TODO DarthAffe 01.01.2024: K-Quants doesn't seem to work so far + public Quantization Quantization { get; set; } = Quantization.F16; + + #endregion +} diff --git a/build.bat b/build.bat index 8242bcf..212ceb5 100644 --- a/build.bat +++ b/build.bat @@ -1,10 +1,12 @@ -if not exist stable-diffusion.cpp-build ( - git clone https://github.com/DarthAffe/stable-diffusion.cpp-build +if not exist stable-diffusion.cpp ( + git clone --recursive https://github.com/leejet/stable-diffusion.cpp ) -cd stable-diffusion.cpp-build +cd stable-diffusion.cpp git fetch -git checkout b518ce72f1ba448f164e58961b1513ccacc95006 +git checkout 2c5f3fc53a040a0f97ff8f359e8f8d1385bfd154 +git submodule init +git submodule update if not exist build ( mkdir build @@ -13,13 +15,13 @@ if not exist build ( cd build rem remove -DSD_CUBLAS=ON to disable cuda support -cmake .. -DCMAKE_BUILD_TYPE=Release -DSD_CUBLAS=ON +cmake .. -DBUILD_SHARED_LIBS=ON -DSD_BUILD_EXAMPLES=OFF -DSD_CUBLAS=ON cmake --build . --config Release cd ..\.. dotnet publish -c Release -o bin -copy .\stable-diffusion.cpp-build\build\bin\Release\sd-abi.dll .\bin\sd-abi.dll +copy .\stable-diffusion.cpp\build\bin\Release\*.dll .\bin\ pause \ No newline at end of file