Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
ComfyUI
Commits
a2236a0c
Commit
a2236a0c
authored
Apr 24, 2023
by
comfyanonymous
Browse files
Merge branch 'master' of
https://github.com/BlenderNeko/ComfyUI
parents
463bde66
0b07b2cc
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
106 additions
and
74 deletions
+106
-74
comfy/sample.py
comfy/sample.py
+57
-0
comfy/samplers.py
comfy/samplers.py
+37
-27
nodes.py
nodes.py
+12
-47
No files found.
comfy/sample.py
0 → 100644
View file @
a2236a0c
import
torch
import
comfy.model_management
def
prepare_noise
(
latent_image
,
seed
,
skip
=
0
):
"""
creates random noise given a latent image and a seed.
optional arg skip can be used to skip and discard x number of noise generations for a given seed
"""
generator
=
torch
.
manual_seed
(
seed
)
for
_
in
range
(
skip
):
noise
=
torch
.
randn
([
1
]
+
list
(
latent_image
.
size
())[
1
:],
dtype
=
latent_image
.
dtype
,
layout
=
latent_image
.
layout
,
generator
=
generator
,
device
=
"cpu"
)
noise
=
torch
.
randn
(
latent_image
.
size
(),
dtype
=
latent_image
.
dtype
,
layout
=
latent_image
.
layout
,
generator
=
generator
,
device
=
"cpu"
)
return
noise
def
prepare_mask
(
noise_mask
,
noise
):
"""ensures noise mask is of proper dimensions"""
device
=
comfy
.
model_management
.
get_torch_device
()
noise_mask
=
torch
.
nn
.
functional
.
interpolate
(
noise_mask
[
None
,
None
,],
size
=
(
noise
.
shape
[
2
],
noise
.
shape
[
3
]),
mode
=
"bilinear"
)
noise_mask
=
noise_mask
.
round
()
noise_mask
=
torch
.
cat
([
noise_mask
]
*
noise
.
shape
[
1
],
dim
=
1
)
noise_mask
=
torch
.
cat
([
noise_mask
]
*
noise
.
shape
[
0
])
noise_mask
=
noise_mask
.
to
(
device
)
return
noise_mask
def
broadcast_cond
(
cond
,
noise
):
"""broadcasts conditioning to the noise batch size"""
device
=
comfy
.
model_management
.
get_torch_device
()
copy
=
[]
for
p
in
cond
:
t
=
p
[
0
]
if
t
.
shape
[
0
]
<
noise
.
shape
[
0
]:
t
=
torch
.
cat
([
t
]
*
noise
.
shape
[
0
])
t
=
t
.
to
(
device
)
copy
+=
[[
t
]
+
p
[
1
:]]
return
copy
def
get_models_from_cond
(
cond
,
model_type
):
models
=
[]
for
c
in
cond
:
if
model_type
in
c
[
1
]:
models
+=
[
c
[
1
][
model_type
]]
return
models
def
load_additional_models
(
positive
,
negative
):
"""loads additional models in positive and negative conditioning"""
control_nets
=
get_models_from_cond
(
positive
,
"control"
)
+
get_models_from_cond
(
negative
,
"control"
)
gligen
=
get_models_from_cond
(
positive
,
"gligen"
)
+
get_models_from_cond
(
negative
,
"gligen"
)
gligen
=
[
x
[
1
]
for
x
in
gligen
]
models
=
control_nets
+
gligen
comfy
.
model_management
.
load_controlnet_gpu
(
models
)
return
models
def
cleanup_additional_models
(
models
):
"""cleanup additional models that were loaded"""
for
m
in
models
:
m
.
cleanup
()
\ No newline at end of file
comfy/samplers.py
View file @
a2236a0c
...
@@ -400,6 +400,38 @@ def encode_adm(noise_augmentor, conds, batch_size, device):
...
@@ -400,6 +400,38 @@ def encode_adm(noise_augmentor, conds, batch_size, device):
return
conds
return
conds
def
calculate_sigmas
(
model
,
steps
,
scheduler
,
sampler
):
"""
Returns a tensor containing the sigmas corresponding to the given model, number of steps, scheduler type and sample technique
"""
if
not
(
isinstance
(
model
,
CompVisVDenoiser
)
or
isinstance
(
model
,
k_diffusion_external
.
CompVisDenoiser
)):
model
=
CFGNoisePredictor
(
model
)
if
model
.
inner_model
.
parameterization
==
"v"
:
model
=
CompVisVDenoiser
(
model
,
quantize
=
True
)
else
:
model
=
k_diffusion_external
.
CompVisDenoiser
(
model
,
quantize
=
True
)
sigmas
=
None
discard_penultimate_sigma
=
False
if
sampler
in
[
'dpm_2'
,
'dpm_2_ancestral'
]:
steps
+=
1
discard_penultimate_sigma
=
True
if
scheduler
==
"karras"
:
sigmas
=
k_diffusion_sampling
.
get_sigmas_karras
(
n
=
steps
,
sigma_min
=
float
(
model
.
sigma_min
),
sigma_max
=
float
(
model
.
sigma_max
))
elif
scheduler
==
"normal"
:
sigmas
=
model
.
get_sigmas
(
steps
)
elif
scheduler
==
"simple"
:
sigmas
=
simple_scheduler
(
model
,
steps
)
elif
scheduler
==
"ddim_uniform"
:
sigmas
=
ddim_scheduler
(
model
,
steps
)
else
:
print
(
"error invalid scheduler"
,
scheduler
)
if
discard_penultimate_sigma
:
sigmas
=
torch
.
cat
([
sigmas
[:
-
2
],
sigmas
[
-
1
:]])
return
sigmas
class
KSampler
:
class
KSampler
:
SCHEDULERS
=
[
"karras"
,
"normal"
,
"simple"
,
"ddim_uniform"
]
SCHEDULERS
=
[
"karras"
,
"normal"
,
"simple"
,
"ddim_uniform"
]
...
@@ -429,41 +461,19 @@ class KSampler:
...
@@ -429,41 +461,19 @@ class KSampler:
self
.
denoise
=
denoise
self
.
denoise
=
denoise
self
.
model_options
=
model_options
self
.
model_options
=
model_options
def
_calculate_sigmas
(
self
,
steps
):
sigmas
=
None
discard_penultimate_sigma
=
False
if
self
.
sampler
in
[
'dpm_2'
,
'dpm_2_ancestral'
]:
steps
+=
1
discard_penultimate_sigma
=
True
if
self
.
scheduler
==
"karras"
:
sigmas
=
k_diffusion_sampling
.
get_sigmas_karras
(
n
=
steps
,
sigma_min
=
self
.
sigma_min
,
sigma_max
=
self
.
sigma_max
,
device
=
self
.
device
)
elif
self
.
scheduler
==
"normal"
:
sigmas
=
self
.
model_wrap
.
get_sigmas
(
steps
).
to
(
self
.
device
)
elif
self
.
scheduler
==
"simple"
:
sigmas
=
simple_scheduler
(
self
.
model_wrap
,
steps
).
to
(
self
.
device
)
elif
self
.
scheduler
==
"ddim_uniform"
:
sigmas
=
ddim_scheduler
(
self
.
model_wrap
,
steps
).
to
(
self
.
device
)
else
:
print
(
"error invalid scheduler"
,
self
.
scheduler
)
if
discard_penultimate_sigma
:
sigmas
=
torch
.
cat
([
sigmas
[:
-
2
],
sigmas
[
-
1
:]])
return
sigmas
def
set_steps
(
self
,
steps
,
denoise
=
None
):
def
set_steps
(
self
,
steps
,
denoise
=
None
):
self
.
steps
=
steps
self
.
steps
=
steps
if
denoise
is
None
or
denoise
>
0.9999
:
if
denoise
is
None
or
denoise
>
0.9999
:
self
.
sigmas
=
self
.
_
calculate_sigmas
(
s
teps
)
self
.
sigmas
=
calculate_sigmas
(
s
elf
.
model_wrap
,
steps
,
self
.
scheduler
,
self
.
sampler
).
to
(
self
.
device
)
else
:
else
:
new_steps
=
int
(
steps
/
denoise
)
new_steps
=
int
(
steps
/
denoise
)
sigmas
=
self
.
_
calculate_sigmas
(
new_steps
)
sigmas
=
calculate_sigmas
(
self
.
model_wrap
,
new_steps
,
self
.
scheduler
,
self
.
sampler
).
to
(
self
.
device
)
self
.
sigmas
=
sigmas
[
-
(
steps
+
1
):]
self
.
sigmas
=
sigmas
[
-
(
steps
+
1
):]
def
sample
(
self
,
noise
,
positive
,
negative
,
cfg
,
latent_image
=
None
,
start_step
=
None
,
last_step
=
None
,
force_full_denoise
=
False
,
denoise_mask
=
None
):
def
sample
(
self
,
noise
,
positive
,
negative
,
cfg
,
latent_image
=
None
,
start_step
=
None
,
last_step
=
None
,
force_full_denoise
=
False
,
denoise_mask
=
None
,
sigmas
=
None
):
sigmas
=
self
.
sigmas
if
sigmas
is
None
:
sigmas
=
self
.
sigmas
sigma_min
=
self
.
sigma_min
sigma_min
=
self
.
sigma_min
if
last_step
is
not
None
and
last_step
<
(
len
(
sigmas
)
-
1
):
if
last_step
is
not
None
and
last_step
<
(
len
(
sigmas
)
-
1
):
...
...
nodes.py
View file @
a2236a0c
...
@@ -16,6 +16,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "co
...
@@ -16,6 +16,7 @@ sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), "co
import
comfy.diffusers_convert
import
comfy.diffusers_convert
import
comfy.samplers
import
comfy.samplers
import
comfy.sample
import
comfy.sd
import
comfy.sd
import
comfy.utils
import
comfy.utils
...
@@ -739,31 +740,19 @@ class SetLatentNoiseMask:
...
@@ -739,31 +740,19 @@ class SetLatentNoiseMask:
s
[
"noise_mask"
]
=
mask
s
[
"noise_mask"
]
=
mask
return
(
s
,)
return
(
s
,)
def
common_ksampler
(
model
,
seed
,
steps
,
cfg
,
sampler_name
,
scheduler
,
positive
,
negative
,
latent
,
denoise
=
1.0
,
disable_noise
=
False
,
start_step
=
None
,
last_step
=
None
,
force_full_denoise
=
False
):
def
common_ksampler
(
model
,
seed
,
steps
,
cfg
,
sampler_name
,
scheduler
,
positive
,
negative
,
latent
,
denoise
=
1.0
,
disable_noise
=
False
,
start_step
=
None
,
last_step
=
None
,
force_full_denoise
=
False
):
latent_image
=
latent
[
"samples"
]
noise_mask
=
None
device
=
comfy
.
model_management
.
get_torch_device
()
device
=
comfy
.
model_management
.
get_torch_device
()
latent_image
=
latent
[
"samples"
]
if
disable_noise
:
if
disable_noise
:
noise
=
torch
.
zeros
(
latent_image
.
size
(),
dtype
=
latent_image
.
dtype
,
layout
=
latent_image
.
layout
,
device
=
"cpu"
)
noise
=
torch
.
zeros
(
latent_image
.
size
(),
dtype
=
latent_image
.
dtype
,
layout
=
latent_image
.
layout
,
device
=
"cpu"
)
else
:
else
:
batch_index
=
0
skip
=
latent
[
"batch_index"
]
if
"batch_index"
in
latent
else
0
if
"batch_index"
in
latent
:
noise
=
comfy
.
sample
.
prepare_noise
(
latent_image
,
seed
,
skip
)
batch_index
=
latent
[
"batch_index"
]
generator
=
torch
.
manual_seed
(
seed
)
for
i
in
range
(
batch_index
):
noise
=
torch
.
randn
([
1
]
+
list
(
latent_image
.
size
())[
1
:],
dtype
=
latent_image
.
dtype
,
layout
=
latent_image
.
layout
,
generator
=
generator
,
device
=
"cpu"
)
noise
=
torch
.
randn
(
latent_image
.
size
(),
dtype
=
latent_image
.
dtype
,
layout
=
latent_image
.
layout
,
generator
=
generator
,
device
=
"cpu"
)
noise_mask
=
None
if
"noise_mask"
in
latent
:
if
"noise_mask"
in
latent
:
noise_mask
=
latent
[
'noise_mask'
]
noise_mask
=
comfy
.
sample
.
prepare_mask
(
latent
[
"noise_mask"
],
noise
)
noise_mask
=
torch
.
nn
.
functional
.
interpolate
(
noise_mask
[
None
,
None
,],
size
=
(
noise
.
shape
[
2
],
noise
.
shape
[
3
]),
mode
=
"bilinear"
)
noise_mask
=
noise_mask
.
round
()
noise_mask
=
torch
.
cat
([
noise_mask
]
*
noise
.
shape
[
1
],
dim
=
1
)
noise_mask
=
torch
.
cat
([
noise_mask
]
*
noise
.
shape
[
0
])
noise_mask
=
noise_mask
.
to
(
device
)
real_model
=
None
real_model
=
None
comfy
.
model_management
.
load_model_gpu
(
model
)
comfy
.
model_management
.
load_model_gpu
(
model
)
...
@@ -772,34 +761,10 @@ def common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive,
...
@@ -772,34 +761,10 @@ def common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive,
noise
=
noise
.
to
(
device
)
noise
=
noise
.
to
(
device
)
latent_image
=
latent_image
.
to
(
device
)
latent_image
=
latent_image
.
to
(
device
)
positive_copy
=
[]
positive_copy
=
comfy
.
sample
.
broadcast_cond
(
positive
,
noise
)
negative_copy
=
[]
negative_copy
=
comfy
.
sample
.
broadcast_cond
(
negative
,
noise
)
control_nets
=
[]
models
=
comfy
.
sample
.
load_additional_models
(
positive
,
negative
)
def
get_models
(
cond
):
models
=
[]
for
c
in
cond
:
if
'control'
in
c
[
1
]:
models
+=
[
c
[
1
][
'control'
]]
if
'gligen'
in
c
[
1
]:
models
+=
[
c
[
1
][
'gligen'
][
1
]]
return
models
for
p
in
positive
:
t
=
p
[
0
]
if
t
.
shape
[
0
]
<
noise
.
shape
[
0
]:
t
=
torch
.
cat
([
t
]
*
noise
.
shape
[
0
])
t
=
t
.
to
(
device
)
positive_copy
+=
[[
t
]
+
p
[
1
:]]
for
n
in
negative
:
t
=
n
[
0
]
if
t
.
shape
[
0
]
<
noise
.
shape
[
0
]:
t
=
torch
.
cat
([
t
]
*
noise
.
shape
[
0
])
t
=
t
.
to
(
device
)
negative_copy
+=
[[
t
]
+
n
[
1
:]]
models
=
get_models
(
positive
)
+
get_models
(
negative
)
comfy
.
model_management
.
load_controlnet_gpu
(
models
)
if
sampler_name
in
comfy
.
samplers
.
KSampler
.
SAMPLERS
:
if
sampler_name
in
comfy
.
samplers
.
KSampler
.
SAMPLERS
:
sampler
=
comfy
.
samplers
.
KSampler
(
real_model
,
steps
=
steps
,
device
=
device
,
sampler
=
sampler_name
,
scheduler
=
scheduler
,
denoise
=
denoise
,
model_options
=
model
.
model_options
)
sampler
=
comfy
.
samplers
.
KSampler
(
real_model
,
steps
=
steps
,
device
=
device
,
sampler
=
sampler_name
,
scheduler
=
scheduler
,
denoise
=
denoise
,
model_options
=
model
.
model_options
)
...
@@ -809,8 +774,8 @@ def common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive,
...
@@ -809,8 +774,8 @@ def common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive,
samples
=
sampler
.
sample
(
noise
,
positive_copy
,
negative_copy
,
cfg
=
cfg
,
latent_image
=
latent_image
,
start_step
=
start_step
,
last_step
=
last_step
,
force_full_denoise
=
force_full_denoise
,
denoise_mask
=
noise_mask
)
samples
=
sampler
.
sample
(
noise
,
positive_copy
,
negative_copy
,
cfg
=
cfg
,
latent_image
=
latent_image
,
start_step
=
start_step
,
last_step
=
last_step
,
force_full_denoise
=
force_full_denoise
,
denoise_mask
=
noise_mask
)
samples
=
samples
.
cpu
()
samples
=
samples
.
cpu
()
for
m
in
models
:
m
.
cleanup
(
)
comfy
.
sample
.
cleanup_additional_models
(
models
)
out
=
latent
.
copy
()
out
=
latent
.
copy
()
out
[
"samples"
]
=
samples
out
[
"samples"
]
=
samples
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment