ADR-0416: VIF on-the-fly filter sync from Netflix upstream¶
Status: Accepted Date: 2026-05-10 Tags: vif, upstream-sync, fork-local, netflix-golden, fork-internal
Context¶
Master Netflix-Golden CI was red on feature_extractor_test.py after PR #754 reverted PR #723. PR #723 had attempted a partial port of upstream Netflix commit bf9ad333 ("libvmaf/feature/vif: switch from precomputed to on-the-fly filter computation") but only ported the mirror-tap-h fix and a small slice of the filter-dispatch rewrite. That partial port left the fork bit-exact with upstream on default-kernelscale compute_vif but diverged on non-default kernelscales, breaking 7 fork-local test_run_vmaf_runner_float_vifks* tests calibrated against the old lookup-table dispatch — so PR #754 reverted #723 entirely. The revert restored the vifks tests but reintroduced 8 fextractor tests fail with vif_num/vif_den deltas of ~8.4 / ~9.3 on values ~713 K / ~1.6 M (relative drift ~1e-5, places=0 strictness).
Investigation showed Netflix upstream has the companion test recalibration in 142c0671, 7209110e, d93495f5, and fe756c9f. The fork was missing those test updates because PR #723 only ported the C-side change without the test sync. The CI failure was therefore a half-port, not a real numeric bug.
Decision¶
Sync the VIF on-the-fly filter machinery in full from Netflix upstream and adopt the companion test recalibrations.
C-side files taken verbatim from upstream/master:
core/src/feature/vif.ccore/src/feature/vif.hcore/src/feature/vif_tools.ccore/src/feature/vif_tools.hcore/src/feature/vif_options.h
Public-API change: compute_vif() gains an int vif_skip_scale0 parameter between vif_kernelscale and vif_sigma_nsq. The single in-tree non-trivial caller, core/src/feature/float_vif.c::extract(), threads s->vif_skip_scale0 ? 1 : 0 through to the new slot. The internal compute_vifdiff recursion in vif.c already passes 0 for the new parameter (upstream pattern).
Test-side cherry-picks from upstream:
142c0671— VIF score values for on-the-fly kernel computation (vif_scale0..3on thesrc01Netflix CPU pair across multiple test variants).d93495f5— relaxVMAF_legacy_score/VMAF_scoretolerance on a handful of tests where upstream observedlibmcross-platform precision drift; conflict resolution kept fork-local values where the fork's binary diverged from upstream's binary at places=4 (the fork already had the relaxation; upstream's assertion text was the change Netflix shipped).fe756c9f— loosenvifks360o97tolerance.7209110e— update expectedVMAF_scorevalues in the twotest_run_vmaf_runner_motion_force_zero/test_run_vmaf_runner_with_param_neg_and_model_mfztests (97.42843 → 97.42835); resolution kept fork-side for thefeature_extractor_test.py,result_test.py,vmafexec_test.pyconflicts because PR #731's commit message states it already cherry-picked7209110efor those files.
Consequences¶
Positive
- Netflix Golden CI green on the canonical CPU pair. Local-pytest baseline delta: master
feature_extractor_test.py8 failures → 0 failures;quality_runner_test.py9 failures → 0 failures (moduloskimagemodule-not-found env issue onniqe_runnertest, unrelated). - VIF default-kernelscale and non-default-kernelscale now both bit-match Netflix upstream's reference implementation.
- Eliminates the lookup-table
vif_filter1d_table_sand theresolve_kernelscale_index()/ALMOST_EQUALmachinery — fork no longer carries a divergent filter-dispatch path.
Negative / open
- GPU backends (CUDA / SYCL / Vulkan / HIP / Metal) still call into their own VIF kernels and were unaffected by this change. The Vulkan VIF shader (
float_vif.comp) already saturates against CPU (ADR-0381) but may need a follow-up parity check now that the CPU reference shifted by ~1e-5; tracked as a state.md follow-up. - Two
vmafexec_feature_extractor_test.pytest groups remain pre-existing failures (*_prescale_*andtest_todataframe_fromdataframe) — these are not introduced by this PR and pre-date PR #754. Tracked separately in state.md.
Alternatives considered¶
- Restore PR #723 only (re-revert PR #754). Rejected: would only flip the failing-test set (8 fextractor pass, 9 vifks fail) without delivering net green CI. The fork would still diverge from upstream for non-default kernelscale.
- Defer to a focused multi-PR session. Rejected: master CI is red on Netflix Golden today; the sync is well-scoped (5 C files + 4 test cherry-picks) and fits a single PR with proper ADR + state.md update.
- Cherry-pick
bf9ad333+8c645ce3directly instead of taking upstream HEAD versions verbatim. Rejected: the cherry-pick produced ~11 conflict regions across 3 files due to fork's incremental pre-port history; taking upstream HEAD versions is cleaner and avoids cascading conflicts.
References¶
- User direction (paraphrased): the user requested the full upstream VIF sync via popup option after seeing the partial-fix trade-offs of restoring PR #723 alone.
- PR #723 (
8c74ac7d) — partial bf9ad333 port, reverted. - PR #754 (
b886ae18) — revert of #723 that exposed the half-port gap. - PR #731 (
67b0a1c6) — ADM noise_weight port; commit message states cherry-pick of3dee9666 + 7209110e(the non-quality-runner subset). - Upstream Netflix commits:
bf9ad333,8c645ce3,142c0671,d93495f5,fe756c9f,7209110e. - ADR-0381 (Vulkan VIF scale 2/3 precision) — adjacent invariant; CPU reference shift may motivate a Vulkan re-check.