mirror of
https://github.com/DarthAffe/StableDiffusion.NET.git
synced 2025-12-12 13:28:35 +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
|
||||
{
|
||||
[NativeName("DEBUG")]
|
||||
Debug,
|
||||
|
||||
[NativeName("INFO")]
|
||||
Info,
|
||||
|
||||
[NativeName("WARN")]
|
||||
Warn,
|
||||
|
||||
[NativeName("ERROR")]
|
||||
Error
|
||||
}
|
||||
@ -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,
|
||||
}
|
||||
@ -2,9 +2,6 @@
|
||||
|
||||
public enum RngType
|
||||
{
|
||||
[NativeName("STD_DEFAULT_RNG")]
|
||||
Standard,
|
||||
|
||||
[NativeName("CUDA_RNG")]
|
||||
Cuda
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -2,15 +2,8 @@
|
||||
|
||||
public enum Schedule
|
||||
{
|
||||
[NativeName("DEFAULT")]
|
||||
Default,
|
||||
|
||||
[NativeName("DISCRETE")]
|
||||
Discrete,
|
||||
|
||||
[NativeName("KARRAS")]
|
||||
Karras,
|
||||
|
||||
[NativeName("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 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
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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.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<byte> Data
|
||||
{
|
||||
@ -25,7 +22,7 @@ public sealed unsafe class StableDiffusionImage : IDisposable
|
||||
{
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
||||
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 (
|
||||
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
|
||||
Loading…
x
Reference in New Issue
Block a user