From d77cebed10b47ad5ef37bf544f51df15b5d5a95c Mon Sep 17 00:00:00 2001 From: DarthAffe Date: Tue, 30 Dec 2025 11:26:48 +0100 Subject: [PATCH] Updated sd.cpp to 43a70e8 --- Header/stable-diffusion.h | 28 ++- .../Parameter/DiffusionModelParameter.cs | 4 + .../Models/Parameter/Embedding.cs | 18 ++ .../DiffusionModelBuilderExtension.cs | 10 + .../Parameter/ImageGenerationParameter.cs | 5 +- StableDiffusion.NET/Models/Parameter/Lora.cs | 18 ++ .../Models/Parameter/SampleParameter.cs | 2 + .../Models/Parameter/UpscaleModelParameter.cs | 2 + .../Parameter/VideoGenerationParameter.cs | 3 + StableDiffusion.NET/Models/UpscaleModel.cs | 3 +- .../DiffusionModelParameterMarshaller.cs | 220 +++++++++++++----- .../ImageGenerationParameterMarshaller.cs | 58 +++-- .../Marshaller/SampleParameterMarshaller.cs | 29 ++- .../VideoGenerationParameterMarshaller.cs | 56 +++-- StableDiffusion.NET/Native/Native.cs | 38 ++- StableDiffusion.NET/StableDiffusionCpp.cs | 7 + 16 files changed, 378 insertions(+), 123 deletions(-) create mode 100644 StableDiffusion.NET/Models/Parameter/Embedding.cs create mode 100644 StableDiffusion.NET/Models/Parameter/Lora.cs diff --git a/Header/stable-diffusion.h b/Header/stable-diffusion.h index e34cdec..d54376b 100644 --- a/Header/stable-diffusion.h +++ b/Header/stable-diffusion.h @@ -150,6 +150,11 @@ typedef struct { float rel_size_y; } sd_tiling_params_t; +typedef struct { + const char* name; + const char* path; +} sd_embedding_t; + typedef struct { const char* model_path; const char* clip_l_path; @@ -164,7 +169,8 @@ typedef struct { const char* taesd_path; const char* control_net_path; const char* lora_model_dir; - const char* embedding_dir; + const sd_embedding_t* embeddings; + uint32_t embedding_count; const char* photo_maker_path; const char* tensor_type_rules; bool vae_decode_only; @@ -219,6 +225,8 @@ typedef struct { int sample_steps; float eta; int shifted_timestep; + float* custom_sigmas; + int custom_sigmas_count; } sd_sample_params_t; typedef struct { @@ -236,6 +244,14 @@ typedef struct { } sd_easycache_params_t; typedef struct { + bool is_high_noise; + float multiplier; + const char* path; +} sd_lora_t; + +typedef struct { + const sd_lora_t* loras; + uint32_t lora_count; const char* prompt; const char* negative_prompt; int clip_skip; @@ -259,6 +275,8 @@ typedef struct { } sd_img_gen_params_t; typedef struct { + const sd_lora_t* loras; + uint32_t lora_count; const char* prompt; const char* negative_prompt; int clip_skip; @@ -331,7 +349,8 @@ typedef struct upscaler_ctx_t upscaler_ctx_t; SD_API upscaler_ctx_t* new_upscaler_ctx(const char* esrgan_path, bool offload_params_to_cpu, bool direct, - int n_threads); + int n_threads, + int tile_size); SD_API void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx); SD_API sd_image_t upscale(upscaler_ctx_t* upscaler_ctx, @@ -353,8 +372,11 @@ SD_API bool preprocess_canny(sd_image_t image, float strong, bool inverse); +SD_API const char* sd_commit(void); +SD_API const char* sd_version(void); + #ifdef __cplusplus } #endif -#endif // __STABLE_DIFFUSION_H__ +#endif // __STABLE_DIFFUSION_H__ \ No newline at end of file diff --git a/StableDiffusion.NET/Models/Parameter/DiffusionModelParameter.cs b/StableDiffusion.NET/Models/Parameter/DiffusionModelParameter.cs index dc3a7d4..4a1af18 100644 --- a/StableDiffusion.NET/Models/Parameter/DiffusionModelParameter.cs +++ b/StableDiffusion.NET/Models/Parameter/DiffusionModelParameter.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using JetBrains.Annotations; namespace StableDiffusion.NET; @@ -24,8 +25,11 @@ public sealed class DiffusionModelParameter /// /// path to embeddings /// + [Obsolete("Use Embeddings instead")] public string EmbeddingsDirectory { get; set; } = string.Empty; + public List Embeddings { get; } = []; + /// /// path to control net model /// diff --git a/StableDiffusion.NET/Models/Parameter/Embedding.cs b/StableDiffusion.NET/Models/Parameter/Embedding.cs new file mode 100644 index 0000000..b53d5e5 --- /dev/null +++ b/StableDiffusion.NET/Models/Parameter/Embedding.cs @@ -0,0 +1,18 @@ +using System.Diagnostics.CodeAnalysis; + +namespace StableDiffusion.NET; + +public sealed class Embedding +{ + public required string Name { get; init; } + public required string Path { get; init; } + + public Embedding() { } + + [SetsRequiredMembers] + public Embedding(string name, string path) + { + this.Name = name; + this.Path = path; + } +} \ No newline at end of file diff --git a/StableDiffusion.NET/Models/Parameter/Extensions/DiffusionModelBuilderExtension.cs b/StableDiffusion.NET/Models/Parameter/Extensions/DiffusionModelBuilderExtension.cs index 6e398c1..aa53e75 100644 --- a/StableDiffusion.NET/Models/Parameter/Extensions/DiffusionModelBuilderExtension.cs +++ b/StableDiffusion.NET/Models/Parameter/Extensions/DiffusionModelBuilderExtension.cs @@ -37,6 +37,7 @@ public static class DiffusionModelBuilderExtension return parameter; } + [Obsolete("Use WithEmbedding instead")] public static DiffusionModelParameter WithEmbeddingSupport(this DiffusionModelParameter parameter, string embeddingsDirectory) { ArgumentNullException.ThrowIfNull(embeddingsDirectory); @@ -46,6 +47,15 @@ public static class DiffusionModelBuilderExtension return parameter; } + public static DiffusionModelParameter WithEmbedding(this DiffusionModelParameter parameter, Embedding embedding) + { + ArgumentNullException.ThrowIfNull(embedding); + + parameter.Embeddings.Add(embedding); + + return parameter; + } + public static DiffusionModelParameter WithControlNet(this DiffusionModelParameter parameter, string controlNetPath) { ArgumentNullException.ThrowIfNull(controlNetPath); diff --git a/StableDiffusion.NET/Models/Parameter/ImageGenerationParameter.cs b/StableDiffusion.NET/Models/Parameter/ImageGenerationParameter.cs index 8cfcd41..4e67566 100644 --- a/StableDiffusion.NET/Models/Parameter/ImageGenerationParameter.cs +++ b/StableDiffusion.NET/Models/Parameter/ImageGenerationParameter.cs @@ -1,4 +1,5 @@ -using HPPH; +using System.Collections.Generic; +using HPPH; using JetBrains.Annotations; namespace StableDiffusion.NET; @@ -61,6 +62,8 @@ public sealed class ImageGenerationParameter public EasyCache EasyCache { get; } = new(); + public List Loras { get; } = []; + #endregion public static ImageGenerationParameter Create() => new(); diff --git a/StableDiffusion.NET/Models/Parameter/Lora.cs b/StableDiffusion.NET/Models/Parameter/Lora.cs new file mode 100644 index 0000000..7cd9e5d --- /dev/null +++ b/StableDiffusion.NET/Models/Parameter/Lora.cs @@ -0,0 +1,18 @@ +using System.Diagnostics.CodeAnalysis; + +namespace StableDiffusion.NET; + +public sealed class Lora +{ + public bool IsHighNoise { get; set; } = false; + public float Multiplier { get; set; } = 1f; + public required string Path { get; init; } + + public Lora() { } + + [SetsRequiredMembers] + public Lora(string path) + { + this.Path = path; + } +} \ No newline at end of file diff --git a/StableDiffusion.NET/Models/Parameter/SampleParameter.cs b/StableDiffusion.NET/Models/Parameter/SampleParameter.cs index 39e988c..83da2fb 100644 --- a/StableDiffusion.NET/Models/Parameter/SampleParameter.cs +++ b/StableDiffusion.NET/Models/Parameter/SampleParameter.cs @@ -26,5 +26,7 @@ public sealed class SampleParameter public int ShiftedTimestep { get; set; } = 0; + public float[] CustomSigmas { get; set; } = []; + internal SampleParameter() { } } \ No newline at end of file diff --git a/StableDiffusion.NET/Models/Parameter/UpscaleModelParameter.cs b/StableDiffusion.NET/Models/Parameter/UpscaleModelParameter.cs index b5ae8ff..27419d9 100644 --- a/StableDiffusion.NET/Models/Parameter/UpscaleModelParameter.cs +++ b/StableDiffusion.NET/Models/Parameter/UpscaleModelParameter.cs @@ -24,5 +24,7 @@ public sealed class UpscaleModelParameter /// public bool ConvDirect { get; set; } = false; + public int TileSize { get; set; } = 128; + public static UpscaleModelParameter Create() => new(); } \ No newline at end of file diff --git a/StableDiffusion.NET/Models/Parameter/VideoGenerationParameter.cs b/StableDiffusion.NET/Models/Parameter/VideoGenerationParameter.cs index b6de6af..19549b7 100644 --- a/StableDiffusion.NET/Models/Parameter/VideoGenerationParameter.cs +++ b/StableDiffusion.NET/Models/Parameter/VideoGenerationParameter.cs @@ -1,5 +1,6 @@ using HPPH; using JetBrains.Annotations; +using System.Collections.Generic; namespace StableDiffusion.NET; @@ -40,6 +41,8 @@ public sealed class VideoGenerationParameter public EasyCache EasyCache { get; } = new(); + public List Loras { get; } = []; + #endregion public static VideoGenerationParameter Create() => new(); diff --git a/StableDiffusion.NET/Models/UpscaleModel.cs b/StableDiffusion.NET/Models/UpscaleModel.cs index 9450422..a4bc2cc 100644 --- a/StableDiffusion.NET/Models/UpscaleModel.cs +++ b/StableDiffusion.NET/Models/UpscaleModel.cs @@ -41,7 +41,8 @@ public sealed unsafe class UpscaleModel : IDisposable _ctx = Native.new_upscaler_ctx(ModelParameter.ModelPath, ModelParameter.OffloadParamsToCPU, ModelParameter.ConvDirect, - ModelParameter.ThreadCount); + ModelParameter.ThreadCount, + ModelParameter.TileSize); if (_ctx == null) throw new NullReferenceException("Failed to initialize upscale-model."); } diff --git a/StableDiffusion.NET/Native/Marshaller/DiffusionModelParameterMarshaller.cs b/StableDiffusion.NET/Native/Marshaller/DiffusionModelParameterMarshaller.cs index e8ff8b8..ba10023 100644 --- a/StableDiffusion.NET/Native/Marshaller/DiffusionModelParameterMarshaller.cs +++ b/StableDiffusion.NET/Native/Marshaller/DiffusionModelParameterMarshaller.cs @@ -1,55 +1,18 @@ -using System.Runtime.InteropServices.Marshalling; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace StableDiffusion.NET; -[CustomMarshaller(typeof(DiffusionModelParameter), MarshalMode.ManagedToUnmanagedIn, typeof(DiffusionModelParameterMarshaller))] -[CustomMarshaller(typeof(DiffusionModelParameter), MarshalMode.ManagedToUnmanagedRef, typeof(DiffusionModelParameterMarshaller))] +[CustomMarshaller(typeof(DiffusionModelParameter), MarshalMode.ManagedToUnmanagedIn, typeof(DiffusionModelParameterMarshallerIn))] +[CustomMarshaller(typeof(DiffusionModelParameter), MarshalMode.ManagedToUnmanagedOut, typeof(DiffusionModelParameterMarshaller))] +[CustomMarshaller(typeof(DiffusionModelParameter), MarshalMode.ManagedToUnmanagedRef, typeof(DiffusionModelParameterMarshallerRef))] internal static unsafe class DiffusionModelParameterMarshaller { - public static Native.Types.sd_ctx_params_t ConvertToUnmanaged(DiffusionModelParameter managed) - => new() - { - model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ModelPath), - clip_l_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipLPath), - clip_g_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipGPath), - clip_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipVisionPath), - t5xxl_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.T5xxlPath), - llm_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.LLMPath), - llm_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.LLMVisionPath), - diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.DiffusionModelPath), - high_noise_diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.HighNoiseDiffusionModelPath), - vae_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.VaePath), - taesd_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.TaesdPath), - control_net_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ControlNetPath), - lora_model_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.LoraModelDirectory), - embedding_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.EmbeddingsDirectory), - photo_maker_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.StackedIdEmbeddingsDirectory), - tensor_type_rules = AnsiStringMarshaller.ConvertToUnmanaged(managed.TensorTypeRules), - vae_decode_only = (sbyte)(managed.VaeDecodeOnly ? 1 : 0), - free_params_immediately = (sbyte)(managed.FreeParamsImmediately ? 1 : 0), - n_threads = managed.ThreadCount, - wtype = managed.Quantization, - rng_type = managed.RngType, - sampler_rng_type = managed.SamplerRngType, - prediction = managed.Prediction, - lora_apply_mode = managed.LoraApplyMode, - offload_params_to_cpu = (sbyte)(managed.OffloadParamsToCPU ? 1 : 0), - keep_clip_on_cpu = (sbyte)(managed.KeepClipOnCPU ? 1 : 0), - keep_control_net_on_cpu = (sbyte)(managed.KeepControlNetOnCPU ? 1 : 0), - keep_vae_on_cpu = (sbyte)(managed.KeepVaeOnCPU ? 1 : 0), - diffusion_flash_attn = (sbyte)(managed.FlashAttention ? 1 : 0), - tae_preview_only = (sbyte)(managed.TaePreviewOnly ? 1 : 0), - diffusion_conv_direct = (sbyte)(managed.DiffusionConvDirect ? 1 : 0), - vae_conv_direct = (sbyte)(managed.VaeConvDirect ? 1 : 0), - force_sdxl_vae_conv_scale = (sbyte)(managed.ForceSdxlVaeConvScale ? 1 : 0), - chroma_use_dit_mask = (sbyte)(managed.ChromaUseDitMap ? 1 : 0), - chroma_use_t5_mask = (sbyte)(managed.ChromaEnableT5Map ? 1 : 0), - chroma_t5_mask_pad = managed.ChromaT5MaskPad, - flow_shift = managed.FlowShift - }; - public static DiffusionModelParameter ConvertToManaged(Native.Types.sd_ctx_params_t unmanaged) - => new() + { + DiffusionModelParameter parameter = new() { ModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.model_path) ?? string.Empty, ClipLPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_l_path) ?? string.Empty, @@ -64,7 +27,6 @@ internal static unsafe class DiffusionModelParameterMarshaller TaesdPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.taesd_path) ?? string.Empty, ControlNetPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.control_net_path) ?? string.Empty, LoraModelDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.lora_model_dir) ?? string.Empty, - EmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.embedding_dir) ?? string.Empty, StackedIdEmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.photo_maker_path) ?? string.Empty, TensorTypeRules = AnsiStringMarshaller.ConvertToManaged(unmanaged.tensor_type_rules) ?? string.Empty, VaeDecodeOnly = unmanaged.vae_decode_only == 1, @@ -90,21 +52,155 @@ internal static unsafe class DiffusionModelParameterMarshaller FlowShift = unmanaged.flow_shift }; - public static void Free(Native.Types.sd_ctx_params_t unmanaged) + for (int i = 0; i < unmanaged.embedding_count; i++) + { + Native.Types.sd_embedding_t embedding = unmanaged.embeddings[i]; + parameter.Embeddings.Add(new Embedding + { + Name = AnsiStringMarshaller.ConvertToManaged(embedding.name) ?? string.Empty, + Path = AnsiStringMarshaller.ConvertToManaged(embedding.path) ?? string.Empty + }); + } + + return parameter; + } + + internal ref struct DiffusionModelParameterMarshallerIn { - AnsiStringMarshaller.Free(unmanaged.model_path); - AnsiStringMarshaller.Free(unmanaged.clip_l_path); - AnsiStringMarshaller.Free(unmanaged.clip_g_path); - AnsiStringMarshaller.Free(unmanaged.t5xxl_path); - AnsiStringMarshaller.Free(unmanaged.llm_path); - AnsiStringMarshaller.Free(unmanaged.llm_vision_path); - AnsiStringMarshaller.Free(unmanaged.diffusion_model_path); - AnsiStringMarshaller.Free(unmanaged.vae_path); - AnsiStringMarshaller.Free(unmanaged.taesd_path); - AnsiStringMarshaller.Free(unmanaged.control_net_path); - AnsiStringMarshaller.Free(unmanaged.lora_model_dir); - AnsiStringMarshaller.Free(unmanaged.embedding_dir); - AnsiStringMarshaller.Free(unmanaged.photo_maker_path); - AnsiStringMarshaller.Free(unmanaged.tensor_type_rules); + private Native.Types.sd_ctx_params_t _ctxParams; + + private Native.Types.sd_embedding_t* _embeddings; + + public DiffusionModelParameterMarshallerIn() { } + + public void FromManaged(DiffusionModelParameter managed) + { + //_embeddings = (Native.Types.sd_embedding_t*)NativeMemory.Alloc((nuint)managed.Embeddings.Count, (nuint)Marshal.SizeOf()); + + //for (int i = 0; i < managed.Embeddings.Count; i++) + //{ + // Embedding embedding = managed.Embeddings[i]; + + // _embeddings[i] = new Native.Types.sd_embedding_t + // { + // name = AnsiStringMarshaller.ConvertToUnmanaged(embedding.Name), + // path = AnsiStringMarshaller.ConvertToUnmanaged(embedding.Path), + // }; + //} + + //HACK DarthAffe 25.12.2025 Workaround to support EmbeddingsDir till the next major release + List embeddings = []; + { + embeddings.AddRange(managed.Embeddings); + + try + { + if (!string.IsNullOrWhiteSpace(managed.EmbeddingsDirectory) && Directory.Exists(managed.EmbeddingsDirectory)) + { + foreach (string file in Directory.GetFiles(managed.EmbeddingsDirectory)) + embeddings.Add(new Embedding(Path.GetFileNameWithoutExtension(file), file)); + } + } + catch { /**/ } + + _embeddings = (Native.Types.sd_embedding_t*)NativeMemory.Alloc((nuint)embeddings.Count, (nuint)Marshal.SizeOf()); + + for (int i = 0; i < embeddings.Count; i++) + { + Embedding embedding = embeddings[i]; + + _embeddings[i] = new Native.Types.sd_embedding_t + { + name = AnsiStringMarshaller.ConvertToUnmanaged(embedding.Name), + path = AnsiStringMarshaller.ConvertToUnmanaged(embedding.Path), + }; + } + } + + _ctxParams = new Native.Types.sd_ctx_params_t + { + model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ModelPath), + clip_l_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipLPath), + clip_g_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipGPath), + clip_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipVisionPath), + t5xxl_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.T5xxlPath), + llm_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.LLMPath), + llm_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.LLMVisionPath), + diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.DiffusionModelPath), + high_noise_diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.HighNoiseDiffusionModelPath), + vae_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.VaePath), + taesd_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.TaesdPath), + control_net_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ControlNetPath), + lora_model_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.LoraModelDirectory), + embeddings = _embeddings, + embedding_count = (uint)embeddings.Count, + photo_maker_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.StackedIdEmbeddingsDirectory), + tensor_type_rules = AnsiStringMarshaller.ConvertToUnmanaged(managed.TensorTypeRules), + vae_decode_only = (sbyte)(managed.VaeDecodeOnly ? 1 : 0), + free_params_immediately = (sbyte)(managed.FreeParamsImmediately ? 1 : 0), + n_threads = managed.ThreadCount, + wtype = managed.Quantization, + rng_type = managed.RngType, + sampler_rng_type = managed.SamplerRngType, + prediction = managed.Prediction, + lora_apply_mode = managed.LoraApplyMode, + offload_params_to_cpu = (sbyte)(managed.OffloadParamsToCPU ? 1 : 0), + keep_clip_on_cpu = (sbyte)(managed.KeepClipOnCPU ? 1 : 0), + keep_control_net_on_cpu = (sbyte)(managed.KeepControlNetOnCPU ? 1 : 0), + keep_vae_on_cpu = (sbyte)(managed.KeepVaeOnCPU ? 1 : 0), + diffusion_flash_attn = (sbyte)(managed.FlashAttention ? 1 : 0), + tae_preview_only = (sbyte)(managed.TaePreviewOnly ? 1 : 0), + diffusion_conv_direct = (sbyte)(managed.DiffusionConvDirect ? 1 : 0), + vae_conv_direct = (sbyte)(managed.VaeConvDirect ? 1 : 0), + force_sdxl_vae_conv_scale = (sbyte)(managed.ForceSdxlVaeConvScale ? 1 : 0), + chroma_use_dit_mask = (sbyte)(managed.ChromaUseDitMap ? 1 : 0), + chroma_use_t5_mask = (sbyte)(managed.ChromaEnableT5Map ? 1 : 0), + chroma_t5_mask_pad = managed.ChromaT5MaskPad, + flow_shift = managed.FlowShift + }; + } + + public Native.Types.sd_ctx_params_t ToUnmanaged() => _ctxParams; + + public void Free() + { + + AnsiStringMarshaller.Free(_ctxParams.model_path); + AnsiStringMarshaller.Free(_ctxParams.clip_l_path); + AnsiStringMarshaller.Free(_ctxParams.clip_g_path); + AnsiStringMarshaller.Free(_ctxParams.t5xxl_path); + AnsiStringMarshaller.Free(_ctxParams.llm_path); + AnsiStringMarshaller.Free(_ctxParams.llm_vision_path); + AnsiStringMarshaller.Free(_ctxParams.diffusion_model_path); + AnsiStringMarshaller.Free(_ctxParams.vae_path); + AnsiStringMarshaller.Free(_ctxParams.taesd_path); + AnsiStringMarshaller.Free(_ctxParams.control_net_path); + AnsiStringMarshaller.Free(_ctxParams.lora_model_dir); + AnsiStringMarshaller.Free(_ctxParams.photo_maker_path); + AnsiStringMarshaller.Free(_ctxParams.tensor_type_rules); + + for (int i = 0; i < _ctxParams.embedding_count; i++) + { + AnsiStringMarshaller.Free(_ctxParams.embeddings[i].name); + AnsiStringMarshaller.Free(_ctxParams.embeddings[i].path); + } + + if (_embeddings != null) + NativeMemory.Free(_embeddings); + } + } + + internal ref struct DiffusionModelParameterMarshallerRef() + { + private DiffusionModelParameterMarshallerIn _inMarshaller = new(); + private DiffusionModelParameter? _parameter; + + public void FromManaged(DiffusionModelParameter managed) => _inMarshaller.FromManaged(managed); + public Native.Types.sd_ctx_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged(); + + public void FromUnmanaged(Native.Types.sd_ctx_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged); + public DiffusionModelParameter ToManaged() => _parameter!; + + public void Free() => _inMarshaller.Free(); } } \ No newline at end of file diff --git a/StableDiffusion.NET/Native/Marshaller/ImageGenerationParameterMarshaller.cs b/StableDiffusion.NET/Native/Marshaller/ImageGenerationParameterMarshaller.cs index 4fbe0d4..b7e2242 100644 --- a/StableDiffusion.NET/Native/Marshaller/ImageGenerationParameterMarshaller.cs +++ b/StableDiffusion.NET/Native/Marshaller/ImageGenerationParameterMarshaller.cs @@ -9,9 +9,9 @@ namespace StableDiffusion.NET; [CustomMarshaller(typeof(ImageGenerationParameter), MarshalMode.ManagedToUnmanagedIn, typeof(ImageGenerationParameterMarshallerIn))] [CustomMarshaller(typeof(ImageGenerationParameter), MarshalMode.ManagedToUnmanagedOut, typeof(ImageGenerationParameterMarshaller))] [CustomMarshaller(typeof(ImageGenerationParameter), MarshalMode.ManagedToUnmanagedRef, typeof(ImageGenerationParameterMarshallerRef))] -internal static class ImageGenerationParameterMarshaller +internal static unsafe class ImageGenerationParameterMarshaller { - public static unsafe ImageGenerationParameter ConvertToManaged(Native.Types.sd_img_gen_params_t unmanaged) + public static ImageGenerationParameter ConvertToManaged(Native.Types.sd_img_gen_params_t unmanaged) { ImageGenerationParameter parameter = new() { @@ -56,28 +56,21 @@ internal static class ImageGenerationParameterMarshaller } }; + for (int i = 0; i < unmanaged.lora_count; i++) + { + Native.Types.sd_lora_t lora = unmanaged.loras[i]; + parameter.Loras.Add(new Lora + { + IsHighNoise = lora.is_high_noise == 1, + Multiplier = lora.multiplier, + Path = AnsiStringMarshaller.ConvertToManaged(lora.path) ?? string.Empty + }); + } + return parameter; } - public static unsafe void Free(Native.Types.sd_img_gen_params_t unmanaged) - { - AnsiStringMarshaller.Free(unmanaged.prompt); - AnsiStringMarshaller.Free(unmanaged.negative_prompt); - - unmanaged.init_image.Free(); - unmanaged.mask_image.Free(); - unmanaged.control_image.Free(); - - if (unmanaged.ref_images != null) - ImageHelper.Free(unmanaged.ref_images, unmanaged.ref_images_count); - - if (unmanaged.pm_params.id_images != null) - ImageHelper.Free(unmanaged.pm_params.id_images, unmanaged.pm_params.id_images_count); - - SampleParameterMarshaller.Free(unmanaged.sample_params); - } - - internal unsafe ref struct ImageGenerationParameterMarshallerIn + internal ref struct ImageGenerationParameterMarshallerIn { private SampleParameterMarshaller.SampleParameterMarshallerIn _sampleParameterMarshaller = new(); private Native.Types.sd_img_gen_params_t _imgGenParams; @@ -87,6 +80,7 @@ internal static class ImageGenerationParameterMarshaller private Native.Types.sd_image_t _controlNetImage; private Native.Types.sd_image_t* _refImages; private Native.Types.sd_image_t* _pmIdImages; + private Native.Types.sd_lora_t* _loras; public ImageGenerationParameterMarshallerIn() { } @@ -99,6 +93,18 @@ internal static class ImageGenerationParameterMarshaller _refImages = managed.RefImages == null ? null : managed.RefImages.ToSdImage(); _pmIdImages = managed.PhotoMaker.IdImages == null ? null : managed.PhotoMaker.IdImages.ToSdImage(); + _loras = (Native.Types.sd_lora_t*)NativeMemory.Alloc((nuint)managed.Loras.Count, (nuint)Marshal.SizeOf()); + for (int i = 0; i < managed.Loras.Count; i++) + { + Lora lora = managed.Loras[i]; + _loras[i] = new Native.Types.sd_lora_t + { + is_high_noise = (sbyte)(lora.IsHighNoise ? 1 : 0), + multiplier = lora.Multiplier, + path = AnsiStringMarshaller.ConvertToUnmanaged(lora.Path) + }; + } + if (managed.MaskImage != null) _maskImage = managed.MaskImage.ToSdImage(true); else if (managed.InitImage != null) @@ -161,7 +167,9 @@ internal static class ImageGenerationParameterMarshaller control_strength = managed.ControlNet.Strength, pm_params = photoMakerParams, vae_tiling_params = tilingParams, - easycache = easyCache + easycache = easyCache, + loras = _loras, + lora_count = (uint)managed.Loras.Count }; } @@ -184,6 +192,12 @@ internal static class ImageGenerationParameterMarshaller ImageHelper.Free(_pmIdImages, _imgGenParams.pm_params.id_images_count); _sampleParameterMarshaller.Free(); + + for (int i = 0; i < _imgGenParams.lora_count; i++) + AnsiStringMarshaller.Free(_imgGenParams.loras[i].path); + + if (_loras != null) + NativeMemory.Free(_loras); } } diff --git a/StableDiffusion.NET/Native/Marshaller/SampleParameterMarshaller.cs b/StableDiffusion.NET/Native/Marshaller/SampleParameterMarshaller.cs index 79c79ac..54de39b 100644 --- a/StableDiffusion.NET/Native/Marshaller/SampleParameterMarshaller.cs +++ b/StableDiffusion.NET/Native/Marshaller/SampleParameterMarshaller.cs @@ -9,9 +9,9 @@ namespace StableDiffusion.NET; [CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedIn, typeof(SampleParameterMarshallerIn))] [CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedOut, typeof(SampleParameterMarshaller))] [CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedRef, typeof(SampleParameterMarshallerRef))] -internal static class SampleParameterMarshaller +internal static unsafe class SampleParameterMarshaller { - public static unsafe SampleParameter ConvertToManaged(Native.Types.sd_sample_params_t unmanaged) + public static SampleParameter ConvertToManaged(Native.Types.sd_sample_params_t unmanaged) { SampleParameter parameter = new() { @@ -33,32 +33,34 @@ internal static class SampleParameterMarshaller SampleMethod = unmanaged.sample_method, SampleSteps = unmanaged.sample_steps, Eta = unmanaged.eta, - ShiftedTimestep = unmanaged.shifted_timestep + ShiftedTimestep = unmanaged.shifted_timestep, + CustomSigmas = new float[unmanaged.custom_sigmas_count] }; if (unmanaged.guidance.slg.layers != null) new Span(unmanaged.guidance.slg.layers, (int)unmanaged.guidance.slg.layer_count).CopyTo(parameter.Guidance.Slg.Layers); + if (unmanaged.custom_sigmas != null) + new Span(unmanaged.custom_sigmas, unmanaged.custom_sigmas_count).CopyTo(parameter.CustomSigmas); + return parameter; } - public static unsafe void Free(Native.Types.sd_sample_params_t unmanaged) - { - if (unmanaged.guidance.slg.layers != null) - NativeMemory.Free(unmanaged.guidance.slg.layers); - } - - internal unsafe ref struct SampleParameterMarshallerIn + internal ref struct SampleParameterMarshallerIn { private Native.Types.sd_sample_params_t _sampleParams; private int* _slgLayers; + private float* _customSigmas; public void FromManaged(SampleParameter managed) { _slgLayers = (int*)NativeMemory.Alloc((nuint)managed.Guidance.Slg.Layers.Length, (nuint)Marshal.SizeOf()); managed.Guidance.Slg.Layers.AsSpan().CopyTo(new Span(_slgLayers, managed.Guidance.Slg.Layers.Length)); + _customSigmas = (float*)NativeMemory.Alloc((nuint)managed.CustomSigmas.Length, (nuint)Marshal.SizeOf()); + managed.CustomSigmas.AsSpan().CopyTo(new Span(_customSigmas, managed.CustomSigmas.Length)); + Native.Types.sd_slg_params_t slg = new() { layers = _slgLayers, @@ -84,7 +86,9 @@ internal static class SampleParameterMarshaller sample_method = managed.SampleMethod, sample_steps = managed.SampleSteps, eta = managed.Eta, - shifted_timestep = managed.ShiftedTimestep + shifted_timestep = managed.ShiftedTimestep, + custom_sigmas = _customSigmas, + custom_sigmas_count = managed.CustomSigmas.Length }; } @@ -94,6 +98,9 @@ internal static class SampleParameterMarshaller { if (_slgLayers != null) NativeMemory.Free(_slgLayers); + + if (_customSigmas != null) + NativeMemory.Free(_customSigmas); } } diff --git a/StableDiffusion.NET/Native/Marshaller/VideoGenerationParameterMarshaller.cs b/StableDiffusion.NET/Native/Marshaller/VideoGenerationParameterMarshaller.cs index c6f77f4..02a10e0 100644 --- a/StableDiffusion.NET/Native/Marshaller/VideoGenerationParameterMarshaller.cs +++ b/StableDiffusion.NET/Native/Marshaller/VideoGenerationParameterMarshaller.cs @@ -1,5 +1,6 @@ // ReSharper disable MemberCanBeMadeStatic.Global +using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; namespace StableDiffusion.NET; @@ -7,9 +8,9 @@ namespace StableDiffusion.NET; [CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedIn, typeof(VideoGenerationParameterMarshallerIn))] [CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedOut, typeof(VideoGenerationParameterMarshaller))] [CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedRef, typeof(VideoGenerationParameterMarshallerRef))] -internal static class VideoGenerationParameterMarshaller +internal static unsafe class VideoGenerationParameterMarshaller { - public static unsafe VideoGenerationParameter ConvertToManaged(Native.Types.sd_vid_gen_params_t unmanaged) + public static VideoGenerationParameter ConvertToManaged(Native.Types.sd_vid_gen_params_t unmanaged) { VideoGenerationParameter parameter = new() { @@ -37,25 +38,21 @@ internal static class VideoGenerationParameterMarshaller } }; + for (int i = 0; i < unmanaged.lora_count; i++) + { + Native.Types.sd_lora_t lora = unmanaged.loras[i]; + parameter.Loras.Add(new Lora + { + IsHighNoise = lora.is_high_noise == 1, + Multiplier = lora.multiplier, + Path = AnsiStringMarshaller.ConvertToManaged(lora.path) ?? string.Empty + }); + } + return parameter; } - public static unsafe void Free(Native.Types.sd_vid_gen_params_t unmanaged) - { - AnsiStringMarshaller.Free(unmanaged.prompt); - AnsiStringMarshaller.Free(unmanaged.negative_prompt); - - unmanaged.init_image.Free(); - unmanaged.end_image.Free(); - - if (unmanaged.control_frames != null) - ImageHelper.Free(unmanaged.control_frames, unmanaged.control_frames_size); - - SampleParameterMarshaller.Free(unmanaged.sample_params); - SampleParameterMarshaller.Free(unmanaged.high_noise_sample_params); - } - - internal unsafe ref struct VideoGenerationParameterMarshallerIn + internal ref struct VideoGenerationParameterMarshallerIn { private SampleParameterMarshaller.SampleParameterMarshallerIn _sampleParameterMarshaller = new(); private SampleParameterMarshaller.SampleParameterMarshallerIn _highNoiseSampleParameterMarshaller = new(); @@ -64,6 +61,7 @@ internal static class VideoGenerationParameterMarshaller private Native.Types.sd_image_t _initImage; private Native.Types.sd_image_t _endImage; private Native.Types.sd_image_t* _controlFrames; + private Native.Types.sd_lora_t* _loras; public VideoGenerationParameterMarshallerIn() { } @@ -75,7 +73,19 @@ internal static class VideoGenerationParameterMarshaller _initImage = managed.InitImage?.ToSdImage() ?? new Native.Types.sd_image_t(); _endImage = managed.EndImage?.ToSdImage() ?? new Native.Types.sd_image_t(); _controlFrames = managed.ControlFrames == null ? null : managed.ControlFrames.ToSdImage(); - + + _loras = (Native.Types.sd_lora_t*)NativeMemory.Alloc((nuint)managed.Loras.Count, (nuint)Marshal.SizeOf()); + for (int i = 0; i < managed.Loras.Count; i++) + { + Lora lora = managed.Loras[i]; + _loras[i] = new Native.Types.sd_lora_t + { + is_high_noise = (sbyte)(lora.IsHighNoise ? 1 : 0), + multiplier = lora.Multiplier, + path = AnsiStringMarshaller.ConvertToUnmanaged(lora.Path) + }; + } + Native.Types.sd_easycache_params_t easyCache = new() { enabled = (sbyte)(managed.EasyCache.IsEnabled ? 1 : 0), @@ -103,6 +113,8 @@ internal static class VideoGenerationParameterMarshaller video_frames = managed.FrameCount, vace_strength = managed.VaceStrength, easycache = easyCache, + loras = _loras, + lora_count = (uint)managed.Loras.Count }; } @@ -121,6 +133,12 @@ internal static class VideoGenerationParameterMarshaller _sampleParameterMarshaller.Free(); _highNoiseSampleParameterMarshaller.Free(); + + for (int i = 0; i < _vidGenParams.lora_count; i++) + AnsiStringMarshaller.Free(_vidGenParams.loras[i].path); + + if (_loras != null) + NativeMemory.Free(_loras); } } diff --git a/StableDiffusion.NET/Native/Native.cs b/StableDiffusion.NET/Native/Native.cs index ffdd241..a6c0875 100644 --- a/StableDiffusion.NET/Native/Native.cs +++ b/StableDiffusion.NET/Native/Native.cs @@ -42,7 +42,7 @@ internal unsafe partial class Native internal static class Types { [StructLayout(LayoutKind.Sequential)] - public struct sd_tiling_params_t + internal struct sd_tiling_params_t { public sbyte enabled; public int tile_size_x; @@ -52,6 +52,13 @@ internal unsafe partial class Native public float rel_size_y; } + [StructLayout(LayoutKind.Sequential)] + internal struct sd_embedding_t + { + public byte* name; + public byte* path; + } + [StructLayout(LayoutKind.Sequential)] internal struct sd_ctx_params_t { @@ -68,7 +75,8 @@ internal unsafe partial class Native public byte* taesd_path; public byte* control_net_path; public byte* lora_model_dir; - public byte* embedding_dir; + public sd_embedding_t* embeddings; + public uint32_t embedding_count; public byte* photo_maker_path; public byte* tensor_type_rules; public sbyte vae_decode_only; @@ -132,6 +140,8 @@ internal unsafe partial class Native public int sample_steps; public float eta; public int shifted_timestep; + public float* custom_sigmas; + public int custom_sigmas_count; } [StructLayout(LayoutKind.Sequential)] @@ -152,9 +162,19 @@ internal unsafe partial class Native public float end_percent; } + [StructLayout(LayoutKind.Sequential)] + internal struct sd_lora_t + { + public sbyte is_high_noise; + public float multiplier; + public byte* path; + } + [StructLayout(LayoutKind.Sequential)] internal struct sd_img_gen_params_t { + public sd_lora_t* loras; + public uint32_t lora_count; public byte* prompt; public byte* negative_prompt; public int clip_skip; @@ -180,6 +200,8 @@ internal unsafe partial class Native [StructLayout(LayoutKind.Sequential)] internal struct sd_vid_gen_params_t { + public sd_lora_t* loras; + public uint32_t lora_count; public byte* prompt; public byte* negative_prompt; public int clip_skip; @@ -305,7 +327,8 @@ internal unsafe partial class Native [LibraryImport(LIB_NAME, EntryPoint = "sd_sample_params_init")] internal static partial void sd_sample_params_init([MarshalUsing(typeof(SampleParameterMarshaller))] ref sd_sample_params_t sample_params); [LibraryImport(LIB_NAME, EntryPoint = "sd_sample_params_to_str")] - internal static partial char* sd_sample_params_to_str([MarshalUsing(typeof(SampleParameterMarshaller))] in sd_sample_params_t sample_params); + [return: MarshalAs(UnmanagedType.LPStr)] + internal static partial string sd_sample_params_to_str([MarshalUsing(typeof(SampleParameterMarshaller))] in sd_sample_params_t sample_params); // @@ -339,7 +362,8 @@ internal unsafe partial class Native internal static partial upscaler_ctx_t* new_upscaler_ctx([MarshalAs(UnmanagedType.LPStr)] string esrgan_path, [MarshalAs(UnmanagedType.I1)] bool offload_params_to_cpu, [MarshalAs(UnmanagedType.I1)] bool direct, - int n_threads); + int n_threads, + int tile_size); [LibraryImport(LIB_NAME, EntryPoint = "free_upscaler_ctx")] internal static partial void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx); @@ -374,5 +398,11 @@ internal unsafe partial class Native float strong, [MarshalAs(UnmanagedType.I1)] bool inverse); + [LibraryImport(LIB_NAME, EntryPoint = "sd_commit")] + internal static partial byte* sd_commit(); + + [LibraryImport(LIB_NAME, EntryPoint = "sd_version")] + internal static partial byte* sd_version(); + #endregion } \ No newline at end of file diff --git a/StableDiffusion.NET/StableDiffusionCpp.cs b/StableDiffusion.NET/StableDiffusionCpp.cs index 7ff65f2..3b5114c 100644 --- a/StableDiffusion.NET/StableDiffusionCpp.cs +++ b/StableDiffusion.NET/StableDiffusionCpp.cs @@ -1,6 +1,7 @@ using HPPH; using JetBrains.Annotations; using System; +using System.Runtime.InteropServices.Marshalling; namespace StableDiffusion.NET; @@ -15,6 +16,8 @@ public static unsafe class StableDiffusionCpp private static Native.sd_preview_cb_t? _previewCallback; // ReSharper restore NotAccessedField.Local + public static string ExpectedSDCommit => "43a70e8"; + #endregion #region Events @@ -62,6 +65,10 @@ public static unsafe class StableDiffusionCpp public static int GetNumPhysicalCores() => Native.sd_get_num_physical_cores(); + public static string GetSDCommit() => AnsiStringMarshaller.ConvertToManaged(Native.sd_commit()) ?? string.Empty; + + public static string GetSDVersion() => AnsiStringMarshaller.ConvertToManaged(Native.sd_version()) ?? string.Empty; + public static Image PreprocessCanny(CannyParameter parameter) { parameter.Validate();