Skip to content

Feature: HiDiffusion integration - #8787

Merged
lstein merged 51 commits into
invoke-ai:mainfrom
DustyShoe:Feature/hidiffusion-integration
Aug 3, 2026
Merged

Feature: HiDiffusion integration#8787
lstein merged 51 commits into
invoke-ai:mainfrom
DustyShoe:Feature/hidiffusion-integration

Conversation

@DustyShoe

@DustyShoe DustyShoe commented Jan 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Added HiDiffusion support across backend and UI. The denoise pipeline can now apply HiDiffusion with optional RAU‑Net and Window Attention toggles, including metadata persistence/recall and graph wiring for SD1/SDXL and the SDXL refiner. The UI exposes aligned advanced switches with informational popovers.
Added HiDiffusion documentation and a “Learn more” link.

Related Issues / Discussions

https://github.com/megvii-research/HiDiffusion
Closes #8780

QA Instructions

  1. UI: Canvas → Advanced Settings → confirm HiDiffusion + RAU‑Net + Window Attention toggles visible, aligned, truncation works at narrow width.
  2. Popovers: hover labels for HiDiffusion/RAU‑Net/Window Attention; popover appears and HiDiffusion shows Learn More link.
  3. Metadata: generate once with HiDiffusion ON + custom RAU/Window; verify metadata fields exist and Recall restores toggles.
  4. SDXL: compare OFF vs ON at 1536+ (same seed). Then toggle RAU off / Window off to confirm output changes and no errors.
  5. SD1.5: repeat step 4 at highest feasible res.
  6. Regression: generate with HiDiffusion OFF; no errors/warnings.

Merge Plan

Should merge without issue.

  • Just to be aware of changes in lockfiles: uv.lock, pyproject.toml.
  • HiDiffusion package availability: it pulls from PyPI upstream. If a version change introduces breaking behavior, we may need to pin a specific version.
  • name_or_path hack: we’re forcing _name_or_path to avoid HiDiffusion errors. If diffusers changes internals, this might need adjustment.
  • No DB/schema breaking changes.

Checklist

  • The PR has a short but descriptive title, suitable for a changelog
  • Tests added / updated (if applicable)
  • ❗Changes to a redux slice have a corresponding migration
  • Documentation added / updated (if applicable)
  • Updated What's New copy (if doing a release after this PR)

@github-actions github-actions Bot added python PRs that change python files Root invocations PRs that change invocations backend PRs that change backend files frontend PRs that change frontend files docs PRs that change docs python-deps PRs that change python dependencies labels Jan 25, 2026
@DustyShoe DustyShoe changed the title Feature/hidiffusion integration Feature: HiDiffusion integration Jan 25, 2026
@Pfannkuchensack Pfannkuchensack self-assigned this Jan 25, 2026
@DustyShoe

DustyShoe commented Jan 25, 2026

Copy link
Copy Markdown
Collaborator Author

I might be spoiled by SDXL too much, but SD1.5 did not impress me much. It produces better results than default denoise. Especially when generating whole image. Inpainting is a tricky one. You might want to try different schedulers. Hands are particularly messy at 1.5k px.
SDXL on other hand, behaves much better and i'm pretty happy with it.
Also noticed ~10% improvement in speed.

@DustyShoe
DustyShoe marked this pull request as draft January 25, 2026 21:21
@DustyShoe

Copy link
Copy Markdown
Collaborator Author

I just realised that updated version of HiDiffusion is here: https://github.com/Teriks/dgenerate/tree/master/dgenerate/extras/hidiffusion
How we can use it if it works better?

@iwr-redmond

iwr-redmond commented Jan 26, 2026

Copy link
Copy Markdown

You may wish to consider vendoring the code inside the Invoke package, e.g. invokeai.backend.hidiffusion. Both packages are licensed with Apache 2.0.

Comment thread docs/src/content/docs/features/hidiffusion.mdx Outdated
@JPPhoto
JPPhoto self-requested a review July 31, 2026 16:21

@JPPhoto JPPhoto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to bump versions of nodes that you've added fields to:

  • invokeai/app/invocations/denoise_latents.py: bump DenoiseLatentsInvocation from 1.5.4 to a new version, likely 1.6.0 because new public inputs were added.

  • invokeai/app/invocations/metadata_linked.py: bump DenoiseLatentsMetaInvocation from 1.1.1 to a new version, likely 1.2.0 for the inherited new inputs and added metadata keys.

  • The generated openapi.json must also be regenerated so the frontend schema advertises the bumped versions.

Very minor, but the license file LICENSE-HiDiffusion.txt at the repository root looks like it's missing a newline at the end.

As soon as you fix these, I'll approve this to merge!

@DustyShoe

Copy link
Copy Markdown
Collaborator Author

@JPPhoto

  • Bumped DenoiseLatentsInvocation to 1.6.0 and DenoiseLatentsMetaInvocation to 1.2.0.
  • Regenerated openapi.json and the frontend schema; schema.ts had no resulting content changes because invocation versions are not represented in its generated types.
  • Added the missing newline at the end of LICENSE-HiDiffusion.txt

@JPPhoto
JPPhoto self-requested a review August 1, 2026 19:39

@JPPhoto JPPhoto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One more that I found:

  • invokeai/backend/stable_diffusion/hidiffusion_utils.py:114: hidiffusion_patch() never accepts or passes invocation-seeded torch.Generator; vendored window attention therefore reaches torch.rand(1) process-global RNG at invokeai/backend/hidiffusion/hidiffusion.py:1420. Same seed can produce different images when window attention is enabled. Test by running two identical HiDiffusion window-attention denoises with the same seed while perturbing global Torch RNG between runs.

@DustyShoe

Copy link
Copy Markdown
Collaborator Author

Fixed both modular and legacy denoise paths to create a dedicated torch.Generator seeded from the invocation seed and pass it through hidiffusion_patch() into the vendored window-attention implementation. Added a regression test that runs the real window-attention patch twice with the same seed while perturbing the process-global Torch RNG; both results are identical.

@JPPhoto
JPPhoto self-requested a review August 2, 2026 03:21

@JPPhoto JPPhoto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to merge!

@DustyShoe

Copy link
Copy Markdown
Collaborator Author

HiDiffusion runtime state could persist on cached UNet modules after the patch was removed. Re-enabling HiDiffusion or changing the bounding-box dimensions could therefore reuse stale timestep, RAU-Net, and convolution attributes, causing duplicated anatomy and other generation artifacts.

Added fix fix: stale HiDiffusion state in cached UNet resets HiDiffusion-specific runtime state before patching the relevant RAU-Net blocks again. Regular generations with HiDiffusion disabled remain unaffected. A regression test covers the ONOFFON sequence using the same cached UNet instance.

@JPPhoto JPPhoto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The latest changes have an issue:

  • invokeai/backend/hidiffusion/hidiffusion.py:2182: remove_hidiffusion() restores classes but never calls _reset_hidiffusion_runtime_state(). If downsampler forward fails after geometry changes at lines 1860-1862 but before restoration, cached stride, padding, and dilation remain mutated; next HiDiffusion-disabled run uses corrupted convolution geometry. Re-enable reset is too late and skipped when RAU-Net is disabled. Test: force F.conv2d to raise during patched downsampler forward, exit patch context, then assert geometry is restored before an unpatched forward.

Here's a regression test you can modify and drop in that shows the fault:

from unittest.mock import patch

import pytest
import torch

from invokeai.backend.stable_diffusion.hidiffusion_utils import hidiffusion_patch


class ModelMixin(torch.nn.Module):
    """Minimal cached UNet accepted by HiDiffusion's diffusers type check."""

    def __init__(self) -> None:
        super().__init__()
        self.num_upsamplers = 3
        self._num_timesteps = 10
        self.block = torch.nn.Conv2d(1, 1, kernel_size=3, stride=2, padding=1)


def test_hidiffusion_teardown_restores_downsampler_geometry_after_forward_error() -> None:
    module_keys = {
        "down_module_key": ["block"],
        "down_module_key_extra": [],
        "up_module_key": [],
        "up_module_key_extra": [],
        "windown_attn_module_key": [],
    }
    model = ModelMixin()
    original_stride = model.block.stride
    original_padding = model.block.padding
    original_dilation = model.block.dilation

    with patch("invokeai.backend.hidiffusion.hidiffusion.sd15_hidiffusion_key", return_value=module_keys):
        with hidiffusion_patch(
            model,
            name_or_path="runwayml/stable-diffusion-v1-5",
            apply_window_attn=False,
        ):
            model.info["size"] = (64, 64)
            with (
                patch(
                    "invokeai.backend.hidiffusion.hidiffusion.F.conv2d",
                    side_effect=RuntimeError("injected convolution failure"),
                ),
                pytest.raises(RuntimeError, match="injected convolution failure"),
            ):
                model.block(torch.zeros(1, 1, 16, 16))

    # The cached module is now unpatched. A HiDiffusion-disabled generation
    # must see its original convolution geometry.
    assert model.block.stride == original_stride
    assert model.block.padding == original_padding
    assert model.block.dilation == original_dilation

@DustyShoe

Copy link
Copy Markdown
Collaborator Author

Implemented transactional HiDiffusion teardown. Downsampler geometry is now passed to F.conv2d() through local variables and is never written to the cached module. Per-module state is snapshotted during patch application and restored during teardown, which remains protected by finally. The regression test now covers ON → failed forward → OFF and verifies that the unpatched cached UNet retains its original convolution geometry.

@JPPhoto
JPPhoto self-requested a review August 2, 2026 13:18

@JPPhoto JPPhoto left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to merge again!

@lstein lstein left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work!

@lstein
lstein merged commit 2f470d3 into invoke-ai:main Aug 3, 2026
17 checks passed
@DustyShoe
DustyShoe deleted the Feature/hidiffusion-integration branch August 3, 2026 18:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.14 Nice-to-Have 6.14.0 backend PRs that change backend files docs PRs that change docs frontend PRs that change frontend files invocations PRs that change invocations python PRs that change python files python-deps PRs that change python dependencies python-tests PRs that change python tests Root

Projects

Status: 6.14.x Theme: USER EXPERIENCE

Development

Successfully merging this pull request may close these issues.

[enhancement]: Add HiDiffusion for improved SD1.x and SDXL image generation

5 participants