Skip to content

Commit 6f33877

Browse files
committed
Merge branch 'upstream' into gempoll
2 parents 735974e + 38c22e6 commit 6f33877

File tree

20 files changed

+520
-284
lines changed

20 files changed

+520
-284
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.\python_embeded\python.exe -s ComfyUI\main.py --windows-standalone-build --fast
2+
pause

.github/workflows/windows_release_nightly_pytorch.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ jobs:
6767
mkdir update
6868
cp -r ComfyUI/.ci/update_windows/* ./update/
6969
cp -r ComfyUI/.ci/windows_base_files/* ./
70+
cp -r ComfyUI/.ci/windows_nightly_base_files/* ./
7071
7172
echo "call update_comfyui.bat nopause
7273
..\python_embeded\python.exe -s -m pip install --upgrade --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/nightly/cu${{ inputs.cu }} -r ../ComfyUI/requirements.txt pygit2

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ To use a textual inversion concepts/embeddings in a text prompt put them in the
230230

231231
Use ```--preview-method auto``` to enable previews.
232232

233-
The default installation includes a fast latent preview method that's low-resolution. To enable higher-quality previews with [TAESD](https://github.com/madebyollin/taesd), download the [taesd_decoder.pth](https://github.com/madebyollin/taesd/raw/main/taesd_decoder.pth) (for SD1.x and SD2.x) and [taesdxl_decoder.pth](https://github.com/madebyollin/taesd/raw/main/taesdxl_decoder.pth) (for SDXL) models and place them in the `models/vae_approx` folder. Once they're installed, restart ComfyUI to enable high-quality previews.
233+
The default installation includes a fast latent preview method that's low-resolution. To enable higher-quality previews with [TAESD](https://github.com/madebyollin/taesd), download the [taesd_decoder.pth, taesdxl_decoder.pth, taesd3_decoder.pth and taef1_decoder.pth](https://github.com/madebyollin/taesd/) and place them in the `models/vae_approx` folder. Once they're installed, restart ComfyUI and launch it with `--preview-method taesd` to enable high-quality previews.
234234

235235
## How to use TLS/SSL?
236236
Generate a self-signed certificate (not appropriate for shared/production use) and key by running the command: `openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -sha256 -days 3650 -nodes -subj "/C=XX/ST=StateName/L=CityName/O=CompanyName/OU=CompanySectionName/CN=CommonNameOrHostname"`

app/frontend_management.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from dataclasses import dataclass
99
from functools import cached_property
1010
from pathlib import Path
11-
from typing import TypedDict
11+
from typing import TypedDict, Optional
1212

1313
import requests
1414
from typing_extensions import NotRequired
@@ -132,12 +132,13 @@ def parse_version_string(cls, value: str) -> tuple[str, str, str]:
132132
return match_result.group(1), match_result.group(2), match_result.group(3)
133133

134134
@classmethod
135-
def init_frontend_unsafe(cls, version_string: str) -> str:
135+
def init_frontend_unsafe(cls, version_string: str, provider: Optional[FrontEndProvider] = None) -> str:
136136
"""
137137
Initializes the frontend for the specified version.
138138
139139
Args:
140140
version_string (str): The version string.
141+
provider (FrontEndProvider, optional): The provider to use. Defaults to None.
141142
142143
Returns:
143144
str: The path to the initialized frontend.
@@ -150,23 +151,29 @@ def init_frontend_unsafe(cls, version_string: str) -> str:
150151
return cls.DEFAULT_FRONTEND_PATH
151152

152153
repo_owner, repo_name, version = cls.parse_version_string(version_string)
153-
provider = FrontEndProvider(repo_owner, repo_name)
154+
provider = provider or FrontEndProvider(repo_owner, repo_name)
154155
release = provider.get_release(version)
155156

156157
semantic_version = release["tag_name"].lstrip("v")
157158
web_root = str(
158159
Path(cls.CUSTOM_FRONTENDS_ROOT) / provider.folder_name / semantic_version
159160
)
160161
if not os.path.exists(web_root):
161-
os.makedirs(web_root, exist_ok=True)
162-
logging.info(
163-
"Downloading frontend(%s) version(%s) to (%s)",
164-
provider.folder_name,
165-
semantic_version,
166-
web_root,
167-
)
168-
logging.debug(release)
169-
download_release_asset_zip(release, destination_path=web_root)
162+
try:
163+
os.makedirs(web_root, exist_ok=True)
164+
logging.info(
165+
"Downloading frontend(%s) version(%s) to (%s)",
166+
provider.folder_name,
167+
semantic_version,
168+
web_root,
169+
)
170+
logging.debug(release)
171+
download_release_asset_zip(release, destination_path=web_root)
172+
finally:
173+
# Clean up the directory if it is empty, i.e. the download failed
174+
if not os.listdir(web_root):
175+
os.rmdir(web_root)
176+
170177
return web_root
171178

172179
@classmethod

comfy/controlnet.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,8 @@ def controlnet_config(sd):
391391
else:
392392
operations = comfy.ops.disable_weight_init
393393

394-
return model_config, operations, load_device, unet_dtype, manual_cast_dtype
394+
offload_device = comfy.model_management.unet_offload_device()
395+
return model_config, operations, load_device, unet_dtype, manual_cast_dtype, offload_device
395396

396397
def controlnet_load_state_dict(control_model, sd):
397398
missing, unexpected = control_model.load_state_dict(sd, strict=False)
@@ -405,12 +406,12 @@ def controlnet_load_state_dict(control_model, sd):
405406

406407
def load_controlnet_mmdit(sd):
407408
new_sd = comfy.model_detection.convert_diffusers_mmdit(sd, "")
408-
model_config, operations, load_device, unet_dtype, manual_cast_dtype = controlnet_config(new_sd)
409+
model_config, operations, load_device, unet_dtype, manual_cast_dtype, offload_device = controlnet_config(new_sd)
409410
num_blocks = comfy.model_detection.count_blocks(new_sd, 'joint_blocks.{}.')
410411
for k in sd:
411412
new_sd[k] = sd[k]
412413

413-
control_model = comfy.cldm.mmdit.ControlNet(num_blocks=num_blocks, operations=operations, device=load_device, dtype=unet_dtype, **model_config.unet_config)
414+
control_model = comfy.cldm.mmdit.ControlNet(num_blocks=num_blocks, operations=operations, device=offload_device, dtype=unet_dtype, **model_config.unet_config)
414415
control_model = controlnet_load_state_dict(control_model, new_sd)
415416

416417
latent_format = comfy.latent_formats.SD3()
@@ -420,9 +421,9 @@ def load_controlnet_mmdit(sd):
420421

421422

422423
def load_controlnet_hunyuandit(controlnet_data):
423-
model_config, operations, load_device, unet_dtype, manual_cast_dtype = controlnet_config(controlnet_data)
424+
model_config, operations, load_device, unet_dtype, manual_cast_dtype, offload_device = controlnet_config(controlnet_data)
424425

425-
control_model = comfy.ldm.hydit.controlnet.HunYuanControlNet(operations=operations, device=load_device, dtype=unet_dtype)
426+
control_model = comfy.ldm.hydit.controlnet.HunYuanControlNet(operations=operations, device=offload_device, dtype=unet_dtype)
426427
control_model = controlnet_load_state_dict(control_model, controlnet_data)
427428

428429
latent_format = comfy.latent_formats.SDXL()
@@ -431,8 +432,8 @@ def load_controlnet_hunyuandit(controlnet_data):
431432
return control
432433

433434
def load_controlnet_flux_xlabs(sd):
434-
model_config, operations, load_device, unet_dtype, manual_cast_dtype = controlnet_config(sd)
435-
control_model = comfy.ldm.flux.controlnet_xlabs.ControlNetFlux(operations=operations, device=load_device, dtype=unet_dtype, **model_config.unet_config)
435+
model_config, operations, load_device, unet_dtype, manual_cast_dtype, offload_device = controlnet_config(sd)
436+
control_model = comfy.ldm.flux.controlnet_xlabs.ControlNetFlux(operations=operations, device=offload_device, dtype=unet_dtype, **model_config.unet_config)
436437
control_model = controlnet_load_state_dict(control_model, sd)
437438
extra_conds = ['y', 'guidance']
438439
control = ControlNet(control_model, load_device=load_device, manual_cast_dtype=manual_cast_dtype, extra_conds=extra_conds)
@@ -536,6 +537,7 @@ def load_controlnet(ckpt_path, model=None):
536537
if manual_cast_dtype is not None:
537538
controlnet_config["operations"] = comfy.ops.manual_cast
538539
controlnet_config["dtype"] = unet_dtype
540+
controlnet_config["device"] = comfy.model_management.unet_offload_device()
539541
controlnet_config.pop("out_channels")
540542
controlnet_config["hint_channels"] = controlnet_data["{}input_hint_block.0.weight".format(prefix)].shape[1]
541543
control_model = comfy.cldm.cldm.ControlNet(**controlnet_config)

comfy/float.py

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,62 @@
11
import torch
2+
import math
3+
4+
def calc_mantissa(abs_x, exponent, normal_mask, MANTISSA_BITS, EXPONENT_BIAS, generator=None):
5+
mantissa_scaled = torch.where(
6+
normal_mask,
7+
(abs_x / (2.0 ** (exponent - EXPONENT_BIAS)) - 1.0) * (2**MANTISSA_BITS),
8+
(abs_x / (2.0 ** (-EXPONENT_BIAS + 1 - MANTISSA_BITS)))
9+
)
10+
11+
mantissa_scaled += torch.rand(mantissa_scaled.size(), dtype=mantissa_scaled.dtype, layout=mantissa_scaled.layout, device=mantissa_scaled.device, generator=generator)
12+
return mantissa_scaled.floor() / (2**MANTISSA_BITS)
213

314
#Not 100% sure about this
4-
def manual_stochastic_round_to_float8(x, dtype):
15+
def manual_stochastic_round_to_float8(x, dtype, generator=None):
516
if dtype == torch.float8_e4m3fn:
617
EXPONENT_BITS, MANTISSA_BITS, EXPONENT_BIAS = 4, 3, 7
718
elif dtype == torch.float8_e5m2:
819
EXPONENT_BITS, MANTISSA_BITS, EXPONENT_BIAS = 5, 2, 15
920
else:
1021
raise ValueError("Unsupported dtype")
1122

23+
x = x.half()
1224
sign = torch.sign(x)
1325
abs_x = x.abs()
26+
sign = torch.where(abs_x == 0, 0, sign)
1427

1528
# Combine exponent calculation and clamping
1629
exponent = torch.clamp(
17-
torch.floor(torch.log2(abs_x)).to(torch.int32) + EXPONENT_BIAS,
30+
torch.floor(torch.log2(abs_x)) + EXPONENT_BIAS,
1831
0, 2**EXPONENT_BITS - 1
1932
)
2033

2134
# Combine mantissa calculation and rounding
22-
# min_normal = 2.0 ** (-EXPONENT_BIAS + 1)
23-
# zero_mask = (abs_x == 0)
24-
# subnormal_mask = (exponent == 0) & (abs_x != 0)
2535
normal_mask = ~(exponent == 0)
2636

27-
mantissa_scaled = torch.where(
28-
normal_mask,
29-
(abs_x / (2.0 ** (exponent - EXPONENT_BIAS)) - 1.0) * (2**MANTISSA_BITS),
30-
(abs_x / (2.0 ** (-EXPONENT_BIAS + 1 - MANTISSA_BITS)))
31-
)
32-
mantissa_floor = mantissa_scaled.floor()
33-
mantissa = torch.where(
34-
torch.rand_like(mantissa_scaled) < (mantissa_scaled - mantissa_floor),
35-
(mantissa_floor + 1) / (2**MANTISSA_BITS),
36-
mantissa_floor / (2**MANTISSA_BITS)
37-
)
38-
result = torch.where(
37+
abs_x[:] = calc_mantissa(abs_x, exponent, normal_mask, MANTISSA_BITS, EXPONENT_BIAS, generator=generator)
38+
39+
sign *= torch.where(
3940
normal_mask,
40-
sign * (2.0 ** (exponent - EXPONENT_BIAS)) * (1.0 + mantissa),
41-
sign * (2.0 ** (-EXPONENT_BIAS + 1)) * mantissa
41+
(2.0 ** (exponent - EXPONENT_BIAS)) * (1.0 + abs_x),
42+
(2.0 ** (-EXPONENT_BIAS + 1)) * abs_x
4243
)
44+
del abs_x
4345

44-
result = torch.where(abs_x == 0, 0, result)
45-
return result.to(dtype=dtype)
46+
return sign.to(dtype=dtype)
4647

4748

4849

49-
def stochastic_rounding(value, dtype):
50+
def stochastic_rounding(value, dtype, seed=0):
5051
if dtype == torch.float32:
5152
return value.to(dtype=torch.float32)
5253
if dtype == torch.float16:
5354
return value.to(dtype=torch.float16)
5455
if dtype == torch.bfloat16:
5556
return value.to(dtype=torch.bfloat16)
5657
if dtype == torch.float8_e4m3fn or dtype == torch.float8_e5m2:
57-
return manual_stochastic_round_to_float8(value, dtype)
58+
generator = torch.Generator(device=value.device)
59+
generator.manual_seed(seed)
60+
return manual_stochastic_round_to_float8(value, dtype, generator=generator)
5861

5962
return value.to(dtype=dtype)

comfy/ldm/flux/layers.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,8 @@ def __init__(self, dim: int, dtype=None, device=None, operations=None):
6363
self.scale = nn.Parameter(torch.empty((dim), dtype=dtype, device=device))
6464

6565
def forward(self, x: Tensor):
66-
x_dtype = x.dtype
67-
x = x.float()
6866
rrms = torch.rsqrt(torch.mean(x**2, dim=-1, keepdim=True) + 1e-6)
69-
return (x * rrms).to(dtype=x_dtype) * comfy.ops.cast_to(self.scale, dtype=x_dtype, device=x.device)
67+
return (x * rrms) * comfy.ops.cast_to(self.scale, dtype=x.dtype, device=x.device)
7068

7169

7270
class QKNorm(torch.nn.Module):

0 commit comments

Comments
 (0)