Compare commits

..

22 Commits

Author SHA1 Message Date
AUTOMATIC1111 6f754ab98b Merge pull request #10780 from akx/image-emb-fonts
Mark caption_image_overlay's textfont as deprecated; fix #10778
2023-06-02 14:36:22 +03:00
AUTOMATIC eed7b2776e add changelog 2023-06-02 10:39:16 +03:00
AUTOMATIC1111 cbc38a903b Merge pull request #10905 from AUTOMATIC1111/fix-10896-pnginfo-parameters
fix 10896 pnginfo parameters
2023-06-02 10:37:35 +03:00
AUTOMATIC eeb685b0e5 bump gradio version to fix tmp filenames for images 2023-06-02 10:34:59 +03:00
AUTOMATIC cbe1799797 Merge branch 'master' into release_candidate 2023-06-01 21:36:48 +03:00
AUTOMATIC b6af0a3809 Merge branch 'release_candidate' 2023-06-01 21:35:14 +03:00
AUTOMATIC 8c3e64f4f6 update readme 2023-06-01 08:13:09 +03:00
AUTOMATIC 3ee1238630 revert default cross attention optimization to Doggettx
make --disable-opt-split-attention command line option work again
2023-06-01 08:12:21 +03:00
AUTOMATIC 17a66931da update readme 2023-06-01 07:29:52 +03:00
AUTOMATIC 915d1da1cd assign devices.dtype early because it's needed before the model is loaded 2023-06-01 07:28:46 +03:00
AUTOMATIC 884435796a add changelog 2023-05-31 23:08:31 +03:00
AUTOMATIC 3690e4e82c fix [Bug]: LoRA don't apply on dropdown list sd_lora #10880 2023-05-31 22:57:27 +03:00
AUTOMATIC1111 6427ffde4d Merge pull request #10808 from AUTOMATIC1111/fix-disable-png-info
fix disable png info
2023-05-31 22:56:56 +03:00
AUTOMATIC1111 c63d46ceb8 Merge pull request #10804 from AUTOMATIC1111/fix-xyz-clip
Fix get_conds_with_caching()
2023-05-31 22:54:51 +03:00
AUTOMATIC1111 fae8bdfa48 Merge pull request #10785 from nyqui/fix-hires.fix
fix "hires. fix" prompt sharing same labels with txt2img_prompt
2023-05-31 22:54:24 +03:00
AUTOMATIC 10dbee0d59 add quoting for infotext values that have a colon in them 2023-05-31 22:54:00 +03:00
AUTOMATIC 20ae71faa8 fix linter issue for 1.3.0 2023-05-27 20:23:16 +03:00
AUTOMATIC 6095ade147 fix serving images that have already been saved without temp files function that broke after updating gradio 2023-05-27 20:19:10 +03:00
AUTOMATIC dd377637ca update the changelog to mention 1.3.0 version 2023-05-27 20:16:33 +03:00
AUTOMATIC 50906bf78b Merge branch 'release_candidate' 2023-05-27 20:13:26 +03:00
AUTOMATIC b186045fee possible fix for empty list of optimizations #10605 2023-05-23 18:02:09 +03:00
AUTOMATIC 3f50b7d71c fix bad styling for thumbs view in extra networks #10639 2023-05-23 14:07:00 +03:00
16 changed files with 112 additions and 46 deletions
+21 -1
View File
@@ -1,4 +1,24 @@
## Upcoming 1.3.0
## 1.3.2
### Bug Fixes:
* fix files served out of tmp directory even if they are saved to disk
* fix postprocessing overwriting parameters
## 1.3.1
### Features:
* revert default cross attention optimization to Doggettx
### Bug Fixes:
* fix bug: LoRA don't apply on dropdown list sd_lora
* fix png info always added even if setting is not enabled
* fix some fields not applying in xyz plot
* fix "hires. fix" prompt sharing same labels with txt2img_prompt
* fix lora hashes not being added properly to infotex if there is only one lora
* fix --use-cpu failing to work properly at startup
* make --disable-opt-split-attention command line option work again
## 1.3.0
### Features:
* add UI to edit defaults
+1 -1
View File
@@ -62,7 +62,7 @@ parser.add_argument("--opt-split-attention-invokeai", action='store_true', help=
parser.add_argument("--opt-split-attention-v1", action='store_true', help="prefer older version of split attention optimization for automatic choice of optimization")
parser.add_argument("--opt-sdp-attention", action='store_true', help="prefer scaled dot product cross-attention layer optimization for automatic choice of optimization; requires PyTorch 2.*")
parser.add_argument("--opt-sdp-no-mem-attention", action='store_true', help="prefer scaled dot product cross-attention layer optimization without memory efficient attention for automatic choice of optimization, makes image generation deterministic; requires PyTorch 2.*")
parser.add_argument("--disable-opt-split-attention", action='store_true', help="does not do anything")
parser.add_argument("--disable-opt-split-attention", action='store_true', help="prefer no cross-attention layer optimization for automatic choice of optimization")
parser.add_argument("--disable-nan-check", action='store_true', help="do not check if produced images/latent spaces have nans; useful for running without a checkpoint in CI")
parser.add_argument("--use-cpu", nargs='+', help="use CPU as torch device for specified modules", default=[], type=str.lower)
parser.add_argument("--listen", action='store_true', help="launch gradio with 0.0.0.0 as server name, allowing to respond to network requests")
+1 -1
View File
@@ -26,7 +26,7 @@ class ExtraNetworkParams:
self.named = {}
for item in self.items:
parts = item.split('=', 2)
parts = item.split('=', 2) if isinstance(item, str) else [item]
if len(parts) == 2:
self.named[parts[0]] = parts[1]
else:
+1 -1
View File
@@ -35,7 +35,7 @@ def reset():
def quote(text):
if ',' not in str(text) and '\n' not in str(text):
if ',' not in str(text) and '\n' not in str(text) and ':' not in str(text):
return text
return json.dumps(text, ensure_ascii=False)
+6 -7
View File
@@ -488,14 +488,13 @@ def save_image_with_geninfo(image, geninfo, filename, extension=None, existing_p
image_format = Image.registered_extensions()[extension]
existing_pnginfo = existing_pnginfo or {}
if opts.enable_pnginfo:
existing_pnginfo['parameters'] = geninfo
if extension.lower() == '.png':
pnginfo_data = PngImagePlugin.PngInfo()
for k, v in (existing_pnginfo or {}).items():
pnginfo_data.add_text(k, str(v))
if opts.enable_pnginfo:
pnginfo_data = PngImagePlugin.PngInfo()
for k, v in (existing_pnginfo or {}).items():
pnginfo_data.add_text(k, str(v))
else:
pnginfo_data = None
image.save(filename, format=image_format, quality=opts.jpeg_quality, pnginfo=pnginfo_data)
+2 -3
View File
@@ -321,14 +321,13 @@ class StableDiffusionProcessing:
have been used before. The second element is where the previously
computed result is stored.
"""
if cache[0] is not None and (required_prompts, steps) == cache[0]:
if cache[0] is not None and (required_prompts, steps, opts.CLIP_stop_at_last_layers, shared.sd_model.sd_checkpoint_info) == cache[0]:
return cache[1]
with devices.autocast():
cache[1] = function(shared.sd_model, required_prompts, steps)
cache[0] = (required_prompts, steps)
cache[0] = (required_prompts, steps, opts.CLIP_stop_at_last_layers, shared.sd_model.sd_checkpoint_info)
return cache[1]
def setup_conds(self):
+17 -6
View File
@@ -48,6 +48,11 @@ def apply_optimizations():
undo_optimizations()
if len(optimizers) == 0:
# a script can access the model very early, and optimizations would not be filled by then
current_optimizer = None
return ''
ldm.modules.diffusionmodules.model.nonlinearity = silu
ldm.modules.diffusionmodules.openaimodel.th = sd_hijack_unet.th
@@ -63,12 +68,15 @@ def apply_optimizations():
if selection == "None":
matching_optimizer = None
elif selection == "Automatic" and shared.cmd_opts.disable_opt_split_attention:
matching_optimizer = None
elif matching_optimizer is None:
matching_optimizer = optimizers[0]
if matching_optimizer is not None:
print(f"Applying optimization: {matching_optimizer.name}")
print(f"Applying optimization: {matching_optimizer.name}... ", end='')
matching_optimizer.apply()
print("done.")
current_optimizer = matching_optimizer
return current_optimizer.name
else:
@@ -149,6 +157,13 @@ class StableDiffusionModelHijack:
def __init__(self):
self.embedding_db.add_embedding_dir(cmd_opts.embeddings_dir)
def apply_optimizations(self):
try:
self.optimization_method = apply_optimizations()
except Exception as e:
errors.display(e, "applying cross attention optimization")
undo_optimizations()
def hijack(self, m):
if type(m.cond_stage_model) == xlmr.BertSeriesModelWithTransformation:
model_embeddings = m.cond_stage_model.roberta.embeddings
@@ -168,11 +183,7 @@ class StableDiffusionModelHijack:
if m.cond_stage_key == "edit":
sd_hijack_unet.hijack_ddpm_edit()
try:
self.optimization_method = apply_optimizations()
except Exception as e:
errors.display(e, "applying cross attention optimization")
undo_optimizations()
self.apply_optimizations()
self.clip = m.cond_stage_model
+3 -3
View File
@@ -59,7 +59,7 @@ class SdOptimizationSdpNoMem(SdOptimization):
name = "sdp-no-mem"
label = "scaled dot product without memory efficient attention"
cmd_opt = "opt_sdp_no_mem_attention"
priority = 90
priority = 80
def is_available(self):
return hasattr(torch.nn.functional, "scaled_dot_product_attention") and callable(torch.nn.functional.scaled_dot_product_attention)
@@ -73,7 +73,7 @@ class SdOptimizationSdp(SdOptimizationSdpNoMem):
name = "sdp"
label = "scaled dot product"
cmd_opt = "opt_sdp_attention"
priority = 80
priority = 70
def apply(self):
ldm.modules.attention.CrossAttention.forward = scaled_dot_product_attention_forward
@@ -116,7 +116,7 @@ class SdOptimizationInvokeAI(SdOptimization):
class SdOptimizationDoggettx(SdOptimization):
name = "Doggettx"
cmd_opt = "opt_split_attention"
priority = 20
priority = 90
def apply(self):
ldm.modules.attention.CrossAttention.forward = split_cross_attention_forward
-2
View File
@@ -313,8 +313,6 @@ def load_model_weights(model, checkpoint_info: CheckpointInfo, state_dict, timer
timer.record("apply half()")
devices.dtype = torch.float32 if shared.cmd_opts.no_half else torch.float16
devices.dtype_vae = torch.float32 if shared.cmd_opts.no_half or shared.cmd_opts.no_half_vae else torch.float16
devices.dtype_unet = model.model.diffusion_model.dtype
devices.unet_needs_upcast = shared.cmd_opts.upcast_sampling and devices.dtype == torch.float16 and devices.dtype_unet == torch.float16
+4
View File
@@ -6,6 +6,7 @@ import threading
import time
import gradio as gr
import torch
import tqdm
import modules.interrogate
@@ -76,6 +77,9 @@ cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_op
devices.device, devices.device_interrogate, devices.device_gfpgan, devices.device_esrgan, devices.device_codeformer = \
(devices.cpu if any(y in cmd_opts.use_cpu for y in [x, 'all']) else devices.get_optimal_device() for x in ['sd', 'interrogate', 'gfpgan', 'esrgan', 'codeformer'])
devices.dtype = torch.float32 if cmd_opts.no_half else torch.float16
devices.dtype_vae = torch.float32 if cmd_opts.no_half or cmd_opts.no_half_vae else torch.float16
device = devices.device
weight_load_location = None if cmd_opts.lowram else "cpu"
+13 -8
View File
@@ -1,8 +1,10 @@
import base64
import json
import warnings
import numpy as np
import zlib
from PIL import Image, ImageDraw, ImageFont
from PIL import Image, ImageDraw
import torch
@@ -129,14 +131,17 @@ def extract_image_data_embed(image):
def caption_image_overlay(srcimage, title, footerLeft, footerMid, footerRight, textfont=None):
from modules.images import get_font
if textfont:
warnings.warn(
'passing in a textfont to caption_image_overlay is deprecated and does nothing',
DeprecationWarning,
stacklevel=2,
)
from math import cos
image = srcimage.copy()
fontsize = 32
if textfont is None:
from modules.images import get_font
textfont = get_font(fontsize)
factor = 1.5
gradient = Image.new('RGBA', (1, image.size[1]), color=(0, 0, 0, 0))
for y in range(image.size[1]):
@@ -147,12 +152,12 @@ def caption_image_overlay(srcimage, title, footerLeft, footerMid, footerRight, t
draw = ImageDraw.Draw(image)
font = ImageFont.truetype(textfont, fontsize)
font = get_font(fontsize)
padding = 10
_, _, w, h = draw.textbbox((0, 0), title, font=font)
fontsize = min(int(fontsize * (((image.size[0]*0.75)-(padding*4))/w)), 72)
font = ImageFont.truetype(textfont, fontsize)
font = get_font(fontsize)
_, _, w, h = draw.textbbox((0, 0), title, font=font)
draw.text((padding, padding), title, anchor='lt', font=font, fill=(255, 255, 255, 230))
@@ -163,7 +168,7 @@ def caption_image_overlay(srcimage, title, footerLeft, footerMid, footerRight, t
_, _, w, h = draw.textbbox((0, 0), footerRight, font=font)
fontsize_right = min(int(fontsize * (((image.size[0]/3)-(padding))/w)), 72)
font = ImageFont.truetype(textfont, min(fontsize_left, fontsize_mid, fontsize_right))
font = get_font(min(fontsize_left, fontsize_mid, fontsize_right))
draw.text((padding, image.size[1]-padding), footerLeft, anchor='ls', font=font, fill=(255, 255, 255, 230))
draw.text((image.size[0]/2, image.size[1]-padding), footerMid, anchor='ms', font=font, fill=(255, 255, 255, 230))
+2 -2
View File
@@ -505,10 +505,10 @@ def create_ui():
with FormRow(elem_id="txt2img_hires_fix_row4", variant="compact", visible=opts.hires_fix_show_prompts) as hr_prompts_container:
with gr.Column(scale=80):
with gr.Row():
hr_prompt = gr.Textbox(label="Prompt", elem_id="hires_prompt", show_label=False, lines=3, placeholder="Prompt for hires fix pass.\nLeave empty to use the same prompt as in first pass.", elem_classes=["prompt"])
hr_prompt = gr.Textbox(label="Hires prompt", elem_id="hires_prompt", show_label=False, lines=3, placeholder="Prompt for hires fix pass.\nLeave empty to use the same prompt as in first pass.", elem_classes=["prompt"])
with gr.Column(scale=80):
with gr.Row():
hr_negative_prompt = gr.Textbox(label="Negative prompt", elem_id="hires_neg_prompt", show_label=False, lines=3, placeholder="Negative prompt for hires fix pass.\nLeave empty to use the same negative prompt as in first pass.", elem_classes=["prompt"])
hr_negative_prompt = gr.Textbox(label="Hires negative prompt", elem_id="hires_neg_prompt", show_label=False, lines=3, placeholder="Negative prompt for hires fix pass.\nLeave empty to use the same negative prompt as in first pass.", elem_classes=["prompt"])
elif category == "batch":
if not opts.dimensions_and_batch_together:
+9 -6
View File
@@ -3,7 +3,7 @@ import tempfile
from collections import namedtuple
from pathlib import Path
import gradio as gr
import gradio.components
from PIL import PngImagePlugin
@@ -31,13 +31,16 @@ def check_tmp_file(gradio, filename):
return False
def save_pil_to_file(pil_image, dir=None):
def save_pil_to_file(self, pil_image, dir=None):
already_saved_as = getattr(pil_image, 'already_saved_as', None)
if already_saved_as and os.path.isfile(already_saved_as):
register_tmp_file(shared.demo, already_saved_as)
filename = already_saved_as
file_obj = Savedfile(f'{already_saved_as}?{os.path.getmtime(already_saved_as)}')
return file_obj
if not shared.opts.save_images_add_number:
filename += f'?{os.path.getmtime(already_saved_as)}'
return filename
if shared.opts.temp_dir != "":
dir = shared.opts.temp_dir
@@ -51,11 +54,11 @@ def save_pil_to_file(pil_image, dir=None):
file_obj = tempfile.NamedTemporaryFile(delete=False, suffix=".png", dir=dir)
pil_image.save(file_obj, pnginfo=(metadata if use_metadata else None))
return file_obj
return file_obj.name
# override save to file function so that it also writes PNG info
gr.processing_utils.save_pil_to_file = save_pil_to_file
gradio.components.IOComponent.pil_to_temp_file = save_pil_to_file
def on_tmpdir_changed():
+1 -1
View File
@@ -3,7 +3,7 @@ transformers==4.25.1
accelerate==0.18.0
basicsr==1.4.2
gfpgan==1.3.8
gradio==3.31.0
gradio==3.32.0
numpy==1.23.5
Pillow==9.5.0
realesrgan==0.3.0
+17 -1
View File
@@ -756,13 +756,22 @@ footer {
.extra-network-cards .card .metadata-button, .extra-network-thumbs .card .metadata-button{
display: none;
position: absolute;
right: 0;
color: white;
right: 0;
}
.extra-network-cards .card .metadata-button {
text-shadow: 2px 2px 3px black;
padding: 0.25em;
font-size: 22pt;
width: 1.5em;
}
.extra-network-thumbs .card .metadata-button {
text-shadow: 1px 1px 2px black;
padding: 0;
font-size: 16pt;
width: 1em;
top: -0.25em;
}
.extra-network-cards .card:hover .metadata-button, .extra-network-thumbs .card:hover .metadata-button{
display: inline-block;
}
@@ -787,6 +796,13 @@ footer {
position: relative;
}
.extra-network-thumbs .card .preview{
position: absolute;
object-fit: cover;
width: 100%;
height:100%;
}
.extra-network-thumbs .card:hover .additional a {
display: inline-block;
}
+14 -3
View File
@@ -291,9 +291,20 @@ def initialize_rest(*, reload_script_modules=False):
modules.sd_hijack.list_optimizers()
startup_timer.record("scripts list_optimizers")
# load model in parallel to other startup stuff
# (when reloading, this does nothing)
Thread(target=lambda: shared.sd_model).start()
def load_model():
"""
Accesses shared.sd_model property to load model.
After it's available, if it has been loaded before this access by some extension,
its optimization may be None because the list of optimizaers has neet been filled
by that time, so we apply optimization again.
"""
shared.sd_model # noqa: B018
if modules.sd_hijack.current_optimizer is None:
modules.sd_hijack.apply_optimizations()
Thread(target=load_model).start()
shared.reload_hypernetworks()
startup_timer.record("reload hypernetworks")