diff --git a/README.md b/README.md index eaa8f62bc..bc524b43a 100644 --- a/README.md +++ b/README.md @@ -2,22 +2,23 @@ *Heavily opinionated custom fork of* -![](ui-screenshot.jpg) +![screenshot](ui-screenshot.jpg)
-### Notes +## Notes Fork is as close as up-to-date with origin as time allows All code changes are merged upstream whenever possible Fork adds extra functionality: + - New skin and UI layout - Ships with set of **CLI** tools that rely on *SD API* for execution: e.g. `generate`, `train`, `bench`, etc. [Full list]() -### Integrated Extensions: +### Integrated Extensions - [System Info](https://github.com/vladmandic/sd-extension-system-info) - [ControlNet](https://github.com/Mikubill/sd-webui-controlnet) @@ -59,6 +60,7 @@ Use this for troubleshooting > ./automatic.sh install Installs and updates to latest supported version: + - Dependencies - Fixed sub-repositories - Extensions @@ -105,12 +107,13 @@ Start with listen on public IP with authentication enabled Updating wiki Detached repos Local changes - +
## Differences Fork does differ in few things: + - Drops compatibility with `python` **3.7** and requires **3.9** Recommended is **Python 3.10** Note that **Python 3.11** or **3.12** are NOT supported diff --git a/automatic.svg b/automatic.svg new file mode 100644 index 000000000..ac6e5431d --- /dev/null +++ b/automatic.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/config.json b/config.json index fa787597e..0b18d24ad 100644 --- a/config.json +++ b/config.json @@ -41,6 +41,8 @@ "disable_weights_auto_swap": false, "disabled_extensions": [ "openOutpaint-webUI-extension", + "openpose-editor", + "sd-webui-3d-open-pose-editor", "ScuNET" ], "do_not_add_watermark": true, diff --git a/extensions-builtin/sd-extension-system-info b/extensions-builtin/sd-extension-system-info index 2e6e7b227..5ff97afb5 160000 --- a/extensions-builtin/sd-extension-system-info +++ b/extensions-builtin/sd-extension-system-info @@ -1 +1 @@ -Subproject commit 2e6e7b2270688366c1b185a9ab52d2b5b7c17f6e +Subproject commit 5ff97afb5c8cba4d8ea0d06de4cd7e48c382c402 diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet index 8682c1e49..6e339e9b5 160000 --- a/extensions-builtin/sd-webui-controlnet +++ b/extensions-builtin/sd-webui-controlnet @@ -1 +1 @@ -Subproject commit 8682c1e49728926bb7cc7753da8917d1ab095fb1 +Subproject commit 6e339e9b578019576155e7902c660fb88acdcb36 diff --git a/extensions-builtin/seed_travel b/extensions-builtin/seed_travel index ebc887b75..3d075a59e 160000 --- a/extensions-builtin/seed_travel +++ b/extensions-builtin/seed_travel @@ -1 +1 @@ -Subproject commit ebc887b751beb1752101cb7bebe7de7a239f7782 +Subproject commit 3d075a59e5493af4d0cad34c98b22bc9302e70b2 diff --git a/extensions-builtin/stable-diffusion-webui-images-browser b/extensions-builtin/stable-diffusion-webui-images-browser index 6de0af30b..58c374c61 160000 --- a/extensions-builtin/stable-diffusion-webui-images-browser +++ b/extensions-builtin/stable-diffusion-webui-images-browser @@ -1 +1 @@ -Subproject commit 6de0af30b02c7e6b527881061701fe623f632fe5 +Subproject commit 58c374c61bca0ab3c2b62d9015a0f572ab510ac8 diff --git a/javascript/localization.js b/javascript/localization.disabled similarity index 100% rename from javascript/localization.js rename to javascript/localization.disabled diff --git a/modules/lycoris b/modules/lycoris index da0033c1d..2389611cc 160000 --- a/modules/lycoris +++ b/modules/lycoris @@ -1 +1 @@ -Subproject commit da0033c1d387f95b228d09a9724cfd994fcee446 +Subproject commit 2389611cc83e0a23499c97a56a9be666a4a7b604 diff --git a/modules/sd_models.py b/modules/sd_models.py index c6a841fa6..1f04fef0c 100644 --- a/modules/sd_models.py +++ b/modules/sd_models.py @@ -302,15 +302,12 @@ def load_model_weights(model, checkpoint_info: CheckpointInfo, state_dict, timer if depth_model: model.depth_model = depth_model - 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 model.first_stage_model.to(devices.dtype_vae) - timer.record("apply dtype to VAE") # clean up cache if limit is reached while len(checkpoints_loaded) > shared.opts.sd_checkpoint_cache: @@ -327,7 +324,7 @@ def load_model_weights(model, checkpoint_info: CheckpointInfo, state_dict, timer sd_vae.clear_loaded_vae() vae_file, vae_source = sd_vae.resolve_vae(checkpoint_info.filename) sd_vae.load_vae(model, vae_file, vae_source) - timer.record("load VAE") + timer.record("load vae") def enable_midas_autodownload(): @@ -440,7 +437,7 @@ def load_model(checkpoint_info=None, already_loaded_state_dict=None, time_taken_ else: sd_model.to(shared.device) - timer.record("move model to device") + timer.record("device move") sd_hijack.model_hijack.hijack(sd_model) @@ -512,7 +509,7 @@ def reload_model_weights(sd_model=None, info=None): if not shared.cmd_opts.lowvram and not shared.cmd_opts.medvram: sd_model.to(devices.device) - timer.record("move model to device") + timer.record("device move") print(f"Weights loaded in {timer.summary()}.") diff --git a/modules/ui.py b/modules/ui.py index 2d3744e53..fa5a87633 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -1444,7 +1444,7 @@ def create_ui(): with gr.Column(scale=6): settings_submit = gr.Button(value="Apply settings", variant='primary', elem_id="settings_submit") with gr.Column(): - restart_gradio = gr.Button(value='Reload UI', variant='primary', elem_id="settings_restart_gradio") + restart_gradio = gr.Button(value='Reload UI', variant='primary', elem_id="settings_restart_gradio", disabled=True) result = gr.HTML(elem_id="settings_result") diff --git a/modules/ui_extensions.py b/modules/ui_extensions.py index 7d021673e..14e29f832 100644 --- a/modules/ui_extensions.py +++ b/modules/ui_extensions.py @@ -279,7 +279,7 @@ def create_ui(): with gr.TabItem("Installed"): with gr.Row(elem_id="extensions_installed_top"): - apply = gr.Button(value="Apply and restart UI", variant="primary") + apply = gr.Button(value="Apply (restart required)", variant="primary") check = gr.Button(value="Check for updates") extensions_disabled_list = gr.Text(elem_id="extensions_disabled_list", visible=False).style(container=False) extensions_update_list = gr.Text(elem_id="extensions_update_list", visible=False).style(container=False) diff --git a/style.css b/style.css index 3eac2b176..8d488700d 100644 --- a/style.css +++ b/style.css @@ -58,9 +58,6 @@ margin-right: 0; } -.performance .vram { -} - #txt2img_generate, #img2img_generate { min-height: 4.5em; } @@ -305,9 +302,6 @@ input[type="range"]{ margin-bottom: -0.75em; } -#txt2img_negative_prompt, #img2img_negative_prompt{ -} - /* gradio 3.8 adds opacity to progressbar which makes it blink; disable it here */ .transition.opacity-20 { opacity: 1 !important; @@ -810,9 +804,6 @@ footer { overflow: visible; } -.gr-compact > *{ -} - .gr-compact .gr-block, .gr-compact .gr-form{ border: none; box-shadow: none; @@ -831,9 +822,6 @@ footer { border: none; } -[id*='img2img_copy_to_'] > button { -} - [id*='img2img_label_copy_to_'] { font-size: 1.0em; font-weight: bold; diff --git a/styles.csv b/styles.csv new file mode 100644 index 000000000..5f282702b --- /dev/null +++ b/styles.csv @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ui-screenshot.jpg b/ui-screenshot.jpg index 6cf9e28ab..e6cb54c6c 100644 Binary files a/ui-screenshot.jpg and b/ui-screenshot.jpg differ diff --git a/user.css b/user.css index 1ec047194..35f799f81 100644 --- a/user.css +++ b/user.css @@ -1,6 +1,6 @@ /* generic html tags */ html { font-size: 16px; } -body, button, input, select, textarea { font-family: "Segoe UI"; font-variant: small-caps; } +body, button, input, select, textarea { font-family: "Segoe UI"; font-variant: small-caps; overflow-x: hidden; } button { font-size: 1.2rem; } img { background-color: black; } input[type=range] { height: 14px; appearance: none; margin-top: 12px; min-width: 160px } @@ -9,6 +9,7 @@ input[type=range]::-webkit-slider-thumb { box-shadow: 2px 2px 3px #111111; borde ::-webkit-scrollbar { width: 12px; } ::-webkit-scrollbar-track { background: #333333; } ::-webkit-scrollbar-thumb { background-color: var(--highlight-color); border-radius: 2px; border-width: 0; box-shadow: 2px 2px 3px #111111; } +svg.feather.feather-image { display: none; } /* main gradio components by selector */ div.gradio-container.dark > div.w-full.flex.flex-col.min-h-screen > div { background-color: black; } @@ -52,7 +53,8 @@ div.gradio-container.dark > div.w-full.flex.flex-col.min-h-screen > div { backgr .tabs { background-color: black; } /* automatic style classes */ -.progressDiv .progress { background: var(--highlight-color); border-radius: 2px; } +.progressDiv { border-radius: 0; position: fixed; top: 40px; right: 30px; max-width: 250px; height: 32px; } +.progressDiv .progress { background: var(--highlight-color); line-height: 2rem; height: 32px; } .gallery-item { box-shadow: none !important; } .performance { color: #888; } .modalControls { background-color: #4E1400; } @@ -70,24 +72,27 @@ div.gradio-container.dark > div.w-full.flex.flex-col.min-h-screen > div { backgr #settings > div.flex-wrap { width: 15em; } #tab_extensions table { background-color: #222222; } #txt2img_cfg_scale { min-width: 200px; } +#txt2img_actions_column { min-width: 260px !important; max-width: 260px !important; } #txt2img_checkboxes, #img2img_checkboxes { background-color: transparent; } #txt2img_checkboxes, #img2img_checkboxes { margin-bottom: 0.2em; } #txt2img_gallery, #img2img_gallery, #extras_gallery { background: black; padding: 0; margin: 0; object-fit: contain; box-shadow: none; min-height: 0; } -#txt2img_generate, #img2img_generate, #txt2img_interrupt, #img2img_interrupt, #txt2img_skip, #img2img_skip { margin-left: 10px; min-height: 2rem; height: 2rem; max-width: 212px; margin-top: 15px; border: none; border-radius: 0; } -#txt2img_interrupt, #img2img_interrupt, #txt2img_skip, #img2img_skip { background-color: var(--inactive-color); } +#txt2img_generate, #img2img_generate { margin-left: 10px; min-height: 2rem; height: 2rem; margin-top: 15px; border: none; border-radius: 0; } +#txt2img_interrupt, #img2img_interrupt, #txt2img_skip, #img2img_skip { margin-left: 10px; min-height: 2rem; height: 2rem; max-width: 120px; margin-top: 15px; border: none; border-radius: 0; background-color: var(--inactive-color); margin-top: -84px; } #txt2img_neg_prompt > label > textarea { font-size: 1.2rem; background-color: black } #txt2img_progress_row > div { min-width: var(--left-column); max-width: var(--left-column); } #txt2img_prompt > label > textarea { font-size: 1.2rem; } -#txt2img_results, #img2img_results, #extras_results { background-color: black; } +#txt2img_results, #img2img_results, #extras_results { background-color: black; padding: 0; } #txt2img_seed_row { padding: 0; margin-top: 8px; } #txt2img_settings { min-width: var(--left-column); max-width: var(--left-column); background-color: #111111; padding-top: 16px; } #txt2img_subseed_row { padding: 0; margin-top: 16px; } #txt2img_subseed_show { min-width: 74px; padding: 8px 0 0 0 } #txt2img_subseed_strength { margin-top: 0; } -#txt2img_tools, #img2img_tools { margin-left: 8px; } +#txt2img_tools, #img2img_tools { margin-top: 8px; scale: 120%; margin-left: 30px; gap: 5px; max-width: 210px; } #txtimg_hr_finalres { max-width: 200px; } #txt2img_prompt, #txt2img_neg_prompt, #img2img_prompt, #img2img_neg_prompt { background-color: black; } #refresh_txt2img_styles, #refresh_img2img_styles, #open_folder_txt2img, #open_folder_img2img, #open_folder_extras, #footer, #style_pos_col, #style_neg_col, #roll_col, #save_zip_txt2img, #save_zip_img2img, #extras_upscaler_2, #extras_upscaler_2_visibility, #txt2img_res_switch_btn, #img2img_res_switch_btn, #txt2img_seed_resize_from_w, #txt2img_seed_resize_from_h, #txt2img_subseed_show, #txt2img_reuse_seed, #txt2img_reuse_subseed, #txt2img_tiling, #img2img_subseed_show { display: none; } +#div.gradio-container.dark { overflow-x: hidden; } /* custom elements overrides */ #steps-animation, #controlnet { border-width: 0; } + diff --git a/webui.py b/webui.py index 48acb83a1..de6accfe4 100644 --- a/webui.py +++ b/webui.py @@ -23,10 +23,7 @@ warnings.filterwarnings(action="ignore", category=DeprecationWarning, module="py startup_timer.record("import torch") import gradio -startup_timer.record("import gradio") - import ldm.modules.encoders.modules -startup_timer.record("import ldm") from modules import extra_networks, ui_extra_networks_checkpoints from modules import extra_networks_hypernet, ui_extra_networks_hypernets, ui_extra_networks_textual_inversion @@ -58,7 +55,7 @@ from modules import modelloader from modules.shared import cmd_opts import modules.hypernetworks.hypernetwork -startup_timer.record("other imports") +startup_timer.record("import libraries") if cmd_opts.server_name: @@ -111,7 +108,7 @@ def initialize(): modelloader.cleanup_models() modules.sd_models.setup_model() - startup_timer.record("list SD models") + startup_timer.record("list models") codeformer.setup_model(cmd_opts.codeformer_models_path) startup_timer.record("setup codeformer") @@ -134,18 +131,6 @@ def initialize(): modules.textual_inversion.textual_inversion.list_textual_inversion_templates() startup_timer.record("refresh textual inversion templates") - try: - modules.sd_models.load_model() - except Exception as e: - errors.display(e, "loading stable diffusion model") - print("", file=sys.stderr) - print("Stable diffusion model failed to load, exiting", file=sys.stderr) - exit(1) - startup_timer.record("load SD checkpoint") - - shared.opts.data["sd_model_checkpoint"] = shared.sd_model.sd_checkpoint_info.title - - shared.opts.onchange("sd_model_checkpoint", wrap_queued_call(lambda: modules.sd_models.reload_model_weights())) shared.opts.onchange("sd_vae", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False) shared.opts.onchange("sd_vae_as_default", wrap_queued_call(lambda: modules.sd_vae.reload_vae_weights()), call=False) shared.opts.onchange("temp_dir", ui_tempdir.on_tmpdir_changed) @@ -178,13 +163,29 @@ def initialize(): startup_timer.record("TLS") # make the program just exit at ctrl+c without waiting for anything - def sigint_handler(sig, frame): + def sigint_handler(_sig, _frame): print('Exiting') os._exit(0) signal.signal(signal.SIGINT, sigint_handler) +def load_model(): + shared.state.begin() + shared.state.job = 'load model' + try: + modules.sd_models.load_model() + except Exception as e: + errors.display(e, "loading stable diffusion model") + print("", file=sys.stderr) + print("Stable diffusion model failed to load, exiting", file=sys.stderr) + exit(1) + shared.opts.data["sd_model_checkpoint"] = shared.sd_model.sd_checkpoint_info.title + shared.opts.onchange("sd_model_checkpoint", wrap_queued_call(lambda: modules.sd_models.reload_model_weights())) + shared.state.end() + startup_timer.record("load checkpoint") + + def setup_middleware(app): app.middleware_stack = None # reset current middleware to allow modifying user provided list app.add_middleware(GZipMiddleware, minimum_size=1000) @@ -203,19 +204,9 @@ def create_api(app): return api -def wait_on_server(demo=None): - while 1: - time.sleep(0.5) - if shared.state.need_restart: - shared.state.need_restart = False - time.sleep(0.5) - demo.close() - time.sleep(0.5) - break - - def api_only(): initialize() + load_model() app = FastAPI() setup_middleware(app) @@ -231,110 +222,71 @@ def webui(): launch_api = cmd_opts.api initialize() - while 1: - if shared.opts.clean_temp_dir_at_start: - ui_tempdir.cleanup_tmpdr() - startup_timer.record("cleanup temp dir") + if shared.opts.clean_temp_dir_at_start: + ui_tempdir.cleanup_tmpdr() + startup_timer.record("cleanup temp dir") - modules.script_callbacks.before_ui_callback() - startup_timer.record("scripts before_ui_callback") + modules.script_callbacks.before_ui_callback() + startup_timer.record("scripts before_ui_callback") - shared.demo = modules.ui.create_ui() - startup_timer.record("create ui") + shared.demo = modules.ui.create_ui() + startup_timer.record("create ui") - if cmd_opts.gradio_queue: - shared.demo.queue(16) + if cmd_opts.gradio_queue: + shared.demo.queue(16) - gradio_auth_creds = [] - if cmd_opts.gradio_auth: - gradio_auth_creds += [x.strip() for x in cmd_opts.gradio_auth.strip('"').replace('\n', '').split(',') if x.strip()] - if cmd_opts.gradio_auth_path: - with open(cmd_opts.gradio_auth_path, 'r', encoding="utf8") as file: - for line in file.readlines(): - gradio_auth_creds += [x.strip() for x in line.split(',') if x.strip()] + gradio_auth_creds = [] + if cmd_opts.gradio_auth: + gradio_auth_creds += [x.strip() for x in cmd_opts.gradio_auth.strip('"').replace('\n', '').split(',') if x.strip()] + if cmd_opts.gradio_auth_path: + with open(cmd_opts.gradio_auth_path, 'r', encoding="utf8") as file: + for line in file.readlines(): + gradio_auth_creds += [x.strip() for x in line.split(',') if x.strip()] - app, local_url, share_url = shared.demo.launch( - share=cmd_opts.share, - server_name=server_name, - server_port=cmd_opts.port, - ssl_keyfile=cmd_opts.tls_keyfile, - ssl_certfile=cmd_opts.tls_certfile, - debug=cmd_opts.gradio_debug, - auth=[tuple(cred.split(':')) for cred in gradio_auth_creds] if gradio_auth_creds else None, - inbrowser=cmd_opts.autolaunch, - prevent_thread_lock=True, - ) - for dep in shared.demo.dependencies: - dep['show_progress'] = False # disable gradio css animation on component update + app, _local_url, _share_url = shared.demo.launch( + share=cmd_opts.share, + server_name=server_name, + server_port=cmd_opts.port, + ssl_keyfile=cmd_opts.tls_keyfile, + ssl_certfile=cmd_opts.tls_certfile, + debug=cmd_opts.gradio_debug, + auth=[tuple(cred.split(':')) for cred in gradio_auth_creds] if gradio_auth_creds else None, + inbrowser=cmd_opts.autolaunch, + prevent_thread_lock=True, + favicon_path='automatic.svg', + ) + for dep in shared.demo.dependencies: + dep['show_progress'] = False # disable gradio css animation on component update - # app is instance of FastAPI server - # shared.demo.server is instance of gradio class which inherits from uvicorn.Server - # shared.demo.config is instance of uvicorn.Config - # shared.demo.app is instance of ASGIApp + # app is instance of FastAPI server + # shared.demo.server is instance of gradio class which inherits from uvicorn.Server + # shared.demo.config is instance of uvicorn.Config + # shared.demo.app is instance of ASGIApp - cmd_opts.autolaunch = False + cmd_opts.autolaunch = False - startup_timer.record("gradio launch") + startup_timer.record("gradio launch") - # gradio uses a very open CORS policy via app.user_middleware, which makes it possible for - # an attacker to trick the user into opening a malicious HTML page, which makes a request to the - # running web ui and do whatever the attacker wants, including installing an extension and - # running its code. We disable this here. Suggested by RyotaK. - app.user_middleware = [x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware'] + app.user_middleware = [x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware'] - setup_middleware(app) + setup_middleware(app) - modules.progress.setup_progress_api(app) + modules.progress.setup_progress_api(app) - if launch_api: - create_api(app) + if launch_api: + create_api(app) - ui_extra_networks.add_pages_to_demo(app) + ui_extra_networks.add_pages_to_demo(app) - modules.script_callbacks.app_started_callback(shared.demo, app) - startup_timer.record("scripts app_started_callback") + modules.script_callbacks.app_started_callback(shared.demo, app) + startup_timer.record("scripts app_started_callback") - print(f"Startup time: {startup_timer.summary()}.") + load_model() - wait_on_server(shared.demo) - print('Restarting UI...') + print(f"Startup time: {startup_timer.summary()}.") - startup_timer.reset() - - sd_samplers.set_samplers() - - modules.script_callbacks.script_unloaded_callback() - extensions.list_extensions() - startup_timer.record("list extensions") - - modelloader.forbid_loaded_nonbuiltin_upscalers() - modules.scripts.reload_scripts() - startup_timer.record("load scripts") - - modules.script_callbacks.model_loaded_callback(shared.sd_model) - startup_timer.record("model loaded callback") - - modelloader.load_upscalers() - startup_timer.record("load upscalers") - - for module in [module for name, module in sys.modules.items() if name.startswith("modules.ui")]: - importlib.reload(module) - startup_timer.record("reload script modules") - - modules.sd_models.list_models() - startup_timer.record("list SD models") - - shared.reload_hypernetworks() - startup_timer.record("reload hypernetworks") - - ui_extra_networks.intialize() - ui_extra_networks.register_page(ui_extra_networks_textual_inversion.ExtraNetworksPageTextualInversion()) - ui_extra_networks.register_page(ui_extra_networks_hypernets.ExtraNetworksPageHypernetworks()) - ui_extra_networks.register_page(ui_extra_networks_checkpoints.ExtraNetworksPageCheckpoints()) - - extra_networks.initialize() - extra_networks.register_extra_network(extra_networks_hypernet.ExtraNetworkHypernet()) - startup_timer.record("initialize extra networks") + while True: + time.sleep(0.1) if __name__ == "__main__": diff --git a/wiki b/wiki index e84c0ef0e..d2592368d 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit e84c0ef0e47fd270a693e145c8815f8dc68b1244 +Subproject commit d2592368d0b530491946f7f4624f253f1313b3a2