diff --git a/StabilityMatrix.Avalonia/App.axaml b/StabilityMatrix.Avalonia/App.axaml index fe088a5be..95f8e0d52 100644 --- a/StabilityMatrix.Avalonia/App.axaml +++ b/StabilityMatrix.Avalonia/App.axaml @@ -100,6 +100,7 @@ + + diff --git a/StabilityMatrix.Avalonia/Controls/Inference/CfzCudnnToggleCard.axaml.cs b/StabilityMatrix.Avalonia/Controls/Inference/CfzCudnnToggleCard.axaml.cs new file mode 100644 index 000000000..c969f9770 --- /dev/null +++ b/StabilityMatrix.Avalonia/Controls/Inference/CfzCudnnToggleCard.axaml.cs @@ -0,0 +1,6 @@ +using Injectio.Attributes; + +namespace StabilityMatrix.Avalonia.Controls; + +[RegisterTransient] +public class CfzCudnnToggleCard : TemplatedControlBase; diff --git a/StabilityMatrix.Avalonia/ViewModels/Base/LoadableViewModelBase.cs b/StabilityMatrix.Avalonia/ViewModels/Base/LoadableViewModelBase.cs index a3cd9d111..a42f7391f 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Base/LoadableViewModelBase.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Base/LoadableViewModelBase.cs @@ -26,6 +26,7 @@ namespace StabilityMatrix.Avalonia.ViewModels.Base; [JsonDerivedType(typeof(RescaleCfgCardViewModel), RescaleCfgCardViewModel.ModuleKey)] [JsonDerivedType(typeof(PlasmaNoiseCardViewModel), PlasmaNoiseCardViewModel.ModuleKey)] [JsonDerivedType(typeof(NrsCardViewModel), NrsCardViewModel.ModuleKey)] +[JsonDerivedType(typeof(CfzCudnnToggleCardViewModel), CfzCudnnToggleCardViewModel.ModuleKey)] [JsonDerivedType(typeof(FreeUModule))] [JsonDerivedType(typeof(HiresFixModule))] [JsonDerivedType(typeof(FluxHiresFixModule))] @@ -41,6 +42,7 @@ namespace StabilityMatrix.Avalonia.ViewModels.Base; [JsonDerivedType(typeof(RescaleCfgModule))] [JsonDerivedType(typeof(PlasmaNoiseModule))] [JsonDerivedType(typeof(NRSModule))] +[JsonDerivedType(typeof(CfzCudnnToggleModule))] public abstract class LoadableViewModelBase : ViewModelBase, IJsonLoadableState { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/CfzCudnnToggleCardViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/CfzCudnnToggleCardViewModel.cs new file mode 100644 index 000000000..07c7df47f --- /dev/null +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/CfzCudnnToggleCardViewModel.cs @@ -0,0 +1,21 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using Injectio.Attributes; +using StabilityMatrix.Avalonia.Controls; +using StabilityMatrix.Avalonia.ViewModels.Base; +using StabilityMatrix.Core.Attributes; + +namespace StabilityMatrix.Avalonia.ViewModels.Inference; + +[View(typeof(CfzCudnnToggleCard))] +[ManagedService] +[RegisterTransient] +public partial class CfzCudnnToggleCardViewModel : LoadableViewModelBase +{ + public const string ModuleKey = "CfzCudnnToggle"; + + [ObservableProperty] + private bool enableCudnn = false; + + [ObservableProperty] + private bool cudnnBenchmark; +} diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceFluxTextToImageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceFluxTextToImageViewModel.cs index da8cb5457..154c732e6 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceFluxTextToImageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceFluxTextToImageViewModel.cs @@ -93,10 +93,11 @@ RunningPackageService runningPackageService { modulesCard.AvailableModules = new[] { + typeof(CfzCudnnToggleModule), + typeof(FaceDetailerModule), typeof(FluxHiresFixModule), - typeof(UpscalerModule), typeof(SaveImageModule), - typeof(FaceDetailerModule) + typeof(UpscalerModule), }; modulesCard.DefaultModules = new[] { typeof(FluxHiresFixModule), typeof(UpscalerModule) }; modulesCard.InitializeDefaults(); @@ -121,7 +122,7 @@ protected override void BuildPrompt(BuildPromptEventArgs args) builder.Connections.Seed = args.SeedOverride switch { { } seed => Convert.ToUInt64(seed), - _ => Convert.ToUInt64(SeedCardViewModel.Seed) + _ => Convert.ToUInt64(SeedCardViewModel.Seed), }; var applyArgs = args.ToModuleApplyStepEventArgs(); @@ -217,7 +218,7 @@ CancellationToken cancellationToken FilesToTransfer = buildPromptArgs.FilesToTransfer, BatchIndex = i, // Only clear output images on the first batch - ClearOutputImages = i == 0 + ClearOutputImages = i == 0, }; batchArgs.Add(generationArgs); diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs index 039f1a7ab..39ff2eb33 100644 --- a/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/InferenceTextToImageViewModel.cs @@ -100,10 +100,11 @@ TabContext tabContext { modulesCard.AvailableModules = new[] { + typeof(CfzCudnnToggleModule), + typeof(FaceDetailerModule), typeof(HiresFixModule), - typeof(UpscalerModule), typeof(SaveImageModule), - typeof(FaceDetailerModule) + typeof(UpscalerModule), }; modulesCard.DefaultModules = new[] { typeof(HiresFixModule), typeof(UpscalerModule) }; modulesCard.InitializeDefaults(); @@ -158,7 +159,7 @@ protected override void BuildPrompt(BuildPromptEventArgs args) builder.Connections.Seed = args.SeedOverride switch { { } seed => Convert.ToUInt64(seed), - _ => Convert.ToUInt64(SeedCardViewModel.Seed) + _ => Convert.ToUInt64(SeedCardViewModel.Seed), }; var applyArgs = args.ToModuleApplyStepEventArgs(); @@ -319,13 +320,13 @@ CancellationToken cancellationToken OutputNodeNames = buildPromptArgs.Builder.Connections.OutputNodeNames.ToArray(), Parameters = SaveStateToParameters(new GenerationParameters()) with { - Seed = Convert.ToUInt64(seed) + Seed = Convert.ToUInt64(seed), }, Project = inferenceProject, FilesToTransfer = buildPromptArgs.FilesToTransfer, BatchIndex = i, // Only clear output images on the first batch - ClearOutputImages = i == 0 + ClearOutputImages = i == 0, }; batchArgs.Add(generationArgs); diff --git a/StabilityMatrix.Avalonia/ViewModels/Inference/Modules/CfzCudnnToggleModule.cs b/StabilityMatrix.Avalonia/ViewModels/Inference/Modules/CfzCudnnToggleModule.cs new file mode 100644 index 000000000..a1287f490 --- /dev/null +++ b/StabilityMatrix.Avalonia/ViewModels/Inference/Modules/CfzCudnnToggleModule.cs @@ -0,0 +1,61 @@ +using System.Linq; +using Injectio.Attributes; +using StabilityMatrix.Avalonia.Models.Inference; +using StabilityMatrix.Avalonia.Services; +using StabilityMatrix.Avalonia.ViewModels.Base; +using StabilityMatrix.Avalonia.ViewModels.Inference; +using StabilityMatrix.Core.Attributes; +using StabilityMatrix.Core.Models.Api.Comfy.Nodes; +using StabilityMatrix.Core.Models.Api.Comfy.NodeTypes; +using StabilityMatrix.Core.Models.Inference; + +namespace StabilityMatrix.Avalonia.ViewModels.Inference.Modules; + +[ManagedService] +[RegisterTransient] +public class CfzCudnnToggleModule : ModuleBase +{ + /// + public CfzCudnnToggleModule(IServiceManager vmFactory) + : base(vmFactory) + { + Title = "Disable CUDNN (ComfyUI-Zluda)"; + } + + /// + /// Applies CUDNN Toggle node between sampler latent output and VAE decode + /// This prevents "GET was unable to find an engine" errors on AMD cards with Zluda + /// + protected override void OnApplyStep(ModuleApplyStepEventArgs e) + { + // Get the primary connection (can be latent or image) + var primary = e.Builder.Connections.Primary; + if (primary == null) + { + return; // No primary connection to process + } + + // Check if primary is a latent (from sampler output) + if (primary.IsT0) // T0 is LatentNodeConnection + { + var latentConnection = primary.AsT0; + + // Insert CUDNN toggle node between sampler and VAE decode + var cudnnToggleOutput = e.Nodes.AddTypedNode( + new ComfyNodeBuilder.CUDNNToggleAutoPassthrough + { + Name = e.Nodes.GetUniqueName("CUDNNToggle"), + Model = null, + Conditioning = null, + Latent = latentConnection, // Pass through the latent from sampler + enable_cudnn = false, + cudnn_benchmark = false, + } + ); + + // Update the primary connection to use the CUDNN toggle latent output (Output3) + // This ensures VAE decode receives latent from CUDNN toggle instead of directly from sampler + e.Builder.Connections.Primary = cudnnToggleOutput.Output3; + } + } +} diff --git a/StabilityMatrix.Core/Models/Api/Comfy/Nodes/ComfyNodeBuilder.cs b/StabilityMatrix.Core/Models/Api/Comfy/Nodes/ComfyNodeBuilder.cs index a78508e8d..181cfc70c 100644 --- a/StabilityMatrix.Core/Models/Api/Comfy/Nodes/ComfyNodeBuilder.cs +++ b/StabilityMatrix.Core/Models/Api/Comfy/Nodes/ComfyNodeBuilder.cs @@ -997,6 +997,20 @@ public record BrownNoise : ComfyTypedNodeBase public required ulong Seed { get; init; } = 0; } + /// + /// CUDNN Toggle node for controlling CUDA Deep Neural Network library settings (CUDNNToggleAutoPassthrough) + /// + [TypedNodeOptions(Name = "CUDNNToggleAutoPassthrough")] + public record CUDNNToggleAutoPassthrough + : ComfyTypedNodeBase + { + public ModelNodeConnection? Model { get; init; } + public ConditioningNodeConnection? Conditioning { get; init; } + public LatentNodeConnection? Latent { get; init; } + public required bool EnableCudnn { get; init; } = false; + public required bool CudnnBenchmark { get; init; } = false; + } + /// /// Custom KSampler node using alternative noise distribution (Lykos_JDC_PlasmaSampler) ///