trellis_sparse_mrp_mlx/trellis_sparse_mlx/__init__.py
John 384e87fca1 DiT blocks: RoPE, per-head RMS norm, AdaLN modulation (23 tests total)
Unlocks all four Pixal3D flow checkpoints (~20GB) at once - they are pure transformers
with no sparse conv. LATO.2 has flow models too (vertex_structured_flow, topo_flow), so
these belong in the shared core rather than either port.

Three details taken from upstream rather than assumed, each silent when wrong:
- norm1/norm3 are NON-affine but norm2 IS affine in the modulated cross block. There is
  an explicit test asserting that asymmetry.
- MultiHeadRMSNorm is written upstream as F.normalize(x)*gamma*sqrt(dim). F.normalize is
  L2, and the sqrt(d) turns it into RMS - implemented directly as RMS and verified equal
  to the upstream formulation to 9.5e-7.
- RoPE phases are NOT derived: Pixal3D ships rope_phases as a stored tensor, so they are
  passed in. Tested that the rotation preserves per-pair norms and is not a no-op.

Also tested: gates at zero make the block an identity on its residual branches.
2026-08-02 11:33:04 +10:00

49 lines
1.7 KiB
Python

"""MLX implementation of the TRELLIS-lineage sparse module.
Microsoft's TRELLIS.2 sparse stack has been inherited, near-verbatim, by a growing
family of 3D generation models — LATO.2 and TencentARC's Pixal3D among them. All of
them hard-require spconv or torchsparse, neither of which has a Metal build, and that
single dependency is what keeps the whole lineage off Apple Silicon.
The blocker is one operation: submanifold 3x3x3 convolution. Every SparseConv3d in
these models is constructed `stride=1, padding=None`, which spconv dispatches to
SubMConv3d. Implement that in MLX and the rest is ordinary linear/norm/attention work.
Packaged separately from any one model so each port depends on a tested core rather
than vendoring its own copy.
"""
from .conv import SubMConv3d, build_indice_map
from .dit import (
DiTAttention,
ModulatedTransformerCrossBlock,
MultiHeadRMSNorm,
TimestepEmbedder,
apply_rope,
)
from .tensor import SparseTensor, VarLenTensor, downsample, subdivide, upsample
from .ops import (
LayerNorm32,
SparseFeedForwardNet,
SparseGELU,
SparseGroupNorm32,
SparseLinear,
SparseMultiHeadAttention,
SparseResBlock,
SparseSiLU,
SparseTransformerBlock,
SparseTransformerCrossBlock,
)
__all__ = [
"SparseTensor", "VarLenTensor", "subdivide", "downsample", "upsample",
"SubMConv3d", "build_indice_map",
"SparseLinear", "LayerNorm32", "SparseGroupNorm32", "SparseSiLU", "SparseGELU",
"SparseResBlock", "SparseFeedForwardNet", "SparseMultiHeadAttention",
"SparseTransformerBlock", "SparseTransformerCrossBlock",
# DiT / flow-model pieces
"MultiHeadRMSNorm", "apply_rope", "TimestepEmbedder", "DiTAttention",
"ModulatedTransformerCrossBlock",
]
__version__ = "0.1.0"