Compare commits
37 Commits
Author | SHA1 | Date | |
---|---|---|---|
1010837cfd | |||
aec7e6d32e | |||
bb0f7cd1cd | |||
5dd92b1d3f | |||
7548f7cdbb | |||
44da3d26f3 | |||
7c01c48297 | |||
7826870d99 | |||
bdb6649722 | |||
31ee73c5eb | |||
0fd706f392 | |||
8907dabd4c | |||
1496d6ec51 | |||
d1a45ed9ac | |||
f73d28ac10 | |||
1b7af75d4e | |||
ed0d78bf73 | |||
046e2acae1 | |||
b6efa71efc | |||
3bb835b5e1 | |||
fbeecda38c | |||
942904186a | |||
737a81570a | |||
3691aeb8e1 | |||
32d8f4d24b | |||
30ccd35dd3 | |||
11265c4034 | |||
8acff43028 | |||
660aa4f4ab | |||
1384c2f1bc | |||
459b9428d4 | |||
a82f16958b | |||
b9f436812b | |||
88e3831bc6 | |||
2a597fcad7 | |||
6158f49400 | |||
9dd819e193 |
14
CHANGES.md
@ -3,22 +3,28 @@
|
|||||||
## v2.5
|
## v2.5
|
||||||
### Major Changes
|
### Major Changes
|
||||||
- **Nearly twice as fast** - significantly faster speed of image generation. We're now pretty close to automatic1111's speed. Code contributions are welcome to make our project even faster: https://github.com/easydiffusion/sdkit/#is-it-fast
|
- **Nearly twice as fast** - significantly faster speed of image generation. We're now pretty close to automatic1111's speed. Code contributions are welcome to make our project even faster: https://github.com/easydiffusion/sdkit/#is-it-fast
|
||||||
|
- **Mac M1/M2 support** - Experimental support for Mac M1/M2. Thanks @michaelgallacher, @JeLuf and vishae.
|
||||||
- **Full support for Stable Diffusion 2.1 (including CPU)** - supports loading v1.4 or v2.0 or v2.1 models seamlessly. No need to enable "Test SD2", and no need to add `sd2_` to your SD 2.0 model file names. Works on CPU as well.
|
- **Full support for Stable Diffusion 2.1 (including CPU)** - supports loading v1.4 or v2.0 or v2.1 models seamlessly. No need to enable "Test SD2", and no need to add `sd2_` to your SD 2.0 model file names. Works on CPU as well.
|
||||||
- **Memory optimized Stable Diffusion 2.1** - you can now use Stable Diffusion 2.1 models, with the same low VRAM optimizations that we've always had for SD 1.4. Please note, the SD 2.0 and 2.1 models require more GPU and System RAM, as compared to the SD 1.4 and 1.5 models.
|
- **Memory optimized Stable Diffusion 2.1** - you can now use Stable Diffusion 2.1 models, with the same low VRAM optimizations that we've always had for SD 1.4. Please note, the SD 2.0 and 2.1 models require more GPU and System RAM, as compared to the SD 1.4 and 1.5 models.
|
||||||
- **11 new samplers!** - explore the new samplers, some of which can generate great images in less than 10 inference steps! We've added the Karras and UniPC samplers.
|
- **11 new samplers!** - explore the new samplers, some of which can generate great images in less than 10 inference steps! We've added the Karras and UniPC samplers. Thanks @Schorny for the UniPC samplers.
|
||||||
- **Model Merging** - You can now merge two models (`.ckpt` or `.safetensors`) and output `.ckpt` or `.safetensors` models, optionally in `fp16` precision. Details: https://github.com/cmdr2/stable-diffusion-ui/wiki/Model-Merging
|
- **Model Merging** - You can now merge two models (`.ckpt` or `.safetensors`) and output `.ckpt` or `.safetensors` models, optionally in `fp16` precision. Details: https://github.com/cmdr2/stable-diffusion-ui/wiki/Model-Merging . Thanks @JeLuf.
|
||||||
- **Fast loading/unloading of VAEs** - No longer needs to reload the entire Stable Diffusion model, each time you change the VAE
|
- **Fast loading/unloading of VAEs** - No longer needs to reload the entire Stable Diffusion model, each time you change the VAE
|
||||||
- **Database of known models** - automatically picks the right configuration for known models. E.g. we automatically detect and apply "v" parameterization (required for some SD 2.0 models), and "fp32" attention precision (required for some SD 2.1 models).
|
- **Database of known models** - automatically picks the right configuration for known models. E.g. we automatically detect and apply "v" parameterization (required for some SD 2.0 models), and "fp32" attention precision (required for some SD 2.1 models).
|
||||||
- **Color correction for img2img** - an option to preserve the color profile (histogram) of the initial image. This is especially useful if you're getting red-tinted images after inpainting/masking.
|
- **Color correction for img2img** - an option to preserve the color profile (histogram) of the initial image. This is especially useful if you're getting red-tinted images after inpainting/masking.
|
||||||
- **Three GPU Memory Usage Settings** - `High` (fastest, maximum VRAM usage), `Balanced` (default - almost as fast, significantly lower VRAM usage), `Low` (slowest, very low VRAM usage). The `Low` setting is applied automatically for GPUs with less than 4 GB of VRAM.
|
- **Three GPU Memory Usage Settings** - `High` (fastest, maximum VRAM usage), `Balanced` (default - almost as fast, significantly lower VRAM usage), `Low` (slowest, very low VRAM usage). The `Low` setting is applied automatically for GPUs with less than 4 GB of VRAM.
|
||||||
- **Find models in sub-folders** - This allows you to organize your models into sub-folders inside `models/stable-diffusion`, instead of keeping them all in a single folder.
|
- **Find models in sub-folders** - This allows you to organize your models into sub-folders inside `models/stable-diffusion`, instead of keeping them all in a single folder. Thanks @patriceac and @ogmaresca.
|
||||||
- **Save metadata as JSON** - You can now save the metadata files as either text or json files (choose in the Settings tab).
|
- **Custom Modifier Categories** - Ability to create custom modifiers with thumbnails, and custom categories (and hierarchy of categories). Details: https://github.com/cmdr2/stable-diffusion-ui/wiki/Custom-Modifiers . Thanks @ogmaresca.
|
||||||
|
- **Embed metadata, or save as TXT/JSON** - You can now embed the metadata directly into the images, or save them as text or json files (choose in the Settings tab). Thanks @patriceac.
|
||||||
- **Major rewrite of the code** - Most of the codebase has been reorganized and rewritten, to make it more manageable and easier for new developers to contribute features. We've separated our core engine into a new project called `sdkit`, which allows anyone to easily integrate Stable Diffusion (and related modules like GFPGAN etc) into their programming projects (via a simple `pip install sdkit`): https://github.com/easydiffusion/sdkit/
|
- **Major rewrite of the code** - Most of the codebase has been reorganized and rewritten, to make it more manageable and easier for new developers to contribute features. We've separated our core engine into a new project called `sdkit`, which allows anyone to easily integrate Stable Diffusion (and related modules like GFPGAN etc) into their programming projects (via a simple `pip install sdkit`): https://github.com/easydiffusion/sdkit/
|
||||||
- **Name change** - Last, and probably the least, the UI is now called "Easy Diffusion". It indicates the focus of this project - an easy way for people to play with Stable Diffusion.
|
- **Name change** - Last, and probably the least, the UI is now called "Easy Diffusion". It indicates the focus of this project - an easy way for people to play with Stable Diffusion.
|
||||||
|
|
||||||
Our focus continues to remain on an easy installation experience, and an easy user-interface. While still remaining pretty powerful, in terms of features and speed.
|
Our focus continues to remain on an easy installation experience, and an easy user-interface. While still remaining pretty powerful, in terms of features and speed.
|
||||||
|
|
||||||
### Detailed changelog
|
### Detailed changelog
|
||||||
|
* 2.5.24 - 11 Mar 2023 - Button to load an image mask from a file.
|
||||||
|
* 2.5.24 - 10 Mar 2023 - Logo change. Image credit: @lazlo_vii.
|
||||||
|
* 2.5.23 - 8 Mar 2023 - Experimental support for Mac M1/M2. Thanks @michaelgallacher, @JeLuf and vishae!
|
||||||
|
* 2.5.23 - 8 Mar 2023 - Ability to create custom modifiers with thumbnails, and custom categories (and hierarchy of categories). More details - https://github.com/cmdr2/stable-diffusion-ui/wiki/Custom-Modifiers . Thanks @ogmaresca.
|
||||||
* 2.5.22 - 28 Feb 2023 - Minor styling changes to UI buttons, and the models dropdown.
|
* 2.5.22 - 28 Feb 2023 - Minor styling changes to UI buttons, and the models dropdown.
|
||||||
* 2.5.22 - 28 Feb 2023 - Lots of UI-related bug fixes. Thanks @patriceac.
|
* 2.5.22 - 28 Feb 2023 - Lots of UI-related bug fixes. Thanks @patriceac.
|
||||||
* 2.5.21 - 22 Feb 2023 - An option to control the size of the image thumbnails. You can use the `Display options` in the top-right corner to change this. Thanks @JeLuf.
|
* 2.5.21 - 22 Feb 2023 - An option to control the size of the image thumbnails. You can use the `Display options` in the top-right corner to change this. Thanks @JeLuf.
|
||||||
|
1
NSIS/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
*.exe
|
BIN
NSIS/cyborg_flower_girl.bmp
Normal file
After Width: | Height: | Size: 565 KiB |
BIN
NSIS/cyborg_flower_girl.ico
Normal file
After Width: | Height: | Size: 223 KiB |
BIN
NSIS/cyborg_flower_girl_icon.png
Normal file
After Width: | Height: | Size: 454 KiB |
BIN
NSIS/cyborg_flower_girl_orig.jpeg
Normal file
After Width: | Height: | Size: 46 KiB |
1
NSIS/nsisconf.nsh
Normal file
@ -0,0 +1 @@
|
|||||||
|
!define EXISTING_INSTALLATION_DIR "D:\path\to\installed\easy-diffusion"
|
@ -1,20 +1,24 @@
|
|||||||
; Script generated by the HM NIS Edit Script Wizard.
|
; Script generated by the HM NIS Edit Script Wizard.
|
||||||
|
|
||||||
Target x86-unicode
|
Target amd64-unicode
|
||||||
Unicode True
|
Unicode True
|
||||||
!AddPluginDir /x86-unicode "."
|
SetCompressor /FINAL lzma
|
||||||
|
RequestExecutionLevel user
|
||||||
|
!AddPluginDir /amd64-unicode "."
|
||||||
; HM NIS Edit Wizard helper defines
|
; HM NIS Edit Wizard helper defines
|
||||||
!define PRODUCT_NAME "Stable Diffusion UI"
|
!define PRODUCT_NAME "Easy Diffusion"
|
||||||
!define PRODUCT_VERSION "Installer 2.35"
|
!define PRODUCT_VERSION "2.5"
|
||||||
!define PRODUCT_PUBLISHER "cmdr2 and contributors"
|
!define PRODUCT_PUBLISHER "cmdr2 and contributors"
|
||||||
!define PRODUCT_WEB_SITE "https://stable-diffusion-ui.github.io"
|
!define PRODUCT_WEB_SITE "https://stable-diffusion-ui.github.io"
|
||||||
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Cmdr2\App Paths\installer.exe"
|
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Easy Diffusion\App Paths\installer.exe"
|
||||||
|
|
||||||
; MUI 1.67 compatible ------
|
; MUI 1.67 compatible ------
|
||||||
!include "MUI.nsh"
|
!include "MUI.nsh"
|
||||||
!include "LogicLib.nsh"
|
!include "LogicLib.nsh"
|
||||||
!include "nsDialogs.nsh"
|
!include "nsDialogs.nsh"
|
||||||
|
|
||||||
|
!include "nsisconf.nsh"
|
||||||
|
|
||||||
Var Dialog
|
Var Dialog
|
||||||
Var Label
|
Var Label
|
||||||
Var Button
|
Var Button
|
||||||
@ -106,7 +110,7 @@ Function DirectoryLeave
|
|||||||
StrCpy $5 $INSTDIR 3
|
StrCpy $5 $INSTDIR 3
|
||||||
System::Call 'Kernel32::GetVolumeInformation(t "$5",t,i ${NSIS_MAX_STRLEN},*i,*i,*i,t.r1,i ${NSIS_MAX_STRLEN})i.r0'
|
System::Call 'Kernel32::GetVolumeInformation(t "$5",t,i ${NSIS_MAX_STRLEN},*i,*i,*i,t.r1,i ${NSIS_MAX_STRLEN})i.r0'
|
||||||
${If} $0 <> 0
|
${If} $0 <> 0
|
||||||
${AndIf} $1 == "NTFS"
|
${AndIf} $1 != "NTFS"
|
||||||
MessageBox mb_ok "$5 has filesystem type '$1'.$\nOnly NTFS filesystems are supported.$\nPlease choose a different drive."
|
MessageBox mb_ok "$5 has filesystem type '$1'.$\nOnly NTFS filesystems are supported.$\nPlease choose a different drive."
|
||||||
Abort
|
Abort
|
||||||
${EndIf}
|
${EndIf}
|
||||||
@ -140,7 +144,7 @@ Function MediaPackDialog
|
|||||||
Abort
|
Abort
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
${NSD_CreateLabel} 0 0 100% 48u "The Windows Media Feature Pack is missing on this computer. It is required for the Stable Diffusion UI.$\nYou can continue the installation after installing the Windows Media Feature Pack."
|
${NSD_CreateLabel} 0 0 100% 48u "The Windows Media Feature Pack is missing on this computer. It is required for Easy Diffusion.$\nYou can continue the installation after installing the Windows Media Feature Pack."
|
||||||
Pop $Label
|
Pop $Label
|
||||||
|
|
||||||
${NSD_CreateButton} 10% 49u 80% 12u "Download Meda Feature Pack from Microsoft"
|
${NSD_CreateButton} 10% 49u 80% 12u "Download Meda Feature Pack from Microsoft"
|
||||||
@ -157,12 +161,12 @@ FunctionEnd
|
|||||||
; MUI Settings
|
; MUI Settings
|
||||||
;---------------------------------------------------------------------------------------------------------
|
;---------------------------------------------------------------------------------------------------------
|
||||||
!define MUI_ABORTWARNING
|
!define MUI_ABORTWARNING
|
||||||
!define MUI_ICON "sd.ico"
|
!define MUI_ICON "cyborg_flower_girl.ico"
|
||||||
|
|
||||||
!define MUI_WELCOMEFINISHPAGE_BITMAP "astro.bmp"
|
!define MUI_WELCOMEFINISHPAGE_BITMAP "cyborg_flower_girl.bmp"
|
||||||
|
|
||||||
; Welcome page
|
; Welcome page
|
||||||
!define MUI_WELCOMEPAGE_TEXT "This installer will guide you through the installation of Stable Diffusion UI.$\n$\n\
|
!define MUI_WELCOMEPAGE_TEXT "This installer will guide you through the installation of Easy Diffusion.$\n$\n\
|
||||||
Click Next to continue."
|
Click Next to continue."
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
Page custom MediaPackDialog
|
Page custom MediaPackDialog
|
||||||
@ -188,8 +192,8 @@ Page custom MediaPackDialog
|
|||||||
;---------------------------------------------------------------------------------------------------------
|
;---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
|
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
|
||||||
OutFile "Install Stable Diffusion UI.exe"
|
OutFile "Install Easy Diffusion.exe"
|
||||||
InstallDir "C:\Stable-Diffusion-UI\"
|
InstallDir "C:\EasyDiffusion\"
|
||||||
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
|
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
|
||||||
ShowInstDetails show
|
ShowInstDetails show
|
||||||
|
|
||||||
@ -200,15 +204,40 @@ Section "MainSection" SEC01
|
|||||||
File "..\CreativeML Open RAIL-M License"
|
File "..\CreativeML Open RAIL-M License"
|
||||||
File "..\How to install and run.txt"
|
File "..\How to install and run.txt"
|
||||||
File "..\LICENSE"
|
File "..\LICENSE"
|
||||||
File "..\Start Stable Diffusion UI.cmd"
|
File "..\scripts\Start Stable Diffusion UI.cmd"
|
||||||
|
File /r "${EXISTING_INSTALLATION_DIR}\installer_files"
|
||||||
|
File /r "${EXISTING_INSTALLATION_DIR}\profile"
|
||||||
|
File /r "${EXISTING_INSTALLATION_DIR}\sd-ui-files"
|
||||||
SetOutPath "$INSTDIR\scripts"
|
SetOutPath "$INSTDIR\scripts"
|
||||||
File "..\scripts\bootstrap.bat"
|
File "${EXISTING_INSTALLATION_DIR}\scripts\install_status.txt"
|
||||||
File "..\scripts\install_status.txt"
|
|
||||||
File "..\scripts\on_env_start.bat"
|
File "..\scripts\on_env_start.bat"
|
||||||
File "C:\windows\system32\curl.exe"
|
File "C:\windows\system32\curl.exe"
|
||||||
CreateDirectory "$INSTDIR\profile"
|
CreateDirectory "$INSTDIR\models"
|
||||||
CreateDirectory "$SMPROGRAMS\Stable Diffusion UI"
|
CreateDirectory "$INSTDIR\models\stable-diffusion"
|
||||||
CreateShortCut "$SMPROGRAMS\Stable Diffusion UI\Start Stable Diffusion UI.lnk" "$INSTDIR\Start Stable Diffusion UI.cmd"
|
CreateDirectory "$INSTDIR\models\gfpgan"
|
||||||
|
CreateDirectory "$INSTDIR\models\realesrgan"
|
||||||
|
CreateDirectory "$INSTDIR\models\vae"
|
||||||
|
CreateDirectory "$SMPROGRAMS\Easy Diffusion"
|
||||||
|
CreateShortCut "$SMPROGRAMS\Easy Diffusion\Easy Diffusion.lnk" "$INSTDIR\Start Stable Diffusion UI.cmd"
|
||||||
|
|
||||||
|
DetailPrint 'Downloading the Stable Diffusion 1.4 model...'
|
||||||
|
NScurl::http get "https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt" "$INSTDIR\models\stable-diffusion\sd-v1-4.ckpt" /CANCEL /INSIST /END
|
||||||
|
|
||||||
|
DetailPrint 'Downloading the GFPGAN model...'
|
||||||
|
NScurl::http get "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth" "$INSTDIR\models\gfpgan\GFPGANv1.3.pth" /CANCEL /INSIST /END
|
||||||
|
|
||||||
|
DetailPrint 'Downloading the RealESRGAN_x4plus model...'
|
||||||
|
NScurl::http get "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth" "$INSTDIR\models\realesrgan\RealESRGAN_x4plus.pth" /CANCEL /INSIST /END
|
||||||
|
|
||||||
|
DetailPrint 'Downloading the RealESRGAN_x4plus_anime model...'
|
||||||
|
NScurl::http get "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth" "$INSTDIR\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth" /CANCEL /INSIST /END
|
||||||
|
|
||||||
|
DetailPrint 'Downloading the default VAE (sd-vae-ft-mse-original) model...'
|
||||||
|
NScurl::http get "https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.ckpt" "$INSTDIR\models\vae\vae-ft-mse-840000-ema-pruned.ckpt" /CANCEL /INSIST /END
|
||||||
|
|
||||||
|
DetailPrint 'Downloading the CLIP model (clip-vit-large-patch14)...'
|
||||||
|
NScurl::http get "https://huggingface.co/openai/clip-vit-large-patch14/resolve/8d052a0f05efbaefbc9e8786ba291cfdf93e5bff/pytorch_model.bin" "$INSTDIR\profile\.cache\huggingface\hub\models--openai--clip-vit-large-patch14\snapshots\8d052a0f05efbaefbc9e8786ba291cfdf93e5bff\pytorch_model.bin" /CANCEL /INSIST /END
|
||||||
|
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
|
||||||
;---------------------------------------------------------------------------------------------------------
|
;---------------------------------------------------------------------------------------------------------
|
||||||
@ -254,7 +283,7 @@ Function .onInit
|
|||||||
|
|
||||||
${If} $4 < "8000"
|
${If} $4 < "8000"
|
||||||
MessageBox MB_OK|MB_ICONEXCLAMATION "Warning!$\n$\nYour system has less than 8GB of memory (RAM).$\n$\n\
|
MessageBox MB_OK|MB_ICONEXCLAMATION "Warning!$\n$\nYour system has less than 8GB of memory (RAM).$\n$\n\
|
||||||
You can still try to install Stable Diffusion UI,$\nbut it might have problems to start, or run$\nvery slowly."
|
You can still try to install Easy Diffusion,$\nbut it might have problems to start, or run$\nvery slowly."
|
||||||
${EndIf}
|
${EndIf}
|
||||||
|
|
||||||
FunctionEnd
|
FunctionEnd
|
||||||
|
@ -25,15 +25,12 @@ if exist "on_sd_start.bat" (
|
|||||||
@rem set legacy installer's PATH, if it exists
|
@rem set legacy installer's PATH, if it exists
|
||||||
if exist "installer" set PATH=%cd%\installer;%cd%\installer\Library\bin;%cd%\installer\Scripts;%cd%\installer\Library\usr\bin;%PATH%
|
if exist "installer" set PATH=%cd%\installer;%cd%\installer\Library\bin;%cd%\installer\Scripts;%cd%\installer\Library\usr\bin;%PATH%
|
||||||
|
|
||||||
@rem Setup the packages required for the installer
|
|
||||||
call scripts\bootstrap.bat
|
|
||||||
|
|
||||||
@rem set new installer's PATH, if it downloaded any packages
|
@rem set new installer's PATH, if it downloaded any packages
|
||||||
if exist "installer_files\env" set PATH=%cd%\installer_files\env;%cd%\installer_files\env\Library\bin;%cd%\installer_files\env\Scripts;%cd%\installer_files\Library\usr\bin;%PATH%
|
if exist "installer_files\env" set PATH=%cd%\installer_files\env;%cd%\installer_files\env\Library\bin;%cd%\installer_files\env\Scripts;%cd%\installer_files\Library\usr\bin;%PATH%
|
||||||
|
|
||||||
set PYTHONPATH=%cd%\installer;%cd%\installer_files\env
|
set PYTHONPATH=%cd%\installer;%cd%\installer_files\env
|
||||||
|
|
||||||
@rem Test the bootstrap
|
@rem Test the core requirements
|
||||||
call where git
|
call where git
|
||||||
call git --version
|
call git --version
|
||||||
|
|
||||||
|
@ -30,9 +30,6 @@ if ! which tar; then fail "'tar' not found. Please install tar."; fi
|
|||||||
if ! which bzip2; then fail "'bzip2' not found. Please install bzip2."; fi
|
if ! which bzip2; then fail "'bzip2' not found. Please install bzip2."; fi
|
||||||
|
|
||||||
if pwd | grep ' '; then fail "The installation directory's path contains a space character. Conda will fail to install. Please change the directory."; fi
|
if pwd | grep ' '; then fail "The installation directory's path contains a space character. Conda will fail to install. Please change the directory."; fi
|
||||||
if [ -f /proc/cpuinfo ]; then
|
|
||||||
if ! cat /proc/cpuinfo | grep avx | uniq; then fail "Your CPU doesn't support AVX."; fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# https://mamba.readthedocs.io/en/latest/installation.html
|
# https://mamba.readthedocs.io/en/latest/installation.html
|
||||||
if [ "$OS_NAME" == "linux" ] && [ "$OS_ARCH" == "arm64" ]; then OS_ARCH="aarch64"; fi
|
if [ "$OS_NAME" == "linux" ] && [ "$OS_ARCH" == "arm64" ]; then OS_ARCH="aarch64"; fi
|
||||||
|
0
scripts/install_status.txt
Normal file
@ -52,7 +52,6 @@ if "%update_branch%"=="" (
|
|||||||
|
|
||||||
@xcopy sd-ui-files\ui ui /s /i /Y /q
|
@xcopy sd-ui-files\ui ui /s /i /Y /q
|
||||||
@copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y
|
@copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y
|
||||||
@copy sd-ui-files\scripts\bootstrap.bat scripts\ /Y
|
|
||||||
@copy sd-ui-files\scripts\check_modules.py scripts\ /Y
|
@copy sd-ui-files\scripts\check_modules.py scripts\ /Y
|
||||||
@copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y
|
@copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y
|
||||||
@copy "sd-ui-files\scripts\Developer Console.cmd" . /Y
|
@copy "sd-ui-files\scripts\Developer Console.cmd" . /Y
|
||||||
|
@ -95,7 +95,7 @@ if "%ERRORLEVEL%" EQU "0" (
|
|||||||
set PYTHONNOUSERSITE=1
|
set PYTHONNOUSERSITE=1
|
||||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||||
|
|
||||||
call python -m pip install --upgrade sdkit==1.0.43 -q || (
|
call python -m pip install --upgrade sdkit==1.0.47 -q || (
|
||||||
echo "Error updating sdkit"
|
echo "Error updating sdkit"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -106,7 +106,7 @@ if "%ERRORLEVEL%" EQU "0" (
|
|||||||
set PYTHONNOUSERSITE=1
|
set PYTHONNOUSERSITE=1
|
||||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||||
|
|
||||||
call python -m pip install sdkit==1.0.43 || (
|
call python -m pip install sdkit==1.0.47 || (
|
||||||
echo "Error installing sdkit. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
echo "Error installing sdkit. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
||||||
pause
|
pause
|
||||||
exit /b
|
exit /b
|
||||||
|
@ -81,7 +81,7 @@ if python ../scripts/check_modules.py sdkit sdkit.models ldm transformers numpy
|
|||||||
export PYTHONNOUSERSITE=1
|
export PYTHONNOUSERSITE=1
|
||||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||||
|
|
||||||
python -m pip install --upgrade sdkit==1.0.43 -q
|
python -m pip install --upgrade sdkit==1.0.47 -q
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "Installing sdkit: https://pypi.org/project/sdkit/"
|
echo "Installing sdkit: https://pypi.org/project/sdkit/"
|
||||||
@ -89,7 +89,7 @@ else
|
|||||||
export PYTHONNOUSERSITE=1
|
export PYTHONNOUSERSITE=1
|
||||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||||
|
|
||||||
if python -m pip install sdkit==1.0.43 ; then
|
if python -m pip install sdkit==1.0.47 ; then
|
||||||
echo "Installed."
|
echo "Installed."
|
||||||
else
|
else
|
||||||
fail "sdkit install failed"
|
fail "sdkit install failed"
|
||||||
@ -285,6 +285,7 @@ printf "\n\nEasy Diffusion installation complete, starting the server!\n\n"
|
|||||||
|
|
||||||
SD_PATH=`pwd`
|
SD_PATH=`pwd`
|
||||||
|
|
||||||
|
export PYTORCH_ENABLE_MPS_FALLBACK=1
|
||||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||||
echo "PYTHONPATH=$PYTHONPATH"
|
echo "PYTHONPATH=$PYTHONPATH"
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import json
|
|||||||
import traceback
|
import traceback
|
||||||
import logging
|
import logging
|
||||||
import shlex
|
import shlex
|
||||||
|
import urllib
|
||||||
from rich.logging import RichHandler
|
from rich.logging import RichHandler
|
||||||
|
|
||||||
from sdkit.utils import log as sdkit_log # hack, so we can overwrite the log config
|
from sdkit.utils import log as sdkit_log # hack, so we can overwrite the log config
|
||||||
@ -54,6 +55,10 @@ APP_CONFIG_DEFAULTS = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IMAGE_EXTENSIONS = [".png", ".apng", ".jpg", ".jpeg", ".jfif", ".pjpeg", ".pjp", ".jxl", ".gif", ".webp", ".avif", ".svg"]
|
||||||
|
CUSTOM_MODIFIERS_DIR = os.path.abspath(os.path.join(SD_DIR, "..", "modifiers"))
|
||||||
|
CUSTOM_MODIFIERS_PORTRAIT_EXTENSIONS=[".portrait", "_portrait", " portrait", "-portrait"]
|
||||||
|
CUSTOM_MODIFIERS_LANDSCAPE_EXTENSIONS=[".landscape", "_landscape", " landscape", "-landscape"]
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
os.makedirs(USER_UI_PLUGINS_DIR, exist_ok=True)
|
os.makedirs(USER_UI_PLUGINS_DIR, exist_ok=True)
|
||||||
@ -234,3 +239,90 @@ def open_browser():
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
webbrowser.open(f"http://localhost:{port}")
|
webbrowser.open(f"http://localhost:{port}")
|
||||||
|
|
||||||
|
def get_image_modifiers():
|
||||||
|
modifiers_json_path = os.path.join(SD_UI_DIR, "modifiers.json")
|
||||||
|
|
||||||
|
modifier_categories = {}
|
||||||
|
original_category_order=[]
|
||||||
|
with open(modifiers_json_path, "r", encoding="utf-8") as f:
|
||||||
|
modifiers_file = json.load(f)
|
||||||
|
|
||||||
|
# The trailing slash is needed to support symlinks
|
||||||
|
if not os.path.isdir(f"{CUSTOM_MODIFIERS_DIR}/"):
|
||||||
|
return modifiers_file
|
||||||
|
|
||||||
|
# convert modifiers from a list of objects to a dict of dicts
|
||||||
|
for category_item in modifiers_file:
|
||||||
|
category_name = category_item['category']
|
||||||
|
original_category_order.append(category_name)
|
||||||
|
category = {}
|
||||||
|
for modifier_item in category_item['modifiers']:
|
||||||
|
modifier = {}
|
||||||
|
for preview_item in modifier_item['previews']:
|
||||||
|
modifier[preview_item['name']] = preview_item['path']
|
||||||
|
category[modifier_item['modifier']] = modifier
|
||||||
|
modifier_categories[category_name] = category
|
||||||
|
|
||||||
|
def scan_directory(directory_path: str, category_name="Modifiers"):
|
||||||
|
for entry in os.scandir(directory_path):
|
||||||
|
if entry.is_file():
|
||||||
|
file_extension = list(filter(lambda e: entry.name.endswith(e), IMAGE_EXTENSIONS))
|
||||||
|
if len(file_extension) == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
modifier_name = entry.name[: -len(file_extension[0])]
|
||||||
|
modifier_path = f"custom/{entry.path[len(CUSTOM_MODIFIERS_DIR) + 1:]}"
|
||||||
|
# URL encode path segments
|
||||||
|
modifier_path = "/".join(map(lambda segment: urllib.parse.quote(segment), modifier_path.split("/")))
|
||||||
|
is_portrait = True
|
||||||
|
is_landscape = True
|
||||||
|
|
||||||
|
portrait_extension = list(filter(lambda e: modifier_name.lower().endswith(e), CUSTOM_MODIFIERS_PORTRAIT_EXTENSIONS))
|
||||||
|
landscape_extension = list(filter(lambda e: modifier_name.lower().endswith(e), CUSTOM_MODIFIERS_LANDSCAPE_EXTENSIONS))
|
||||||
|
|
||||||
|
if len(portrait_extension) > 0:
|
||||||
|
is_landscape = False
|
||||||
|
modifier_name = modifier_name[: -len(portrait_extension[0])]
|
||||||
|
elif len(landscape_extension) > 0:
|
||||||
|
is_portrait = False
|
||||||
|
modifier_name = modifier_name[: -len(landscape_extension[0])]
|
||||||
|
|
||||||
|
if (category_name not in modifier_categories):
|
||||||
|
modifier_categories[category_name] = {}
|
||||||
|
|
||||||
|
category = modifier_categories[category_name]
|
||||||
|
|
||||||
|
if (modifier_name not in category):
|
||||||
|
category[modifier_name] = {}
|
||||||
|
|
||||||
|
if (is_portrait or "portrait" not in category[modifier_name]):
|
||||||
|
category[modifier_name]["portrait"] = modifier_path
|
||||||
|
|
||||||
|
if (is_landscape or "landscape" not in category[modifier_name]):
|
||||||
|
category[modifier_name]["landscape"] = modifier_path
|
||||||
|
elif entry.is_dir():
|
||||||
|
scan_directory(
|
||||||
|
entry.path,
|
||||||
|
entry.name if directory_path==CUSTOM_MODIFIERS_DIR else f"{category_name}/{entry.name}",
|
||||||
|
)
|
||||||
|
|
||||||
|
scan_directory(CUSTOM_MODIFIERS_DIR)
|
||||||
|
|
||||||
|
custom_categories = sorted(
|
||||||
|
[cn for cn in modifier_categories.keys() if cn not in original_category_order],
|
||||||
|
key=str.casefold,
|
||||||
|
)
|
||||||
|
|
||||||
|
# convert the modifiers back into a list of objects
|
||||||
|
modifier_categories_list = []
|
||||||
|
for category_name in [*original_category_order, *custom_categories]:
|
||||||
|
category = { 'category': category_name, 'modifiers': [] }
|
||||||
|
for modifier_name in sorted(modifier_categories[category_name].keys(), key=str.casefold):
|
||||||
|
modifier = { 'modifier': modifier_name, 'previews': [] }
|
||||||
|
for preview_name, preview_path in modifier_categories[category_name][modifier_name].items():
|
||||||
|
modifier['previews'].append({ 'name': preview_name, 'path': preview_path })
|
||||||
|
category['modifiers'].append(modifier)
|
||||||
|
modifier_categories_list.append(category)
|
||||||
|
|
||||||
|
return modifier_categories_list
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import torch
|
import torch
|
||||||
import traceback
|
import traceback
|
||||||
import re
|
import re
|
||||||
@ -21,20 +22,20 @@ mem_free_threshold = 0
|
|||||||
|
|
||||||
def get_device_delta(render_devices, active_devices):
|
def get_device_delta(render_devices, active_devices):
|
||||||
"""
|
"""
|
||||||
render_devices: 'cpu', or 'auto' or ['cuda:N'...]
|
render_devices: 'cpu', or 'auto', or 'mps' or ['cuda:N'...]
|
||||||
active_devices: ['cpu', 'cuda:N'...]
|
active_devices: ['cpu', 'mps', 'cuda:N'...]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if render_devices in ("cpu", "auto"):
|
if render_devices in ("cpu", "auto", "mps"):
|
||||||
render_devices = [render_devices]
|
render_devices = [render_devices]
|
||||||
elif render_devices is not None:
|
elif render_devices is not None:
|
||||||
if isinstance(render_devices, str):
|
if isinstance(render_devices, str):
|
||||||
render_devices = [render_devices]
|
render_devices = [render_devices]
|
||||||
if isinstance(render_devices, list) and len(render_devices) > 0:
|
if isinstance(render_devices, list) and len(render_devices) > 0:
|
||||||
render_devices = list(filter(lambda x: x.startswith("cuda:"), render_devices))
|
render_devices = list(filter(lambda x: x.startswith("cuda:") or x == "mps", render_devices))
|
||||||
if len(render_devices) == 0:
|
if len(render_devices) == 0:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Invalid render_devices value in config.json. Valid: {"render_devices": ["cuda:0", "cuda:1"...]}, or {"render_devices": "cpu"} or {"render_devices": "auto"}'
|
'Invalid render_devices value in config.json. Valid: {"render_devices": ["cuda:0", "cuda:1"...]}, or {"render_devices": "cpu"} or {"render_devices": "mps"} or {"render_devices": "auto"}'
|
||||||
)
|
)
|
||||||
|
|
||||||
render_devices = list(filter(lambda x: is_device_compatible(x), render_devices))
|
render_devices = list(filter(lambda x: is_device_compatible(x), render_devices))
|
||||||
@ -63,10 +64,26 @@ def get_device_delta(render_devices, active_devices):
|
|||||||
return devices_to_start, devices_to_stop
|
return devices_to_start, devices_to_stop
|
||||||
|
|
||||||
|
|
||||||
|
def is_mps_available():
|
||||||
|
return (
|
||||||
|
platform.system() == "Darwin"
|
||||||
|
and hasattr(torch.backends, "mps")
|
||||||
|
and torch.backends.mps.is_available()
|
||||||
|
and torch.backends.mps.is_built()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def is_cuda_available():
|
||||||
|
return torch.cuda.is_available()
|
||||||
|
|
||||||
|
|
||||||
def auto_pick_devices(currently_active_devices):
|
def auto_pick_devices(currently_active_devices):
|
||||||
global mem_free_threshold
|
global mem_free_threshold
|
||||||
|
|
||||||
if not torch.cuda.is_available():
|
if is_mps_available():
|
||||||
|
return ["mps"]
|
||||||
|
|
||||||
|
if not is_cuda_available():
|
||||||
return ["cpu"]
|
return ["cpu"]
|
||||||
|
|
||||||
device_count = torch.cuda.device_count()
|
device_count = torch.cuda.device_count()
|
||||||
@ -115,11 +132,11 @@ def device_init(context, device):
|
|||||||
|
|
||||||
validate_device_id(device, log_prefix="device_init")
|
validate_device_id(device, log_prefix="device_init")
|
||||||
|
|
||||||
if device == "cpu":
|
if "cuda" not in device:
|
||||||
context.device = "cpu"
|
context.device = device
|
||||||
context.device_name = get_processor_name()
|
context.device_name = get_processor_name()
|
||||||
context.half_precision = False
|
context.half_precision = False
|
||||||
log.debug(f"Render device CPU available as {context.device_name}")
|
log.debug(f"Render device available as {context.device_name}")
|
||||||
return
|
return
|
||||||
|
|
||||||
context.device_name = torch.cuda.get_device_name(device)
|
context.device_name = torch.cuda.get_device_name(device)
|
||||||
@ -134,8 +151,6 @@ def device_init(context, device):
|
|||||||
log.info(f'Setting {device} as active, with precision: {"half" if context.half_precision else "full"}')
|
log.info(f'Setting {device} as active, with precision: {"half" if context.half_precision else "full"}')
|
||||||
torch.cuda.device(device)
|
torch.cuda.device(device)
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def needs_to_force_full_precision(context):
|
def needs_to_force_full_precision(context):
|
||||||
if "FORCE_FULL_PRECISION" in os.environ:
|
if "FORCE_FULL_PRECISION" in os.environ:
|
||||||
@ -158,14 +173,16 @@ def needs_to_force_full_precision(context):
|
|||||||
|
|
||||||
|
|
||||||
def get_max_vram_usage_level(device):
|
def get_max_vram_usage_level(device):
|
||||||
if device != "cpu":
|
if "cuda" in device:
|
||||||
_, mem_total = torch.cuda.mem_get_info(device)
|
_, mem_total = torch.cuda.mem_get_info(device)
|
||||||
mem_total /= float(10**9)
|
else:
|
||||||
|
return "high"
|
||||||
|
|
||||||
if mem_total < 4.5:
|
mem_total /= float(10**9)
|
||||||
return "low"
|
if mem_total < 4.5:
|
||||||
elif mem_total < 6.5:
|
return "low"
|
||||||
return "balanced"
|
elif mem_total < 6.5:
|
||||||
|
return "balanced"
|
||||||
|
|
||||||
return "high"
|
return "high"
|
||||||
|
|
||||||
@ -174,7 +191,7 @@ def validate_device_id(device, log_prefix=""):
|
|||||||
def is_valid():
|
def is_valid():
|
||||||
if not isinstance(device, str):
|
if not isinstance(device, str):
|
||||||
return False
|
return False
|
||||||
if device == "cpu":
|
if device == "cpu" or device == "mps":
|
||||||
return True
|
return True
|
||||||
if not device.startswith("cuda:") or not device[5:].isnumeric():
|
if not device.startswith("cuda:") or not device[5:].isnumeric():
|
||||||
return False
|
return False
|
||||||
@ -182,7 +199,7 @@ def validate_device_id(device, log_prefix=""):
|
|||||||
|
|
||||||
if not is_valid():
|
if not is_valid():
|
||||||
raise EnvironmentError(
|
raise EnvironmentError(
|
||||||
f"{log_prefix}: device id should be 'cpu', or 'cuda:N' (where N is an integer index for the GPU). Got: {device}"
|
f"{log_prefix}: device id should be 'cpu', 'mps', or 'cuda:N' (where N is an integer index for the GPU). Got: {device}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -198,7 +215,7 @@ def is_device_compatible(device):
|
|||||||
log.error(str(e))
|
log.error(str(e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if device == "cpu":
|
if device in ("cpu", "mps"):
|
||||||
return True
|
return True
|
||||||
# Memory check
|
# Memory check
|
||||||
try:
|
try:
|
||||||
@ -217,14 +234,14 @@ def is_device_compatible(device):
|
|||||||
|
|
||||||
def get_processor_name():
|
def get_processor_name():
|
||||||
try:
|
try:
|
||||||
import platform, subprocess
|
import subprocess
|
||||||
|
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
return platform.processor()
|
return platform.processor()
|
||||||
elif platform.system() == "Darwin":
|
elif platform.system() == "Darwin":
|
||||||
os.environ["PATH"] = os.environ["PATH"] + os.pathsep + "/usr/sbin"
|
os.environ["PATH"] = os.environ["PATH"] + os.pathsep + "/usr/sbin"
|
||||||
command = "sysctl -n machdep.cpu.brand_string"
|
command = "sysctl -n machdep.cpu.brand_string"
|
||||||
return subprocess.check_output(command).strip()
|
return subprocess.check_output(command, shell=True).decode().strip()
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
command = "cat /proc/cpuinfo"
|
command = "cat /proc/cpuinfo"
|
||||||
all_info = subprocess.check_output(command, shell=True).decode().strip()
|
all_info = subprocess.check_output(command, shell=True).decode().strip()
|
||||||
|
@ -25,6 +25,13 @@ NOCACHE_HEADERS = {"Cache-Control": "no-cache, no-store, must-revalidate", "Prag
|
|||||||
|
|
||||||
|
|
||||||
class NoCacheStaticFiles(StaticFiles):
|
class NoCacheStaticFiles(StaticFiles):
|
||||||
|
def __init__(self, directory: str):
|
||||||
|
# follow_symlink is only available on fastapi >= 0.92.0
|
||||||
|
if (os.path.islink(directory)):
|
||||||
|
super().__init__(directory = os.path.realpath(directory))
|
||||||
|
else:
|
||||||
|
super().__init__(directory = directory)
|
||||||
|
|
||||||
def is_not_modified(self, response_headers, request_headers) -> bool:
|
def is_not_modified(self, response_headers, request_headers) -> bool:
|
||||||
if "content-type" in response_headers and (
|
if "content-type" in response_headers and (
|
||||||
"javascript" in response_headers["content-type"] or "css" in response_headers["content-type"]
|
"javascript" in response_headers["content-type"] or "css" in response_headers["content-type"]
|
||||||
@ -45,6 +52,13 @@ class SetAppConfigRequest(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
|
if os.path.isdir(app.CUSTOM_MODIFIERS_DIR):
|
||||||
|
server_api.mount(
|
||||||
|
"/media/modifier-thumbnails/custom",
|
||||||
|
NoCacheStaticFiles(directory=app.CUSTOM_MODIFIERS_DIR),
|
||||||
|
name="custom-thumbnails",
|
||||||
|
)
|
||||||
|
|
||||||
server_api.mount("/media", NoCacheStaticFiles(directory=os.path.join(app.SD_UI_DIR, "media")), name="media")
|
server_api.mount("/media", NoCacheStaticFiles(directory=os.path.join(app.SD_UI_DIR, "media")), name="media")
|
||||||
|
|
||||||
for plugins_dir, dir_prefix in app.UI_PLUGINS_SOURCES:
|
for plugins_dir, dir_prefix in app.UI_PLUGINS_SOURCES:
|
||||||
@ -156,7 +170,7 @@ def read_web_data_internal(key: str = None):
|
|||||||
elif key == "models":
|
elif key == "models":
|
||||||
return JSONResponse(model_manager.getModels(), headers=NOCACHE_HEADERS)
|
return JSONResponse(model_manager.getModels(), headers=NOCACHE_HEADERS)
|
||||||
elif key == "modifiers":
|
elif key == "modifiers":
|
||||||
return FileResponse(os.path.join(app.SD_UI_DIR, "modifiers.json"), headers=NOCACHE_HEADERS)
|
return JSONResponse(app.get_image_modifiers(), headers=NOCACHE_HEADERS)
|
||||||
elif key == "ui_plugins":
|
elif key == "ui_plugins":
|
||||||
return JSONResponse(app.getUIPlugins(), headers=NOCACHE_HEADERS)
|
return JSONResponse(app.getUIPlugins(), headers=NOCACHE_HEADERS)
|
||||||
else:
|
else:
|
||||||
|
@ -385,7 +385,7 @@ def get_devices():
|
|||||||
}
|
}
|
||||||
|
|
||||||
def get_device_info(device):
|
def get_device_info(device):
|
||||||
if device == "cpu":
|
if device in ("cpu", "mps"):
|
||||||
return {"name": device_manager.get_processor_name()}
|
return {"name": device_manager.get_processor_name()}
|
||||||
|
|
||||||
mem_free, mem_total = torch.cuda.mem_get_info(device)
|
mem_free, mem_total = torch.cuda.mem_get_info(device)
|
||||||
@ -400,14 +400,17 @@ def get_devices():
|
|||||||
}
|
}
|
||||||
|
|
||||||
# list the compatible devices
|
# list the compatible devices
|
||||||
gpu_count = torch.cuda.device_count()
|
cuda_count = torch.cuda.device_count()
|
||||||
for device in range(gpu_count):
|
for device in range(cuda_count):
|
||||||
device = f"cuda:{device}"
|
device = f"cuda:{device}"
|
||||||
if not device_manager.is_device_compatible(device):
|
if not device_manager.is_device_compatible(device):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
devices["all"].update({device: get_device_info(device)})
|
devices["all"].update({device: get_device_info(device)})
|
||||||
|
|
||||||
|
if device_manager.is_mps_available():
|
||||||
|
devices["all"].update({"mps": get_device_info("mps")})
|
||||||
|
|
||||||
devices["all"].update({"cpu": get_device_info("cpu")})
|
devices["all"].update({"cpu": get_device_info("cpu")})
|
||||||
|
|
||||||
# list the activated devices
|
# list the activated devices
|
||||||
|
@ -25,8 +25,9 @@
|
|||||||
<div id="top-nav">
|
<div id="top-nav">
|
||||||
<div id="logo">
|
<div id="logo">
|
||||||
<h1>
|
<h1>
|
||||||
|
<img id="logo_img" src="/media/images/icon-512x512.png" >
|
||||||
Easy Diffusion
|
Easy Diffusion
|
||||||
<small>v2.5.22 <span id="updateBranchLabel"></span></small>
|
<small>v2.5.24 <span id="updateBranchLabel"></span></small>
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
<div id="server-status">
|
<div id="server-status">
|
||||||
@ -289,6 +290,7 @@
|
|||||||
<button id="clear-all-previews" class="secondaryButton"><i class="fa-solid fa-trash-can icon"></i> Clear All</button>
|
<button id="clear-all-previews" class="secondaryButton"><i class="fa-solid fa-trash-can icon"></i> Clear All</button>
|
||||||
<button id="save-all-images" class="tertiaryButton"><i class="fa-solid fa-download icon"></i> Download All Images</button>
|
<button id="save-all-images" class="tertiaryButton"><i class="fa-solid fa-download icon"></i> Download All Images</button>
|
||||||
<div class="display-settings">
|
<div class="display-settings">
|
||||||
|
<span class="auto-scroll"></span> <!-- hack for Rabbit Hole update -->
|
||||||
<button id="auto_scroll_btn" class="tertiaryButton">
|
<button id="auto_scroll_btn" class="tertiaryButton">
|
||||||
<i class="fa-solid fa-arrows-up-to-line icon"></i>
|
<i class="fa-solid fa-arrows-up-to-line icon"></i>
|
||||||
<input id="auto_scroll" name="auto_scroll" type="checkbox" style="display: none">
|
<input id="auto_scroll" name="auto_scroll" type="checkbox" style="display: none">
|
||||||
|
@ -214,3 +214,10 @@
|
|||||||
.image-editor-popup h4 {
|
.image-editor-popup h4 {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.image-editor-popup .load_mask {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.inpainter .load_mask {
|
||||||
|
display: flex;
|
||||||
|
}
|
@ -27,6 +27,11 @@ code {
|
|||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
#logo_img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
transform: translateY(4px);
|
||||||
|
}
|
||||||
#prompt {
|
#prompt {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 65pt;
|
height: 65pt;
|
||||||
@ -324,6 +329,7 @@ div.img-preview img {
|
|||||||
#logo {
|
#logo {
|
||||||
display: inline;
|
display: inline;
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
|
padding-top: 8px;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
#logo h1 {
|
#logo h1 {
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 329 KiB After Width: | Height: | Size: 352 KiB |
@ -117,6 +117,42 @@ const IMAGE_EDITOR_TOOLS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
const IMAGE_EDITOR_ACTIONS = [
|
const IMAGE_EDITOR_ACTIONS = [
|
||||||
|
{
|
||||||
|
id: "load_mask",
|
||||||
|
name: "Load mask from file",
|
||||||
|
className: "load_mask",
|
||||||
|
icon: "fa-regular fa-folder-open",
|
||||||
|
handler: (editor) => {
|
||||||
|
let el = document.createElement('input')
|
||||||
|
el.setAttribute("type", "file")
|
||||||
|
el.addEventListener("change", function() {
|
||||||
|
if (this.files.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let reader = new FileReader()
|
||||||
|
let file = this.files[0]
|
||||||
|
|
||||||
|
reader.addEventListener('load', function(event) {
|
||||||
|
let maskData = reader.result
|
||||||
|
|
||||||
|
editor.layers.drawing.ctx.clearRect(0, 0, editor.width, editor.height)
|
||||||
|
var image = new Image()
|
||||||
|
image.onload = () => {
|
||||||
|
editor.layers.drawing.ctx.drawImage(image, 0, 0, editor.width, editor.height)
|
||||||
|
}
|
||||||
|
image.src = maskData
|
||||||
|
})
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
reader.readAsDataURL(file)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
el.click()
|
||||||
|
},
|
||||||
|
trackHistory: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "fill_all",
|
id: "fill_all",
|
||||||
name: "Fill all",
|
name: "Fill all",
|
||||||
@ -457,6 +493,9 @@ class ImageEditor {
|
|||||||
var element = document.createElement("div")
|
var element = document.createElement("div")
|
||||||
var icon = document.createElement("i")
|
var icon = document.createElement("i")
|
||||||
element.className = "image-editor-button button"
|
element.className = "image-editor-button button"
|
||||||
|
if (action.className) {
|
||||||
|
element.className += " " + action.className
|
||||||
|
}
|
||||||
icon.className = action.icon
|
icon.className = action.icon
|
||||||
element.appendChild(icon)
|
element.appendChild(icon)
|
||||||
element.append(action.name)
|
element.append(action.name)
|
||||||
|