ADR-1176: Metal motion_v2 mirror closeout and reflect-101 parity contract¶
- Status: Accepted
- Date: 2026-09-04
- Deciders: Lusoris
- Tags:
metal,gpu,motion-v2,parity,boundary,closeout,fork-local
Context¶
ADR-1166 recorded the upstream triage findings from Netflix/vmaf#1580 and noted that the Metal integer_motion_v2 mirror kernel used 2 * sup - idx - 1 at the high boundary rather than reflect-101 (2 * (sup - 1) - idx). At triage time, ADR-1166 recorded this item as deferred under the premise that fixing it would move Metal scores and required dedicated Apple Silicon GPU verification and snapshot regeneration.
PR #1223 (commit 71da046db) subsequently implemented the reflect-101 fold in core/src/feature/metal/integer_motion_v2.metal:74-80:
inline int mv2_mirror(int idx, int sup)
{
if (sup <= 1) return 0;
while (idx < 0 || idx >= sup)
idx = (idx < 0) ? -idx : 2 * (sup - 1) - idx;
return idx;
}
This implementation iterated the bounce to handle out-of-bounds indices and corrected the boundary formula to 2 * (sup - 1) - idx, matching:
- CPU
core/src/feature/integer_motion_v2.c:157(mirror) - CUDA
core/src/feature/cuda/integer_motion_v2/motion_v2_score.cu:51(mv2_mirror) - SYCL
core/src/feature/sycl/integer_motion_v2_sycl.cpp:109(dev_mirror_mv2) - HIP
core/src/feature/hip/integer_motion_v2/motion_v2_score.hip:67(mv2_mirror, ADR-1106)
However, several closeout conditions remained unmet on master:
- The kernel header comment in
core/src/feature/metal/integer_motion_v2.metal:20-23contradicted the code by continuing to claim2 * size - idx - 1padding. docs/state.mdand ADR-1166 still described the Metal fix as open/deferred.- No Metal score snapshots exist in
testdata/(git ls-tree origin/master testdata | grep -i metalreturns 0), so no snapshot regeneration (/regen-snapshots) was actually required. - In
core/test/test_metal_motion_v2_parity.c, non-Apple hosts returning-ENODEVfromvmaf_metal_state_initemitted[skip: no Metal device]to stderr but exited with 0. Because Meson hides passing stderr in standard test runs, CI logs could not prove whether the test executed on live hardware or skipped.
Decision¶
- Close out the Metal motion_v2 mirror fix: Formally record that the reflect-101 kernel fix landed in PR #1223 (
71da046db). This ADR supersedes in part the deferral recorded in ADR-1166 §Neutral / follow-ups. - Align documentation with implementation: Correct the header comment in
core/src/feature/metal/integer_motion_v2.metalto document the iterated reflect-101 fold (2 * (sup - 1) - idx). Record the invariant incore/src/feature/metal/AGENTS.md. - No snapshot regeneration needed: Confirm that no fork-added Metal reference snapshots exist under
testdata/. CPU golden assertions remain unaffected. - Make test skip observable: In
core/test/test_metal_motion_v2_parity.c, setmu_skipped = 1on the-ENODEVbranch sotest.cexits 77 (Meson's standard skip code), log explicit device confirmation to stdout when hardware is active, and configure the test incore/test/meson.buildwithshould_fail : false,protocol : 'exitcode', andverbose : true.
Alternatives considered¶
| Option | Pros | Cons | Why not chosen |
|---|---|---|---|
| Leave ADR-1166 deferral open | Zero documentation work | Leaves state.md and ADR-1166 out of sync with actual code in tree | Rejected: code was already merged in #1223; state tracking must reflect reality. |
| Regenerate testdata snapshots | Follows standard GPU change playbook | No Metal snapshots exist in testdata/ | Rejected: testdata/ only contains CPU and select CUDA/SYCL snapshots. |
Keep exit 0 on -ENODEV skip | Matches legacy Metal parity tests | Indistinguishable from real device pass in CI logs | Rejected: exits 77 with verbose stdout gives clear observability of real hardware runs. |
Consequences¶
- Positive: Code, comments, ADRs, and
docs/state.mdare unified; cross-backend parity contract is documented; CI logs unambiguously distinguish device execution from skip. - Negative: None. Kernel code is unchanged from PR #1223; CPU golden data is untouched.
- Neutral / follow-ups: Other
test_metal_*_parity.ctests may adopt the observablemu_skipped = 1exit 77 pattern in future maintenance sweeps.
References¶
- PR #1223 (commit
71da046db) — upstream issue harvest batch implementation - ADR-1166 — upstream issue harvest triage (superseded in part)
- ADR-1106 — HIP motion_v2 mirror correction
- ADR-0421 — Metal motion_v2 initial kernel specification
- ADR-0214 — cross-backend parity gate (places=4)
core/src/feature/metal/integer_motion_v2.metalcore/test/test_metal_motion_v2_parity.c- Source: req