mirror of
https://github.com/DarthAffe/StableDiffusion.NET.git
synced 2025-12-12 21:38:45 +00:00
Updated to stable-diffusion.cpp 2c5f3fc and moved to the now included C-API
This commit is contained in:
parent
289abe4d20
commit
1b8c2fce9d
@ -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
|
|
||||||
}
|
|
||||||
@ -2,15 +2,8 @@
|
|||||||
|
|
||||||
public enum LogLevel
|
public enum LogLevel
|
||||||
{
|
{
|
||||||
[NativeName("DEBUG")]
|
|
||||||
Debug,
|
Debug,
|
||||||
|
|
||||||
[NativeName("INFO")]
|
|
||||||
Info,
|
Info,
|
||||||
|
|
||||||
[NativeName("WARN")]
|
|
||||||
Warn,
|
Warn,
|
||||||
|
|
||||||
[NativeName("ERROR")]
|
|
||||||
Error
|
Error
|
||||||
}
|
}
|
||||||
@ -2,27 +2,23 @@
|
|||||||
|
|
||||||
public enum Quantization
|
public enum Quantization
|
||||||
{
|
{
|
||||||
[NativeName("DEFAULT")]
|
F32 = 0,
|
||||||
Default,
|
F16 = 1,
|
||||||
|
Q4_0 = 2,
|
||||||
[NativeName("F32")]
|
Q4_1 = 3,
|
||||||
F32,
|
// Q4_2 = 4, support has been removed
|
||||||
|
// Q4_3 (5) support has been removed
|
||||||
[NativeName("F16")]
|
Q5_0 = 6,
|
||||||
F16,
|
Q5_1 = 7,
|
||||||
|
Q8_0 = 8,
|
||||||
[NativeName("Q4_0")]
|
Q8_1 = 9,
|
||||||
Q4_0,
|
Q2_K = 10,
|
||||||
|
Q3_K = 11,
|
||||||
[NativeName("Q4_1")]
|
Q4_K = 12,
|
||||||
Q4_1,
|
Q5_K = 13,
|
||||||
|
Q6_K = 14,
|
||||||
[NativeName("Q5_0")]
|
Q8_K = 15,
|
||||||
Q5_0,
|
I8,
|
||||||
|
I16,
|
||||||
[NativeName("Q5_1")]
|
I32,
|
||||||
Q5_1,
|
|
||||||
|
|
||||||
[NativeName("Q8_0")]
|
|
||||||
Q8_0
|
|
||||||
}
|
}
|
||||||
@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
public enum RngType
|
public enum RngType
|
||||||
{
|
{
|
||||||
[NativeName("STD_DEFAULT_RNG")]
|
|
||||||
Standard,
|
Standard,
|
||||||
|
|
||||||
[NativeName("CUDA_RNG")]
|
|
||||||
Cuda
|
Cuda
|
||||||
}
|
}
|
||||||
@ -2,30 +2,13 @@
|
|||||||
|
|
||||||
public enum Sampler
|
public enum Sampler
|
||||||
{
|
{
|
||||||
[NativeName("EULER_A")]
|
|
||||||
Euler_A,
|
Euler_A,
|
||||||
|
|
||||||
[NativeName("EULER")]
|
|
||||||
Euler,
|
Euler,
|
||||||
|
|
||||||
[NativeName("HEUN")]
|
|
||||||
Heun,
|
Heun,
|
||||||
|
|
||||||
[NativeName("DPM2")]
|
|
||||||
DPM2,
|
DPM2,
|
||||||
|
|
||||||
[NativeName("DPMPP2S_A")]
|
|
||||||
DPMPP2SA,
|
DPMPP2SA,
|
||||||
|
|
||||||
[NativeName("DPMPP2M")]
|
|
||||||
DPMPP2M,
|
DPMPP2M,
|
||||||
|
|
||||||
[NativeName("DPMPP2Mv2")]
|
|
||||||
DPMPP2Mv2,
|
DPMPP2Mv2,
|
||||||
|
|
||||||
[NativeName("LCM")]
|
|
||||||
LCM,
|
LCM,
|
||||||
|
|
||||||
[NativeName("N_SAMPLE_METHODS")]
|
|
||||||
N_Sample_Methods
|
N_Sample_Methods
|
||||||
}
|
}
|
||||||
@ -2,15 +2,8 @@
|
|||||||
|
|
||||||
public enum Schedule
|
public enum Schedule
|
||||||
{
|
{
|
||||||
[NativeName("DEFAULT")]
|
|
||||||
Default,
|
Default,
|
||||||
|
|
||||||
[NativeName("DISCRETE")]
|
|
||||||
Discrete,
|
Discrete,
|
||||||
|
|
||||||
[NativeName("KARRAS")]
|
|
||||||
Karras,
|
Karras,
|
||||||
|
|
||||||
[NativeName("N_SCHEDULES")]
|
|
||||||
N_Schedules
|
N_Schedules
|
||||||
}
|
}
|
||||||
@ -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<NativeName>();
|
|
||||||
return nativeName?.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@ -8,13 +8,14 @@ public class ModelParameter
|
|||||||
public bool VaeDecodeOnly { get; set; } = false;
|
public bool VaeDecodeOnly { get; set; } = false;
|
||||||
public bool VaeTiling { get; set; } = false;
|
public bool VaeTiling { get; set; } = false;
|
||||||
public string TaesdPath { get; set; } = string.Empty;
|
public string TaesdPath { get; set; } = string.Empty;
|
||||||
public string ESRGANPath { get; set; } = string.Empty;
|
|
||||||
public string LoraModelDir { get; set; } = string.Empty;
|
public string LoraModelDir { get; set; } = string.Empty;
|
||||||
public RngType RngType { get; set; } = RngType.Standard;
|
public RngType RngType { get; set; } = RngType.Standard;
|
||||||
public string VaePath { get; set; } = string.Empty;
|
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 Schedule Schedule { get; set; } = Schedule.Default;
|
||||||
public int ClipSkip { get; set; } = -1;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
#pragma warning disable CS0169 // Field is never used
|
#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 IDE1006
|
||||||
#pragma warning disable IDE0051
|
|
||||||
#pragma warning disable IDE0044
|
|
||||||
// ReSharper disable InconsistentNaming
|
// ReSharper disable InconsistentNaming
|
||||||
// ReSharper disable ArrangeTypeMemberModifiers
|
// ReSharper disable ArrangeTypeMemberModifiers
|
||||||
|
|
||||||
@ -10,89 +7,96 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace StableDiffusion.NET;
|
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
|
internal unsafe partial class Native
|
||||||
{
|
{
|
||||||
#region Constants
|
#region Constants
|
||||||
|
|
||||||
private const string LIB_NAME = "sd-abi";
|
private const string LIB_NAME = "stable-diffusion";
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region DLL-Import
|
#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;
|
internal uint width;
|
||||||
float cfg_scale;
|
internal uint height;
|
||||||
int width;
|
internal uint channel;
|
||||||
int height;
|
internal byte* data;
|
||||||
int sample_method;
|
|
||||||
int sample_steps;
|
|
||||||
long seed;
|
|
||||||
int batch_count;
|
|
||||||
float strength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_default_params_ref")]
|
[LibraryImport(LIB_NAME, EntryPoint = "get_num_physical_cores")]
|
||||||
internal static partial stable_diffusion_full_params* stable_diffusion_full_default_params_ref();
|
internal static partial int get_num_physical_cores();
|
||||||
|
|
||||||
[LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_negative_prompt")]
|
[LibraryImport(LIB_NAME, EntryPoint = "sd_get_system_info")]
|
||||||
internal static partial void stable_diffusion_full_params_set_negative_prompt(stable_diffusion_full_params* @params, [MarshalAs(UnmanagedType.LPStr)] string negative_prompt);
|
internal static partial void* sd_get_system_info();
|
||||||
|
|
||||||
[LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_cfg_scale")]
|
[LibraryImport(LIB_NAME, EntryPoint = "new_sd_ctx")]
|
||||||
internal static partial void stable_diffusion_full_params_set_cfg_scale(stable_diffusion_full_params* @params, float cfg_scale);
|
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")]
|
[LibraryImport(LIB_NAME, EntryPoint = "free_sd_ctx")]
|
||||||
internal static partial void stable_diffusion_full_params_set_width(stable_diffusion_full_params* @params, int width);
|
internal static partial void free_sd_ctx(sd_ctx_t* sd_ctx);
|
||||||
|
|
||||||
[LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_height")]
|
[LibraryImport(LIB_NAME, EntryPoint = "txt2img")]
|
||||||
internal static partial void stable_diffusion_full_params_set_height(stable_diffusion_full_params* @params, int height);
|
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")]
|
[LibraryImport(LIB_NAME, EntryPoint = "img2img")]
|
||||||
internal static partial void stable_diffusion_full_params_set_sample_method(stable_diffusion_full_params* @params, [MarshalAs(UnmanagedType.LPStr)] string sample_method);
|
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")]
|
[LibraryImport(LIB_NAME, EntryPoint = "new_upscaler_ctx")]
|
||||||
internal static partial void stable_diffusion_full_params_set_sample_steps(stable_diffusion_full_params* @params, int sample_steps);
|
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")]
|
[LibraryImport(LIB_NAME, EntryPoint = "free_upscaler_ctx")]
|
||||||
internal static partial void stable_diffusion_full_params_set_seed(stable_diffusion_full_params* @params, long seed);
|
internal static partial void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx);
|
||||||
|
|
||||||
[LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_batch_count")]
|
[LibraryImport(LIB_NAME, EntryPoint = "upscale")]
|
||||||
internal static partial void stable_diffusion_full_params_set_batch_count(stable_diffusion_full_params* @params, int batch_count);
|
internal static partial sd_image_t upscale(upscaler_ctx_t* upscaler_ctx,
|
||||||
|
sd_image_t input_image,
|
||||||
[LibraryImport(LIB_NAME, EntryPoint = "stable_diffusion_full_params_set_strength")]
|
int upscale_factor);
|
||||||
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);
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
@ -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<byte> 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
|
|
||||||
}
|
|
||||||
@ -1,23 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace StableDiffusion.NET;
|
namespace StableDiffusion.NET;
|
||||||
|
|
||||||
public sealed unsafe class StableDiffusionImage : IDisposable
|
public sealed unsafe class StableDiffusionImage : IDisposable
|
||||||
{
|
{
|
||||||
#region Constants
|
|
||||||
|
|
||||||
public const int BPP = 3;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
private readonly byte* _imagePtr;
|
internal readonly Native.sd_image_t* Image;
|
||||||
|
|
||||||
public int Width { get; }
|
public int Width { get; }
|
||||||
public int Height { get; }
|
public int Height { get; }
|
||||||
|
public int Bpp { get; }
|
||||||
|
public int Stride { get; }
|
||||||
|
|
||||||
public ReadOnlySpan<byte> Data
|
public ReadOnlySpan<byte> Data
|
||||||
{
|
{
|
||||||
@ -25,7 +22,7 @@ public sealed unsafe class StableDiffusionImage : IDisposable
|
|||||||
{
|
{
|
||||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||||
|
|
||||||
return new ReadOnlySpan<byte>(_imagePtr, Width * Height * BPP);
|
return new ReadOnlySpan<byte>(Image->data, Width * Height * Bpp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,11 +30,14 @@ public sealed unsafe class StableDiffusionImage : IDisposable
|
|||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
internal StableDiffusionImage(byte* ptr, int width, int height)
|
internal unsafe StableDiffusionImage(Native.sd_image_t* image)
|
||||||
{
|
{
|
||||||
this._imagePtr = ptr;
|
this.Image = image;
|
||||||
this.Width = width;
|
|
||||||
this.Height = height;
|
Width = (int)image->width;
|
||||||
|
Height = (int)image->height;
|
||||||
|
Bpp = (int)image->channel;
|
||||||
|
Stride = Width * Bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
~StableDiffusionImage() => Dispose();
|
~StableDiffusionImage() => Dispose();
|
||||||
@ -50,8 +50,9 @@ public sealed unsafe class StableDiffusionImage : IDisposable
|
|||||||
{
|
{
|
||||||
if (_disposed) return;
|
if (_disposed) return;
|
||||||
|
|
||||||
Native.stable_diffusion_free_buffer(_imagePtr);
|
Marshal.FreeHGlobal((nint)Image->data);
|
||||||
|
Marshal.FreeHGlobal((nint)Image);
|
||||||
|
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|||||||
181
StableDiffusion.NET/StableDiffusionModel.cs
Normal file
181
StableDiffusion.NET/StableDiffusionModel.cs
Normal file
@ -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<byte> 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<byte> 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
|
||||||
|
}
|
||||||
@ -1,197 +1,18 @@
|
|||||||
using System;
|
namespace StableDiffusion.NET;
|
||||||
|
|
||||||
namespace StableDiffusion.NET;
|
public sealed class StableDiffusionParameter
|
||||||
|
|
||||||
public sealed unsafe class StableDiffusionParameter : IDisposable
|
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
private bool _disposed;
|
public string NegativePrompt { get; set; } = string.Empty;
|
||||||
|
public float CfgScale { get; set; } = 7.5f;
|
||||||
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
public int Width { get; set; } = 512;
|
||||||
internal readonly Native.stable_diffusion_full_params* ParamPtr;
|
public int Height { get; set; } = 512;
|
||||||
#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
public Sampler SampleMethod { get; set; } = Sampler.Euler_A;
|
||||||
|
public int SampleSteps { get; set; } = 25;
|
||||||
private string _negativePrompt;
|
public long Seed { get; set; } = -1;
|
||||||
public string NegativePrompt
|
public float Strength { get; set; } = 0.7f;
|
||||||
{
|
public int ClipSkip { get; set; } = -1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
14
StableDiffusion.NET/UpscalerModelParameter.cs
Normal file
14
StableDiffusion.NET/UpscalerModelParameter.cs
Normal file
@ -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
|
||||||
|
}
|
||||||
14
build.bat
14
build.bat
@ -1,10 +1,12 @@
|
|||||||
if not exist stable-diffusion.cpp-build (
|
if not exist stable-diffusion.cpp (
|
||||||
git clone https://github.com/DarthAffe/stable-diffusion.cpp-build
|
git clone --recursive https://github.com/leejet/stable-diffusion.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
cd stable-diffusion.cpp-build
|
cd stable-diffusion.cpp
|
||||||
git fetch
|
git fetch
|
||||||
git checkout b518ce72f1ba448f164e58961b1513ccacc95006
|
git checkout 2c5f3fc53a040a0f97ff8f359e8f8d1385bfd154
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
|
||||||
if not exist build (
|
if not exist build (
|
||||||
mkdir build
|
mkdir build
|
||||||
@ -13,13 +15,13 @@ if not exist build (
|
|||||||
cd build
|
cd build
|
||||||
|
|
||||||
rem remove -DSD_CUBLAS=ON to disable cuda support
|
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
|
cmake --build . --config Release
|
||||||
|
|
||||||
cd ..\..
|
cd ..\..
|
||||||
|
|
||||||
dotnet publish -c Release -o bin
|
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
|
pause
|
||||||
Loading…
x
Reference in New Issue
Block a user