Skip to content

Commit d66df9a

Browse files
Merge branch 'main' into lstein/chore/codeowners
2 parents f66a1a3 + 5c00684 commit d66df9a

File tree

21 files changed

+631
-75
lines changed

21 files changed

+631
-75
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,3 +192,6 @@ installer/InvokeAI-Installer/
192192
.aider*
193193

194194
.claude/
195+
196+
# Weblate configuration file
197+
weblate.ini

invokeai/app/invocations/z_image_denoise.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
title="Denoise - Z-Image",
5151
tags=["image", "z-image"],
5252
category="image",
53-
version="1.3.0",
53+
version="1.4.0",
5454
classification=Classification.Prototype,
5555
)
5656
class ZImageDenoiseInvocation(BaseInvocation):
@@ -69,6 +69,7 @@ class ZImageDenoiseInvocation(BaseInvocation):
6969
)
7070
denoising_start: float = InputField(default=0.0, ge=0, le=1, description=FieldDescriptions.denoising_start)
7171
denoising_end: float = InputField(default=1.0, ge=0, le=1, description=FieldDescriptions.denoising_end)
72+
add_noise: bool = InputField(default=True, description="Add noise based on denoising start.")
7273
transformer: TransformerField = InputField(
7374
description=FieldDescriptions.z_image_model, input=Input.Connection, title="Transformer"
7475
)
@@ -347,8 +348,12 @@ def _run_diffusion(self, context: InvocationContext) -> torch.Tensor:
347348

348349
# Prepare input latent image
349350
if init_latents is not None:
350-
s_0 = sigmas[0]
351-
latents = s_0 * noise + (1.0 - s_0) * init_latents
351+
if self.add_noise:
352+
# Noise the init_latents by the appropriate amount for the first timestep.
353+
s_0 = sigmas[0]
354+
latents = s_0 * noise + (1.0 - s_0) * init_latents
355+
else:
356+
latents = init_latents
352357
else:
353358
if self.denoising_start > 1e-5:
354359
raise ValueError("denoising_start should be 0 when initial latents are not provided.")

invokeai/app/invocations/z_image_image_to_latents.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from invokeai.backend.model_manager.load.load_base import LoadedModel
2121
from invokeai.backend.stable_diffusion.diffusers_pipeline import image_resized_to_grid_as_tensor
2222
from invokeai.backend.util.devices import TorchDevice
23+
from invokeai.backend.util.vae_working_memory import estimate_vae_working_memory_flux
2324

2425
# Z-Image can use either the Diffusers AutoencoderKL or the FLUX AutoEncoder
2526
ZImageVAE = Union[AutoencoderKL, FluxAutoEncoder]
@@ -47,7 +48,14 @@ def vae_encode(vae_info: LoadedModel, image_tensor: torch.Tensor) -> torch.Tenso
4748
"Ensure you are using a compatible VAE model."
4849
)
4950

50-
with vae_info.model_on_device() as (_, vae):
51+
# Estimate working memory needed for VAE encode
52+
estimated_working_memory = estimate_vae_working_memory_flux(
53+
operation="encode",
54+
image_tensor=image_tensor,
55+
vae=vae_info.model,
56+
)
57+
58+
with vae_info.model_on_device(working_mem_bytes=estimated_working_memory) as (_, vae):
5159
if not isinstance(vae, (AutoencoderKL, FluxAutoEncoder)):
5260
raise TypeError(
5361
f"Expected AutoencoderKL or FluxAutoEncoder, got {type(vae).__name__}. "

invokeai/app/invocations/z_image_latents_to_image.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from invokeai.backend.flux.modules.autoencoder import AutoEncoder as FluxAutoEncoder
2222
from invokeai.backend.stable_diffusion.extensions.seamless import SeamlessExt
2323
from invokeai.backend.util.devices import TorchDevice
24+
from invokeai.backend.util.vae_working_memory import estimate_vae_working_memory_flux
2425

2526
# Z-Image can use either the Diffusers AutoencoderKL or the FLUX AutoEncoder
2627
ZImageVAE = Union[AutoencoderKL, FluxAutoEncoder]
@@ -53,12 +54,19 @@ def invoke(self, context: InvocationContext) -> ImageOutput:
5354

5455
is_flux_vae = isinstance(vae_info.model, FluxAutoEncoder)
5556

57+
# Estimate working memory needed for VAE decode
58+
estimated_working_memory = estimate_vae_working_memory_flux(
59+
operation="decode",
60+
image_tensor=latents,
61+
vae=vae_info.model,
62+
)
63+
5664
# FLUX VAE doesn't support seamless, so only apply for AutoencoderKL
5765
seamless_context = (
5866
nullcontext() if is_flux_vae else SeamlessExt.static_patch_model(vae_info.model, self.vae.seamless_axes)
5967
)
6068

61-
with seamless_context, vae_info.model_on_device() as (_, vae):
69+
with seamless_context, vae_info.model_on_device(working_mem_bytes=estimated_working_memory) as (_, vae):
6270
context.util.signal_progress("Running VAE")
6371
if not isinstance(vae, (AutoencoderKL, FluxAutoEncoder)):
6472
raise TypeError(

invokeai/app/services/invocation_stats/invocation_stats_common.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class NodeExecutionStatsSummary:
1414
node_type: str
1515
num_calls: int
1616
time_used_seconds: float
17-
peak_vram_gb: float
17+
delta_vram_gb: float
1818

1919

2020
@dataclass
@@ -58,10 +58,10 @@ class InvocationStatsSummary:
5858
def __str__(self) -> str:
5959
_str = ""
6060
_str = f"Graph stats: {self.graph_stats.graph_execution_state_id}\n"
61-
_str += f"{'Node':>30} {'Calls':>7} {'Seconds':>9} {'VRAM Used':>10}\n"
61+
_str += f"{'Node':>30} {'Calls':>7} {'Seconds':>9} {'VRAM Change':+>10}\n"
6262

6363
for summary in self.node_stats:
64-
_str += f"{summary.node_type:>30} {summary.num_calls:>7} {summary.time_used_seconds:>8.3f}s {summary.peak_vram_gb:>9.3f}G\n"
64+
_str += f"{summary.node_type:>30} {summary.num_calls:>7} {summary.time_used_seconds:>8.3f}s {summary.delta_vram_gb:+10.3f}G\n"
6565

6666
_str += f"TOTAL GRAPH EXECUTION TIME: {self.graph_stats.execution_time_seconds:7.3f}s\n"
6767

@@ -100,7 +100,7 @@ class NodeExecutionStats:
100100
start_ram_gb: float # GB
101101
end_ram_gb: float # GB
102102

103-
peak_vram_gb: float # GB
103+
delta_vram_gb: float # GB
104104

105105
def total_time(self) -> float:
106106
return self.end_time - self.start_time
@@ -174,9 +174,9 @@ def get_node_stats_summaries(self) -> list[NodeExecutionStatsSummary]:
174174
for node_type, node_type_stats_list in node_stats_by_type.items():
175175
num_calls = len(node_type_stats_list)
176176
time_used = sum([n.total_time() for n in node_type_stats_list])
177-
peak_vram = max([n.peak_vram_gb for n in node_type_stats_list])
177+
delta_vram = max([n.delta_vram_gb for n in node_type_stats_list])
178178
summary = NodeExecutionStatsSummary(
179-
node_type=node_type, num_calls=num_calls, time_used_seconds=time_used, peak_vram_gb=peak_vram
179+
node_type=node_type, num_calls=num_calls, time_used_seconds=time_used, delta_vram_gb=delta_vram
180180
)
181181
summaries.append(summary)
182182

invokeai/app/services/invocation_stats/invocation_stats_default.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ def collect_stats(self, invocation: BaseInvocation, graph_execution_state_id: st
5252
# Record state before the invocation.
5353
start_time = time.time()
5454
start_ram = psutil.Process().memory_info().rss
55-
if torch.cuda.is_available():
56-
torch.cuda.reset_peak_memory_stats()
55+
56+
# Remember current VRAM usage
57+
vram_in_use = torch.cuda.memory_allocated() if torch.cuda.is_available() else 0.0
5758

5859
assert services.model_manager.load is not None
5960
services.model_manager.load.ram_cache.stats = self._cache_stats[graph_execution_state_id]
@@ -62,14 +63,16 @@ def collect_stats(self, invocation: BaseInvocation, graph_execution_state_id: st
6263
# Let the invocation run.
6364
yield None
6465
finally:
65-
# Record state after the invocation.
66+
# Record delta VRAM
67+
delta_vram_gb = ((torch.cuda.memory_allocated() - vram_in_use) / GB) if torch.cuda.is_available() else 0.0
68+
6669
node_stats = NodeExecutionStats(
6770
invocation_type=invocation.get_type(),
6871
start_time=start_time,
6972
end_time=time.time(),
7073
start_ram_gb=start_ram / GB,
7174
end_ram_gb=psutil.Process().memory_info().rss / GB,
72-
peak_vram_gb=torch.cuda.max_memory_allocated() / GB if torch.cuda.is_available() else 0.0,
75+
delta_vram_gb=delta_vram_gb,
7376
)
7477
self._stats[graph_execution_state_id].add_node_execution_stats(node_stats)
7578

@@ -81,6 +84,8 @@ def get_stats(self, graph_execution_state_id: str) -> InvocationStatsSummary:
8184
graph_stats_summary = self._get_graph_summary(graph_execution_state_id)
8285
node_stats_summaries = self._get_node_summaries(graph_execution_state_id)
8386
model_cache_stats_summary = self._get_model_cache_summary(graph_execution_state_id)
87+
# Note: We use memory_allocated() here (not memory_reserved()) because we want to show
88+
# the current actively-used VRAM, not the total reserved memory including PyTorch's cache.
8489
vram_usage_gb = torch.cuda.memory_allocated() / GB if torch.cuda.is_available() else None
8590

8691
return InvocationStatsSummary(

invokeai/backend/model_manager/load/model_cache/model_cache.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ def stats(self) -> Optional[CacheStats]:
240240
def stats(self, stats: CacheStats) -> None:
241241
"""Set the CacheStats object for collecting cache statistics."""
242242
self._stats = stats
243+
# Populate the cache size in the stats object when it's set
244+
if self._stats is not None:
245+
self._stats.cache_size = self._ram_cache_size_bytes
243246

244247
def _record_activity(self) -> None:
245248
"""Record model activity and reset the timeout timer if configured.

invokeai/backend/util/vae_working_memory.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ def estimate_vae_working_memory_sd15_sdxl(
4747
# If we are running in FP32, then we should account for the likely increase in model size (~250MB).
4848
working_memory += 250 * 2**20
4949

50-
print(f"estimate_vae_working_memory_sd15_sdxl: {int(working_memory)}")
51-
5250
return int(working_memory)
5351

5452

invokeai/frontend/web/public/locales/en.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2185,6 +2185,9 @@
21852185
"showHUD": "Show HUD",
21862186
"rectangle": "Rectangle",
21872187
"maskFill": "Mask Fill",
2188+
"maskLayerEmpty": "Mask layer is empty",
2189+
"extractMaskedAreaFailed": "Unable to extract masked area.",
2190+
"extractMaskedAreaMissingData": "Cannot extract: image or mask data is missing.",
21882191
"addPositivePrompt": "Add $t(controlLayers.prompt)",
21892192
"addNegativePrompt": "Add $t(controlLayers.negativePrompt)",
21902193
"addReferenceImage": "Add $t(controlLayers.referenceImage)",
@@ -2514,6 +2517,13 @@
25142517
"fitModeContain": "Contain",
25152518
"fitModeCover": "Cover",
25162519
"fitModeFill": "Fill",
2520+
"smoothing": "Smoothing",
2521+
"smoothingDesc": "Apply a high-quality backend resample when committing transforms.",
2522+
"smoothingMode": "Resample Mode",
2523+
"smoothingModeBilinear": "Bilinear",
2524+
"smoothingModeBicubic": "Bicubic",
2525+
"smoothingModeHamming": "Hamming",
2526+
"smoothingModeLanczos": "Lanczos",
25172527
"reset": "Reset",
25182528
"apply": "Apply",
25192529
"cancel": "Cancel"

invokeai/frontend/web/public/locales/it.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2762,7 +2762,9 @@
27622762
"watchRecentReleaseVideos": "Guarda i video su questa versione",
27632763
"items": [
27642764
"Gestione modelli: se non è possibile identificare un modello durante l'installazione, ora è possibile selezionare manualmente il tipo di modello e l'architettura.",
2765-
"Interno: sistema di identificazione dei modelli migliorato, che semplifica per i collaboratori l'aggiunta del supporto per nuovi modelli."
2765+
"Interno: sistema di identificazione dei modelli migliorato, che semplifica per i collaboratori l'aggiunta del supporto per nuovi modelli.",
2766+
"Strumento di ritaglio per immagini di riferimento",
2767+
"Interfaccia utente migliorata della scheda Gestione modelli"
27662768
],
27672769
"watchUiUpdatesOverview": "Guarda la panoramica degli aggiornamenti dell'interfaccia utente"
27682770
},

0 commit comments

Comments
 (0)