Cube3D: use channels-first 1D latent (B,1,L) like Hunyuan3Dv2

Replaces the dummy trailing-dim latent with a channels-first 1D latent
(B, 1, num_tokens) and a dedicated latent_formats.Cube3D
(latent_channels=1, latent_dimensions=1). This mirrors the existing
native 3D model Hunyuan3Dv2's (B, C, L) convention and avoids
fix_empty_latent_channels truncating the token sequence (it narrows
dim=1 to latent_channels for empty latents). Requires no core sampler
changes: encode_model_conds sees a valid noise.shape[2].

- latent_formats.Cube3D added; wired into supported_models.Cube3D
- EmptyCubeLatent emits (B, 1, num_tokens)
- sample_cube takes T from x.shape[-1], returns (B, 1, T), and repeats
  conditioning to the latent batch size

Amp-Thread-ID: https://ampcode.com/threads/T-019ec361-addb-70d8-a74b-438ce8a1e096
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Jedrzej Kosinski
2026-06-14 23:14:17 -07:00
parent 871f7bc390
commit a6c7397b71
4 changed files with 23 additions and 8 deletions

View File

@@ -38,10 +38,9 @@ class EmptyCubeLatent(IO.ComfyNode):
@classmethod
def execute(cls, num_tokens, batch_size) -> IO.NodeOutput:
# Trailing singleton dim keeps this a 3D latent so it flows through ComfyUI's
# conds/noise pipeline (encode_model_conds reads noise.shape[2]); the sampler
# only uses dim 1 (num_tokens).
latent = torch.zeros([batch_size, num_tokens, 1], device=comfy.model_management.intermediate_device())
# Channels-first 1D latent (B, 1, num_tokens), mirroring Hunyuan3Dv2's (B, C, L)
# convention (latent_channels=1). The sampler only uses the sequence length.
latent = torch.zeros([batch_size, 1, num_tokens], device=comfy.model_management.intermediate_device())
return IO.NodeOutput({"samples": latent, "type": "cube_tokens"})