#!/usr/bin/env python3 """Reference dumps for the 1024_cascade high-resolution geometry stage. Produces dumps/reference_cascade.gguf with the full HR chain so the C++ port can be validated stage by stage: cond_512, cond_1024 the two DINOv3 conds (embedded → self-contained test) coords32 [L,4] 32^3 scaffold (from the SS reference latent) lr_noise [L,32] LR sampling noise (seed 4321) lr_slat [L,32] 512-model sampler output, denormalized up_coords [Nup,4] decoder.upsample(lr_slat, upsample_times=4) → 512^3 hr_coords [Lhr,4] quantized+unique → 64^3 (the HR flow scaffold) hr_noise [Lhr,32] HR sampling noise (seed 5678) hr_flow_t500_out [Lhr,32] 1024-model flow forward at t=500 on hr_coords hr_slat [Lhr,32] 1024-model sampler output, denormalized lvl{i}.*, out7, out_coords per-level decode taps at resolution 1024 (→ 1024^3) The reference is generated with TF32 disabled (ref_common.setup) so the golden values are true fp32. Run inside the container (see scripts/refgen.sh). """ import argparse import json import os import struct import sys sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import ref_common # noqa: E402 ref_common.setup() # TF32 off + sdpa sparse attention + pure-torch sparse conv import numpy as np # noqa: E402 import torch # noqa: E402 import torch.nn.functional as F # noqa: E402 def read_dinodata(path): with open(path, "rb") as f: assert f.read(8) == b"DINOCOND", "bad magic" _, _, ndim = struct.unpack(" 0 occ = (F.max_pool3d(occ.float(), 2, 2, 0) > 0.5) coords = torch.argwhere(occ)[:, [0, 2, 3, 4]].int().contiguous() L = coords.shape[0] caps["coords32"] = coords.float() print(f"scaffold: {L} voxels at 32^3") del ss_dec # ── LR flow: sample with the 512 model + cond_512, denormalize ─────────── flow_lr, cfg_lr = load_flow(os.path.join(args.models, "slat_flow_img2shape_dit_1_3B_512_bf16"), dev) g = torch.Generator().manual_seed(args.lr_seed) lr_noise = torch.randn(L, cfg_lr["in_channels"], generator=g).to(dev) caps["lr_noise"] = lr_noise x0 = sp.SparseTensor(feats=lr_noise.clone(), coords=coords.to(dev)) with torch.no_grad(): lr_slat = sampler.sample(flow_lr, x0, cond=cond_512, neg_cond=torch.zeros_like(cond_512), **sampler_params, verbose=True).samples lr_slat = lr_slat * std + mean caps["lr_slat"] = lr_slat.feats print(f"lr_slat: {lr_slat.feats.shape} mean={lr_slat.feats.mean().item():.5f}") del flow_lr if dev.type == "cuda": torch.cuda.empty_cache() # ── shape decoder: upsample(×4) → 512^3 candidate coords ───────────────── dstem = os.path.join(args.models, "shape_dec_next_dc_f16c32_fp16") with open(dstem + ".json") as f: dcfg = json.load(f)["args"] dcfg.pop("use_fp16", None) dcfg.pop("resolution", None) dec = FlexiDualGridVaeDecoder(resolution=args.resolution, use_fp16=False, **dcfg) dec.load_state_dict({k: v.float() for k, v in load_file(dstem + ".safetensors").items()}) # The decoder runs on CPU: the 1024^3 expansion materializes millions of # voxels through the pure-torch sparse conv and would OOM the 16 GB GPU (and # it is exactly what the C++ port runs on CPU). Flows stay on GPU. dec.eval().float().cpu() with torch.no_grad(): up_coords = dec.upsample(lr_slat.cpu(), upsample_times=4) # [Nup, 4] at 512^3 caps["up_coords"] = up_coords.float() print(f"upsample: {up_coords.shape[0]} candidate coords at {args.lr_resolution}^3") # ── quantize + unique → 64^3 HR scaffold (verbatim pipeline formula) ───── hr_res = args.resolution quant_coords = torch.cat([ up_coords[:, :1], ((up_coords[:, 1:] + 0.5) / args.lr_resolution * (hr_res // 16)).int(), ], dim=1) hr_coords = quant_coords.unique(dim=0) Lhr = hr_coords.shape[0] caps["hr_coords"] = hr_coords.float() print(f"hr scaffold: {Lhr} voxels at {hr_res // 16}^3") # ── HR flow: forward @ t=500 + full sampler with 1024 model + cond_1024 ── flow_hr, cfg_hr = load_flow(os.path.join(args.models, "slat_flow_img2shape_dit_1_3B_1024_bf16"), dev) g = torch.Generator().manual_seed(args.hr_seed) hr_noise = torch.randn(Lhr, cfg_hr["in_channels"], generator=g).to(dev) caps["hr_noise"] = hr_noise xh = sp.SparseTensor(feats=hr_noise.clone(), coords=hr_coords.to(dev)) with torch.no_grad(): out = flow_hr(xh, torch.tensor([args.t], device=dev), cond_1024) caps["hr_flow_t500_out"] = out.feats print(f"hr flow t={args.t}: l2={out.feats.norm().item():.4f}") xh0 = sp.SparseTensor(feats=hr_noise.clone(), coords=hr_coords.to(dev)) with torch.no_grad(): hr_slat = sampler.sample(flow_hr, xh0, cond=cond_1024, neg_cond=torch.zeros_like(cond_1024), **sampler_params, verbose=True).samples hr_slat = hr_slat * std + mean caps["hr_slat"] = hr_slat.feats print(f"hr_slat: {hr_slat.feats.shape} mean={hr_slat.feats.mean().item():.5f}") del flow_hr if dev.type == "cuda": torch.cuda.empty_cache() # ── final decode of the HR slat at resolution 1024, level by level ─────── # Only the final 7-channel output is kept: the per-level intermediates are # multiple GB at 1024^3 (and the decoder's level logic is already validated # exactly at the 512 tier). We run the base SparseUnetVaeDecoder forward # manually to get the raw 7 channels — dec(...) would run the FDG mesh # conversion (stubbed o_voxel). Running the decode on CPU is host-RAM heavy. dec.set_resolution(args.resolution) hr_slat_cpu = hr_slat.cpu() with torch.no_grad(): h = dec.from_latent(hr_slat_cpu.float()) for i, res in enumerate(dec.blocks): for j, block in enumerate(res): if i < len(dec.blocks) - 1 and j == len(res) - 1: h, _sub = block(h) else: h = block(h) print(f"decode level {i}: {h.feats.shape[0]} voxels x {h.feats.shape[1]} ch") hn = h.replace(F.layer_norm(h.feats, h.feats.shape[-1:])) out7 = dec.output_layer(hn) caps["out7"] = out7.feats caps["out_coords"] = out7.coords.float() print(f"out7: {out7.feats.shape}") import gguf writer = gguf.GGUFWriter(args.out, "reference") manifest = {"shapes": {}, "atol": 2e-3, "rtol": 2e-3, "lr_resolution": args.lr_resolution, "resolution": args.resolution} for name, t in caps.items(): a = t.detach().cpu().float().numpy() manifest["shapes"][name] = list(a.shape) writer.add_tensor(name, np.ascontiguousarray(a.reshape(-1), dtype=np.float32)) writer.write_header_to_file() writer.write_kv_data_to_file() writer.write_tensors_to_file() writer.close() with open(os.path.join(ref_common.DUMPS, "manifest_cascade.json"), "w") as f: json.dump(manifest, f, indent=1) print(f"wrote {args.out} ({os.path.getsize(args.out):,} bytes), {len(caps)} tensors") if __name__ == "__main__": main()