Views
No views yet
/path/to/stable-diffusion-webui1git remote add reForge https://github.com/Panchovix/stable-diffusion-webui-reForge
2git branch Panchovix/main
3git checkout Panchovix/main
4git fetch reForge
5git branch -u reForge/main
6git stash
7git pullgit checkout master or git checkout dev.git merge --aborthttps://github.com/Panchovix/stable-diffusion-webui-reForge.git and then run webui-user.bat):1git clone https://github.com/Panchovix/stable-diffusion-webui-reForge.git
2cd stable-diffusion-webui-reForge
3git checkout main1cd stable-diffusion-webui-reForge
2git pullmedvram, lowvram, medvram-sdxl, precision full, no half, no half vae, attention_xxx, upcast unet, ... are all REMOVED. Adding these flags will not cause error but they will not do anything now. We highly encourage Forge/reForge users to remove all cmd flags and let Forge/reForge to decide how to load models.--always-offload-from-vram (This flag will make things slower but less risky). This option will let Forge/reForge always unload models from VRAM. This can be useful if you use multiple software together and want Forge/reForge to use less VRAM and give some VRAM to other software, or when you are using some old extensions that will compete vram with Forge/reForge, or (very rarely) when you get OOM.--cuda-malloc (This flag will make things faster but more risky). This will ask pytorch to use cudaMallocAsync for tensor malloc. On some profilers I can observe performance gain at millisecond level, but the real speed up on most my devices are often unnoticed (about or less than 0.1 second per image). This cannot be set as default because many users reported issues that the async malloc will crash the program. Users need to enable this cmd flag at their own risk.--cuda-stream (This flag will make things faster but more risky). This will use pytorch CUDA streams (a special type of thread on GPU) to move models and compute tensors simultaneously. This can almost eliminate all model moving time, and speed up SDXL on 30XX/40XX devices with small VRAM (eg, RTX 4050 6GB, RTX 3060 Laptop 6GB, etc) by about 15% to 25%. However, this unfortunately cannot be set as default because I observe higher possibility of pure black images (Nan outputs) on 2060, and higher chance of OOM on 1080 and 2060. When the resolution is large, there is a chance that the computation time of one single attention layer is longer than the time for moving entire model to GPU. When that happens, the next attention layer will OOM since the GPU is filled with the entire model, and no remaining space is available for computing another attention layer. Most overhead detecting methods are not robust enough to be reliable on old devices (in my tests). Users need to enable this cmd flag at their own risk.--pin-shared-memory (This flag will make things faster but more risky). Effective only when used together with --cuda-stream. This will offload modules to Shared GPU Memory instead of system RAM when offloading models. On some 30XX/40XX devices with small VRAM (eg, RTX 4050 6GB, RTX 3060 Laptop 6GB, etc), I can observe significant (at least 20%) speed-up for SDXL. However, this unfortunately cannot be set as default because the OOM of Shared GPU Memory is a much more severe problem than common GPU memory OOM. Pytorch does not provide any robust method to unload or detect Shared GPU Memory. Once the Shared GPU Memory OOM, the entire program will crash (observed with SDXL on GTX 1060/1050/1066), and there is no dynamic method to prevent or recover from the crash. Users need to enable this cmd flag at their own risk.--disable-xformers
Disables xformers, to use other attentions like SDP.
--attention-split
Use the split cross attention optimization. Ignored when xformers is used.
--attention-quad
Use the sub-quadratic cross attention optimization . Ignored when xformers is used.
--attention-pytorch
Use the new pytorch 2.0 cross attention function.
--disable-attention-upcast
Disable all upcasting of attention. Should be unnecessary except for debugging.
--gpu-device-id
Set the id of the cuda device this instance will use.--always-gpu
Store and run everything (text encoders/CLIP models, etc... on the GPU).
--always-high-vram
By default models will be unloaded to CPU memory after being used. This option keeps them in GPU memory.
--always-normal-vram
Used to force normal vram use if lowvram gets automatically enabled.
--always-low-vram
Split the unet in parts to use less vram.
--always-no-vram
When lowvram isn't enough.
--always-cpu
To use the CPU for everything (slow).--all-in-fp32
--all-in-fp16
--unet-in-bf16
--unet-in-fp16
--unet-in-fp8-e4m3fn
--unet-in-fp8-e5m2
--vae-in-fp16
--vae-in-fp32
--vae-in-bf16
--clip-in-fp8-e4m3fn
--clip-in-fp8-e5m2
--clip-in-fp16
--clip-in-fp32--directml
--disable-ipex-hijack
--pytorch-deterministicfantasy landscape with a [mountain:lake:0.25] and [an oak:a christmas tree:0.75][ in foreground::0.6][ in background:0.25] [shoddy:masterful:0.5].Stable Diffusion WebUI with Forge/reForge backend, or for simplicity, the Forge backend. The API and python symbols are made similar to previous software only for reducing the learning cost of developers. Backend has a high percentage of Comfy code, about 80-85% or so.extensions-builtin/sd_forge_freeu/scripts/forge_freeu.py1import torch
2import gradio as gr
3from modules import scripts
4
5
6def Fourier_filter(x, threshold, scale):
7 x_freq = torch.fft.fftn(x.float(), dim=(-2, -1))
8 x_freq = torch.fft.fftshift(x_freq, dim=(-2, -1))
9 B, C, H, W = x_freq.shape
10 mask = torch.ones((B, C, H, W), device=x.device)
11 crow, ccol = H // 2, W //2
12 mask[..., crow - threshold:crow + threshold, ccol - threshold:ccol + threshold] = scale
13 x_freq = x_freq * mask
14 x_freq = torch.fft.ifftshift(x_freq, dim=(-2, -1))
15 x_filtered = torch.fft.ifftn(x_freq, dim=(-2, -1)).real
16 return x_filtered.to(x.dtype)
17
18
19def set_freeu_v2_patch(model, b1, b2, s1, s2):
20 model_channels = model.model.model_config.unet_config["model_channels"]
21 scale_dict = {model_channels * 4: (b1, s1), model_channels * 2: (b2, s2)}
22
23 def output_block_patch(h, hsp, *args, **kwargs):
24 scale = scale_dict.get(h.shape[1], None)
25 if scale is not None:
26 hidden_mean = h.mean(1).unsqueeze(1)
27 B = hidden_mean.shape[0]
28 hidden_max, _ = torch.max(hidden_mean.view(B, -1), dim=-1, keepdim=True)
29 hidden_min, _ = torch.min(hidden_mean.view(B, -1), dim=-1, keepdim=True)
30 hidden_mean = (hidden_mean - hidden_min.unsqueeze(2).unsqueeze(3)) / \
31 (hidden_max - hidden_min).unsqueeze(2).unsqueeze(3)
32 h[:, :h.shape[1] // 2] = h[:, :h.shape[1] // 2] * ((scale[0] - 1) * hidden_mean + 1)
33 hsp = Fourier_filter(hsp, threshold=1, scale=scale[1])
34 return h, hsp
35
36 m = model.clone()
37 m.set_model_output_block_patch(output_block_patch)
38 return m
39
40
41class FreeUForForge(scripts.Script):
42 def title(self):
43 return "FreeU Integrated"
44
45 def show(self, is_img2img):
46 # make this extension visible in both txt2img and img2img tab.
47 return scripts.AlwaysVisible
48
49 def ui(self, *args, **kwargs):
50 with gr.Accordion(open=False, label=self.title()):
51 freeu_enabled = gr.Checkbox(label='Enabled', value=False)
52 freeu_b1 = gr.Slider(label='B1', minimum=0, maximum=2, step=0.01, value=1.01)
53 freeu_b2 = gr.Slider(label='B2', minimum=0, maximum=2, step=0.01, value=1.02)
54 freeu_s1 = gr.Slider(label='S1', minimum=0, maximum=4, step=0.01, value=0.99)
55 freeu_s2 = gr.Slider(label='S2', minimum=0, maximum=4, step=0.01, value=0.95)
56
57 return freeu_enabled, freeu_b1, freeu_b2, freeu_s1, freeu_s2
58
59 def process_before_every_sampling(self, p, *script_args, **kwargs):
60 # This will be called before every sampling.
61 # If you use highres fix, this will be called twice.
62
63 freeu_enabled, freeu_b1, freeu_b2, freeu_s1, freeu_s2 = script_args
64
65 if not freeu_enabled:
66 return
67
68 unet = p.sd_model.forge_objects.unet
69
70 unet = set_freeu_v2_patch(unet, freeu_b1, freeu_b2, freeu_s1, freeu_s2)
71
72 p.sd_model.forge_objects.unet = unet
73
74 # Below codes will add some logs to the texts below the image outputs on UI.
75 # The extra_generation_params does not influence results.
76 p.extra_generation_params.update(dict(
77 freeu_enabled=freeu_enabled,
78 freeu_b1=freeu_b1,
79 freeu_b2=freeu_b2,
80 freeu_s1=freeu_s1,
81 freeu_s2=freeu_s2,
82 ))
83
84 returnextensions-builtin/sd_forge_svd/scripts/forge_svd.py1import torch
2import gradio as gr
3import os
4import pathlib
5
6from modules import script_callbacks
7from modules.paths import models_path
8from modules.ui_common import ToolButton, refresh_symbol
9from modules import shared
10
11from modules_forge.forge_util import numpy_to_pytorch, pytorch_to_numpy
12from ldm_patched.modules.sd import load_checkpoint_guess_config
13from ldm_patched.contrib.external_video_model import VideoLinearCFGGuidance, SVD_img2vid_Conditioning
14from ldm_patched.contrib.external import KSampler, VAEDecode
15
16
17opVideoLinearCFGGuidance = VideoLinearCFGGuidance()
18opSVD_img2vid_Conditioning = SVD_img2vid_Conditioning()
19opKSampler = KSampler()
20opVAEDecode = VAEDecode()
21
22svd_root = os.path.join(models_path, 'svd')
23os.makedirs(svd_root, exist_ok=True)
24svd_filenames = []
25
26
27def update_svd_filenames():
28 global svd_filenames
29 svd_filenames = [
30 pathlib.Path(x).name for x in
31 shared.walk_files(svd_root, allowed_extensions=[".pt", ".ckpt", ".safetensors"])
32 ]
33 return svd_filenames
34
35
36@torch.inference_mode()
37@torch.no_grad()
38def predict(filename, width, height, video_frames, motion_bucket_id, fps, augmentation_level,
39 sampling_seed, sampling_steps, sampling_cfg, sampling_sampler_name, sampling_scheduler,
40 sampling_denoise, guidance_min_cfg, input_image):
41 filename = os.path.join(svd_root, filename)
42 model_raw, _, vae, clip_vision = \
43 load_checkpoint_guess_config(filename, output_vae=True, output_clip=False, output_clipvision=True)
44 model = opVideoLinearCFGGuidance.patch(model_raw, guidance_min_cfg)[0]
45 init_image = numpy_to_pytorch(input_image)
46 positive, negative, latent_image = opSVD_img2vid_Conditioning.encode(
47 clip_vision, init_image, vae, width, height, video_frames, motion_bucket_id, fps, augmentation_level)
48 output_latent = opKSampler.sample(model, sampling_seed, sampling_steps, sampling_cfg,
49 sampling_sampler_name, sampling_scheduler, positive,
50 negative, latent_image, sampling_denoise)[0]
51 output_pixels = opVAEDecode.decode(vae, output_latent)[0]
52 outputs = pytorch_to_numpy(output_pixels)
53 return outputs
54
55
56def on_ui_tabs():
57 with gr.Blocks() as svd_block:
58 with gr.Row():
59 with gr.Column():
60 input_image = gr.Image(label='Input Image', source='upload', type='numpy', height=400)
61
62 with gr.Row():
63 filename = gr.Dropdown(label="SVD Checkpoint Filename",
64 choices=svd_filenames,
65 value=svd_filenames[0] if len(svd_filenames) > 0 else None)
66 refresh_button = ToolButton(value=refresh_symbol, tooltip="Refresh")
67 refresh_button.click(
68 fn=lambda: gr.update(choices=update_svd_filenames),
69 inputs=[], outputs=filename)
70
71 width = gr.Slider(label='Width', minimum=16, maximum=8192, step=8, value=1024)
72 height = gr.Slider(label='Height', minimum=16, maximum=8192, step=8, value=576)
73 video_frames = gr.Slider(label='Video Frames', minimum=1, maximum=4096, step=1, value=14)
74 motion_bucket_id = gr.Slider(label='Motion Bucket Id', minimum=1, maximum=1023, step=1, value=127)
75 fps = gr.Slider(label='Fps', minimum=1, maximum=1024, step=1, value=6)
76 augmentation_level = gr.Slider(label='Augmentation Level', minimum=0.0, maximum=10.0, step=0.01,
77 value=0.0)
78 sampling_steps = gr.Slider(label='Sampling Steps', minimum=1, maximum=200, step=1, value=20)
79 sampling_cfg = gr.Slider(label='CFG Scale', minimum=0.0, maximum=50.0, step=0.1, value=2.5)
80 sampling_denoise = gr.Slider(label='Sampling Denoise', minimum=0.0, maximum=1.0, step=0.01, value=1.0)
81 guidance_min_cfg = gr.Slider(label='Guidance Min Cfg', minimum=0.0, maximum=100.0, step=0.5, value=1.0)
82 sampling_sampler_name = gr.Radio(label='Sampler Name',
83 choices=['euler', 'euler_ancestral', 'heun', 'heunpp2', 'dpm_2',
84 'dpm_2_ancestral', 'lms', 'dpm_fast', 'dpm_adaptive',
85 'dpmpp_2s_ancestral', 'dpmpp_sde', 'dpmpp_sde_gpu',
86 'dpmpp_2m', 'dpmpp_2m_sde', 'dpmpp_2m_sde_gpu',
87 'dpmpp_3m_sde', 'dpmpp_3m_sde_gpu', 'ddpm', 'lcm', 'ddim',
88 'uni_pc', 'uni_pc_bh2'], value='euler')
89 sampling_scheduler = gr.Radio(label='Scheduler',
90 choices=['normal', 'karras', 'exponential', 'sgm_uniform', 'simple',
91 'ddim_uniform'], value='karras')
92 sampling_seed = gr.Number(label='Seed', value=12345, precision=0)
93
94 generate_button = gr.Button(value="Generate")
95
96 ctrls = [filename, width, height, video_frames, motion_bucket_id, fps, augmentation_level,
97 sampling_seed, sampling_steps, sampling_cfg, sampling_sampler_name, sampling_scheduler,
98 sampling_denoise, guidance_min_cfg, input_image]
99
100 with gr.Column():
101 output_gallery = gr.Gallery(label='Gallery', show_label=False, object_fit='contain',
102 visible=True, height=1024, columns=4)
103
104 generate_button.click(predict, inputs=ctrls, outputs=[output_gallery])
105 return [(svd_block, "SVD", "svd")]
106
107
108update_svd_filenames()
109script_callbacks.on_ui_tabs(on_ui_tabs)extensions-builtin/sd_forge_controlnet_example/scripts/sd_forge_controlnet_example.py--show-controlnet-example.1# Use --show-controlnet-example to see this extension.
2
3import cv2
4import gradio as gr
5import torch
6
7from modules import scripts
8from modules.shared_cmd_options import cmd_opts
9from modules_forge.shared import supported_preprocessors
10from modules.modelloader import load_file_from_url
11from ldm_patched.modules.controlnet import load_controlnet
12from modules_forge.controlnet import apply_controlnet_advanced
13from modules_forge.forge_util import numpy_to_pytorch
14from modules_forge.shared import controlnet_dir
15
16
17class ControlNetExampleForge(scripts.Script):
18 model = None
19
20 def title(self):
21 return "ControlNet Example for Developers"
22
23 def show(self, is_img2img):
24 # make this extension visible in both txt2img and img2img tab.
25 return scripts.AlwaysVisible
26
27 def ui(self, *args, **kwargs):
28 with gr.Accordion(open=False, label=self.title()):
29 gr.HTML('This is an example controlnet extension for developers.')
30 gr.HTML('You see this extension because you used --show-controlnet-example')
31 input_image = gr.Image(source='upload', type='numpy')
32 funny_slider = gr.Slider(label='This slider does nothing. It just shows you how to transfer parameters.',
33 minimum=0.0, maximum=1.0, value=0.5)
34
35 return input_image, funny_slider
36
37 def process(self, p, *script_args, **kwargs):
38 input_image, funny_slider = script_args
39
40 # This slider does nothing. It just shows you how to transfer parameters.
41 del funny_slider
42
43 if input_image is None:
44 return
45
46 # controlnet_canny_path = load_file_from_url(
47 # url='https://huggingface.co/lllyasviel/sd_control_collection/resolve/main/sai_xl_canny_256lora.safetensors',
48 # model_dir=model_dir,
49 # file_name='sai_xl_canny_256lora.safetensors'
50 # )
51 controlnet_canny_path = load_file_from_url(
52 url='https://huggingface.co/lllyasviel/fav_models/resolve/main/fav/control_v11p_sd15_canny_fp16.safetensors',
53 model_dir=controlnet_dir,
54 file_name='control_v11p_sd15_canny_fp16.safetensors'
55 )
56 print('The model [control_v11p_sd15_canny_fp16.safetensors] download finished.')
57
58 self.model = load_controlnet(controlnet_canny_path)
59 print('Controlnet loaded.')
60
61 return
62
63 def process_before_every_sampling(self, p, *script_args, **kwargs):
64 # This will be called before every sampling.
65 # If you use highres fix, this will be called twice.
66
67 input_image, funny_slider = script_args
68
69 if input_image is None or self.model is None:
70 return
71
72 B, C, H, W = kwargs['noise'].shape # latent_shape
73 height = H * 8
74 width = W * 8
75 batch_size = p.batch_size
76
77 preprocessor = supported_preprocessors['canny']
78
79 # detect control at certain resolution
80 control_image = preprocessor(
81 input_image, resolution=512, slider_1=100, slider_2=200, slider_3=None)
82
83 # here we just use nearest neighbour to align input shape.
84 # You may want crop and resize, or crop and fill, or others.
85 control_image = cv2.resize(
86 control_image, (width, height), interpolation=cv2.INTER_NEAREST)
87
88 # Output preprocessor result. Now called every sampling. Cache in your own way.
89 p.extra_result_images.append(control_image)
90
91 print('Preprocessor Canny finished.')
92
93 control_image_bchw = numpy_to_pytorch(control_image).movedim(-1, 1)
94
95 unet = p.sd_model.forge_objects.unet
96
97 # Unet has input, middle, output blocks, and we can give different weights
98 # to each layers in all blocks.
99 # Below is an example for stronger control in middle block.
100 # This is helpful for some high-res fix passes. (p.is_hr_pass)
101 positive_advanced_weighting = {
102 'input': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2],
103 'middle': [1.0],
104 'output': [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2]
105 }
106 negative_advanced_weighting = {
107 'input': [0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25],
108 'middle': [1.05],
109 'output': [0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 0.95, 1.05, 1.15, 1.25]
110 }
111
112 # The advanced_frame_weighting is a weight applied to each image in a batch.
113 # The length of this list must be same with batch size
114 # For example, if batch size is 5, the below list is [0.2, 0.4, 0.6, 0.8, 1.0]
115 # If you view the 5 images as 5 frames in a video, this will lead to
116 # progressively stronger control over time.
117 advanced_frame_weighting = [float(i + 1) / float(batch_size) for i in range(batch_size)]
118
119 # The advanced_sigma_weighting allows you to dynamically compute control
120 # weights given diffusion timestep (sigma).
121 # For example below code can softly make beginning steps stronger than ending steps.
122 sigma_max = unet.model.model_sampling.sigma_max
123 sigma_min = unet.model.model_sampling.sigma_min
124 advanced_sigma_weighting = lambda s: (s - sigma_min) / (sigma_max - sigma_min)
125
126 # You can even input a tensor to mask all control injections
127 # The mask will be automatically resized during inference in UNet.
128 # The size should be B 1 H W and the H and W are not important
129 # because they will be resized automatically
130 advanced_mask_weighting = torch.ones(size=(1, 1, 512, 512))
131
132 # But in this simple example we do not use them
133 positive_advanced_weighting = None
134 negative_advanced_weighting = None
135 advanced_frame_weighting = None
136 advanced_sigma_weighting = None
137 advanced_mask_weighting = None
138
139 unet = apply_controlnet_advanced(unet=unet, controlnet=self.model, image_bchw=control_image_bchw,
140 strength=0.6, start_percent=0.0, end_percent=0.8,
141 positive_advanced_weighting=positive_advanced_weighting,
142 negative_advanced_weighting=negative_advanced_weighting,
143 advanced_frame_weighting=advanced_frame_weighting,
144 advanced_sigma_weighting=advanced_sigma_weighting,
145 advanced_mask_weighting=advanced_mask_weighting)
146
147 p.sd_model.forge_objects.unet = unet
148
149 # Below codes will add some logs to the texts below the image outputs on UI.
150 # The extra_generation_params does not influence results.
151 p.extra_generation_params.update(dict(
152 controlnet_info='You should see these texts below output images!',
153 ))
154
155 return
156
157
158# Use --show-controlnet-example to see this extension.
159if not cmd_opts.show_controlnet_example:
160 del ControlNetExampleForge
161modules_forge.shared.preprocessorsextensions-builtin\forge_preprocessor_normalbae\scripts\preprocessor_normalbae.py1from modules_forge.supported_preprocessor import Preprocessor, PreprocessorParameter
2from modules_forge.shared import preprocessor_dir, add_supported_preprocessor
3from modules_forge.forge_util import resize_image_with_pad
4from modules.modelloader import load_file_from_url
5
6import types
7import torch
8import numpy as np
9
10from einops import rearrange
11from annotator.normalbae.models.NNET import NNET
12from annotator.normalbae import load_checkpoint
13from torchvision import transforms
14
15
16class PreprocessorNormalBae(Preprocessor):
17 def __init__(self):
18 super().__init__()
19 self.name = 'normalbae'
20 self.tags = ['NormalMap']
21 self.model_filename_filters = ['normal']
22 self.slider_resolution = PreprocessorParameter(
23 label='Resolution', minimum=128, maximum=2048, value=512, step=8, visible=True)
24 self.slider_1 = PreprocessorParameter(visible=False)
25 self.slider_2 = PreprocessorParameter(visible=False)
26 self.slider_3 = PreprocessorParameter(visible=False)
27 self.show_control_mode = True
28 self.do_not_need_model = False
29 self.sorting_priority = 100 # higher goes to top in the list
30
31 def load_model(self):
32 if self.model_patcher is not None:
33 return
34
35 model_path = load_file_from_url(
36 "https://huggingface.co/lllyasviel/Annotators/resolve/main/scannet.pt",
37 model_dir=preprocessor_dir)
38
39 args = types.SimpleNamespace()
40 args.mode = 'client'
41 args.architecture = 'BN'
42 args.pretrained = 'scannet'
43 args.sampling_ratio = 0.4
44 args.importance_ratio = 0.7
45 model = NNET(args)
46 model = load_checkpoint(model_path, model)
47 self.norm = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
48
49 self.model_patcher = self.setup_model_patcher(model)
50
51 def __call__(self, input_image, resolution, slider_1=None, slider_2=None, slider_3=None, **kwargs):
52 input_image, remove_pad = resize_image_with_pad(input_image, resolution)
53
54 self.load_model()
55
56 self.move_all_model_patchers_to_gpu()
57
58 assert input_image.ndim == 3
59 image_normal = input_image
60
61 with torch.no_grad():
62 image_normal = self.send_tensor_to_model_device(torch.from_numpy(image_normal))
63 image_normal = image_normal / 255.0
64 image_normal = rearrange(image_normal, 'h w c -> 1 c h w')
65 image_normal = self.norm(image_normal)
66
67 normal = self.model_patcher.model(image_normal)
68 normal = normal[0][-1][:, :3]
69 normal = ((normal + 1) * 0.5).clip(0, 1)
70
71 normal = rearrange(normal[0], 'c h w -> h w c').cpu().numpy()
72 normal_image = (normal * 255.0).clip(0, 255).astype(np.uint8)
73
74 return remove_pad(normal_image)
75
76
77add_supported_preprocessor(PreprocessorNormalBae())
78DDPMsd-webui-controlnet
multidiffusion-upscaler-for-automatic1111canvas-zoom
translations/localizations
Dynamic Prompts
Adetailer
Ultimate SD Upscale
Reactor