The native composition is now:
pose token + optional initial estimate
-> original-contract FFN / pose, hand and scale decoding
-> real converted MHR: skeleton, blendshapes, correctives, skinning
-> meters / joint rotations / 308-point mapping / 70-point selection / axes
src/body_output.cpp connects the existing pose prefix and real MHR GGUF runtime;
it does not accept injected MHR results in the composed entry point. This is
composition/contract parity with synthetic SAM head state, not trained SAM
image-to-body parity. The MHR asset is real and byte-verified. The FFN, scale/hand
PCA, hand index buffers and 308-point mapping are deliberately synthetic and
explicit in the tests, because the trained SAM checkpoint remains gated. Do not
ship them as model defaults, semantic keypoint definitions or inference weights.
The pinned original MHRHead constructor and complete forward/mhr_forward
methods run in the reviewed container. MOMENTUM_ENABLED=0 deliberately selects
the verified released TorchScript through the original loader; the newer Momentum
Python model is not substituted. No original mathematical functions are rewritten
for the full-head oracle. Original source and RoMa wheel hashes are checked before
import; only the exact official MHR byte identity is deserialized.
- Geometry and skeleton come from the native pose parameters, not from a fixture.
- Vertices and joint coordinates are divided by 100 before keypoint regression. Native CPU preserves direct division; the CUDA-reference Vulkan mode preserves F32 reciprocal multiplication. The arithmetic choice is explicit internally.
- The mapping input is
[vertices, joint coordinates], then permute/flatten from[B,N,3]to[N,B*3]. The full 308 rows are projected before selecting 70. GGML performs the projection; its output layout is checked explicitly. - RoMa
unitquat_to_rotmatuses XYZW and does not normalize. Its diagonal formula uses all four squares, not the unit-only1 - 2*(...)shortcut. - Only vertex/keypoint/joint positions get the Y/Z sign flips in the final
body outputs.
joint_global_rotsremains in MHR's original rotation convention; applying a seemingly consistent camera-axis change there would differ upstream. do_pcblendis accepted by the original head but never forwarded toself.mhr. This body path therefore keeps MHR's defaultapply_correctives=True; both default anddo_pcblend=Falseoriginal outputs are compared explicitly.- The wrist-centric hand model, hand refinement and its extra transforms are
separate unfinished paths.
slim_keypointsis also unused by this original body-mode forward; do not invent different output selection semantics.
Use the isolated container procedure in MHR.md, an output directory such
as generated/fixtures/body-output-cpu, and these Python entry-point arguments:
/work/reference/capture_body_output.py \
--model /work/generated/models/mhr-public/assets/mhr_model.pt \
--upstream /work/reference/upstream/sam-3d-body \
--roma-wheel /work/generated/wheels/roma-1.6.1-py3-none-any.whl \
--output /output --device cpuCapture CUDA separately with the documented GPU exposure and --device cuda.
The two cases exercise batch two/no initial estimate and batch one/1024-wide
two-layer FFN with an initial estimate. Head weights are small perturbations of
the original zero-pose initialization, and the nontrivial synthetic mapping has
signed weights using both vertices and joints. Every required state array is
passed explicitly to native inference.
Non-replacing operation observation and source-frame locals capture 23 boundaries per case. Observation is checked against an uninstrumented complete head call: CPU is exact; CUDA worst difference is 1.49e-8 on these inputs. The original final tensor outputs are retained independently and compared natively too.
uv run --project reference/python --frozen python scripts/run_body_output.py \
--reference generated/fixtures/body-output-cpu \
--runner build/debug/bin/sam3d-body-output-capture \
--module build/debug/bin/libggml-cpu.so \
--gguf generated/models/mhr-public/mhr-lod1-f32.gguf \
--output generated/fixtures/body-output-native-cpu --threads 12For NVIDIA Vulkan use that build's runner and libggml-vulkan.so, the CUDA
reference, --backend Vulkan, and your device index/description. Driver paths are
caller configuration, not hardcoded. The runner sets the same strict-F32 Vulkan
options as the preceding component captures. CPU retains ASan/UBSan/LSan; the
documented NVIDIA ASan/ICD exception uses the separate Vulkan UBSan build.
Both backends pass 70 comparisons (46 boundaries plus 24 uninstrumented final tensor comparisons) at max-abs 1e-4 / relative-L2 2e-5. Native CPU final vertices are within 4.77e-7 meters and keypoints within 2.39e-7 m. Vulkan/CUDA final vertices are within 5.97e-7 m and keypoints within 3.58e-7 m. Worst intermediate max-abs, including raw MHR centimeters, is 4.58e-5 on CPU and 5.35e-5 on Vulkan. These are correctness gates, not performance measurements.
The normal sanitizer regression body_output_mapping_upstream covers 12 mapping
boundaries plus malformed shapes/nonfinite values, axis signs and non-normalizing
quaternion behavior. Its 268KB fixture compresses the first case to 16 vertices:
only identically zero mapping columns are omitted, with all joints retained.
The expected outputs still come from the original complete head. This fixture is
explicitly an isolated mapping test, not the full-head test with real GGUF.
It needs no model download. Adjacent JSON records full-capture provenance.
| Tensor artifact | SHA-256 |
|---|---|
| Original CPU observed head | 48c9948fb6ea97b68e5bc034b6c1397684dd9a3affe005f6d87015c105d7bfee |
| Original CUDA observed head | a958c882e77d66a9a1c1c3a605e4654cfa673197a72dda4162c4adc4e6f7ca09 |
| Native CPU | 2d2d8e2156c3a1ea21a6ad334b2f4e86edffe201522e929b80415c251c54dfde |
| Native NVIDIA Vulkan | b693270880c6b354380ff285325ab22271c50769f7b8cf42fb36ab0194b086c8 |
| Normal mapping fixture | 773ceef7f6eaf60c5c97b9bc0f71001f23d84482fc00ac390908515d9dfc9cdc |
The full per-layer decoder geometry/camera feedback composition is now separately tested with synthetic SAM state; see BODY_FLOW.md. Remaining acceptance includes trained checkpoint buffers/semantic keypoints, full-width decoder and backbone/decoder composition, hand refinement, the public model/session API, image-to-mesh demo/Chrome QA, Objects and optimized end-to-end performance. This stage does not satisfy those.