Repository navigation
fix: clear the -Denable_asm=false and aarch64 build warnings, and lint vif_neon.c to zero - #1483
Merged
Merged
Conversation
| /* Intentional bit-exact compare: AVX2 and scalar paths must produce | ||
| * identical float results per the CAMBI parity contract. */ | ||
| mu_assert("scalar vs avx2 calculate_c_values parity (bit-exact)", | ||
| c_scalar[i] == c_avx2[i]); /* bit-exact SIMD parity assertion */ |
…ings A -Denable_asm=false build emitted ~30 -Wunused-function / -Wunused-const-variable / -Wunused-variable warnings across ten SIMD parity-test files under core/test/: scalar-reference helpers, fixture builders, and lookup tables were defined unconditionally while every caller sat under an ISA guard (ARCH_X86, HAVE_AVX512, ARCH_AARCH64, or the ARCH_X86 || ARCH_AARCH64 union run_tests() already dispatches on). Move each helper under the same guard its callers use, walking the full dependency chain so the warning does not just relocate to a pick_*/ref_* helper one level down. test_ssimulacra2_simd.c needed one guard spanning its whole pick/ref/test section for that reason; test_cambi.c's histograms_a became a local declaration inside the existing #if ARCH_X86 block instead of an unconditional one. Nothing deleted, no (void) casts or [[maybe_unused]] suppressions. Files: test_vif_simd.c, test_ssimulacra2_simd.c, test_speed_simd.c, test_psnr_hvs_simd.c, test_ms_ssim_decimate.c, test_motion_v2_simd.c, test_iqa_convolve.c, test_integer_ssim_simd.c, test_cambi_simd.c, test_cambi.c. Verified zero warnings and an identical test count on: - -Denable_asm=false x86-64 (133/133 fast tests, was 30 warnings) - default x86-64 (137/137 fast tests, 0 warnings before and after) - aarch64 cross build under qemu-aarch64-static (135/135 fast tests; the two pre-existing, unrelated vif_neon.c -Wunused-but-set-variable warnings are untouched) Closes T-NO-ASM-SIMD-TEST-WARNINGS-2026-09-18 (docs/state.md).
…stic kernels vif_statistic_8_neon() and vif_statistic_16_neon() advanced an i_dst_stride counter every row and never read it, nor the stride it was built from; GCC reports -Wunused-but-set-variable on every aarch64 build. Upstream carries the same dead counters. No arithmetic changes.
…tidy findings The four NEON VIF kernels were single functions of 131 to 322 lines built from NEON_FILTER_* statement macros, which gave 36 clang-tidy findings: 18 macro-parentheses, 6 isolate-declaration, 4 function-size, 4 use-internal-linkage and 4 implicit-widening. No CI lane measures the arm64 tree, so the file was never held to ADR-1142 / ADR-0141. This branch touches it, so it has to end clean. Each kernel is now a row loop over static FORCE_INLINE helpers. They issue the same intrinsics in the same lane order as before: per-plane vertical and horizontal passes over small lane structs. The first filter tap has its own *_init helper wherever the macro code seeded an accumulator with a plain product. The macros are gone. vif_neon.c now includes vif_neon.h, which gives the four dispatched kernels their prototypes instead of making them static. The decimation index is now computed in ptrdiff_t. The rewrite also clears cppcheck's 42 shadowVariable and 6 constVariablePointer reports. The two statistic kernels take the Research-2045 constParameterPointer exception that their x86 twins already carry, because the VifState callback type requires the mutable parameter. tidy-ratchet --lane cpu --build-dir build-aarch64-clang --only vif_neon.c: 36 warnings before, 0 after, with no NOLINT and no compile failure. Bit-exactness: CLI binaries built before and after this change, with GCC and with Clang, were run under qemu-aarch64 over 34 input/config pairs, each with NEON and with --cpumask scalar dispatch. Inputs: the Netflix src01 pair, 8-, 10- and 12-bit inputs, and 570x318, 571x317 and 61x35 frames. Configs: --feature vif, vif debug with vif_enhn_gain_limit=1.0, the default model and vmaf_v0.6.1, all at --precision max. All 68 JSON outputs per compiler are byte-identical to the previous binary (excluding fps and version), and NEON matches scalar on all 34 pairs. test_vif_neon and the fast suite (135/135) pass on both cross builds, and GCC and Clang compile the file with -Wall -Wextra and no diagnostics.
Guarding histograms_a for -Denable_asm=false builds pushed the test to 61 lines. The AVX2 leg now lives in a helper compiled only for x86, which also lets the test release its pictures before reporting a mismatch.
…ards The guards moved three long test functions the line-keyed baseline tracks (ref_calc_psnrhvs, ref_picture_to_linear_rgb, test_ptlr_one), so the audit reported them as new while debt fell from 1,627 to 1,623 infractions. Recorded with the pinned engine (praetor e4b35cb) from a clean clone.
lusoris
force-pushed
the
fix/no-asm-test-warnings
branch
from
September 19, 2026 08:47
04fab82 to
f90e0a6
Compare
This was referenced Sep 30, 2026
lusoris
added a commit
that referenced
this pull request
Sep 30, 2026
At the coarsest of CAMBI's five scales a wide, short input has fewer rows than half the window plus one (pad_size + 1 rows): 1920x128 leaves 8 rows against pad_size 11. The c-values walk ran its first pass and its top edge for pad_size rows and started its bottom edge at height - pad_size whatever the height, so it read image and mask rows past both ends of the frame and wrote them into c_values (Netflix/vmaf#1628). Under ASan, master fails at 1920x2, 1920x16, 1920x64, 1920x128, 1920x160 and 3840x128 at every dispatch level; a release build aborts or segfaults on 1921x129 4:4:4. Port the upstream fix (Netflix/vmaf#1629) to calculate_c_values() in cambi.c and to the upstream-mirror calculate_c_values_avx2(), and give cambi_calculate_c_values_frame(), the walk the dispatched AVX2 scan, AVX-512 and NEON drivers share, the same three bounds: first pass i < MIN(pad_size, height) top edge i < MIN(pad_size + 1, height) bottom edge i = MAX(height - pad_size, 0) With at least pad_size + 1 rows at every scale the bounds are the old ones. cambi and cambi=full_ref=true scores are identical to master at --precision max on the Netflix pairs, both checkerboard pairs, 200 frames of BBB 3840x2160 and noise and ramp inputs of standard sizes, at the AVX-512, AVX2 and C dispatch levels. Frames with fewer than pad_size + 1 rows at the coarsest scale that completed on scalar master while reading out of bounds now score differently (e.g. 3-frame 8-bit ramps: 3840x128 moves 19.544347 -> 19.512269, 1920x160 moves 22.270340 -> 22.267602, and 3840x256 moves 21.778393 -> 21.769946). test_calculate_c_values_short_frame runs every driver the host has on views of 1 to 10 rows into a taller picture: rows outside the frame must keep a sentinel, and every in-frame c-value must equal a from-scratch window histogram. On master it fails for 1 to 4 rows on all five drivers without a sanitizer. test_cambi_stage_simd now also sweeps 1-row and pad-row frames. test_cambi's AVX2 parity check had stopped running again: #1483 merged first and #1479 lost its code change when rebased onto #1483, leaving only the comment behind vmaf_get_cpu_flags(). It now reads CPUID via vmaf_get_cpu_flags_x86(). docs/metrics/cambi.md gains a frame-size section, and its window_size default is corrected to the code's 65. docs/state.md closes T-CAMBI-SHORT-FRAME-OOB-2026-09-30 and T-CAMBI-AVX2-PARITY-GATE-REVERTED-2026-09-30, and opens T-CAMBI-NARROW-FRAME-COLUMNS-2026-09-30 and T-CLI-PRE-REGISTRATION-OPTS-DICT-LEAK-2026-09-30 as RC2 stabilisation. core/src/feature/x86/cambi_avx2.c carries an ADR-1256 cppcheck suppression for the mutable callback ABI.
lusoris
added a commit
that referenced
this pull request
Sep 30, 2026
At the coarsest of CAMBI's five scales a wide, short input can have no more rows than pad_size, half the window: 1920x128 leaves 8 rows against pad_size 11, and with the default window every height up to 176 at 1920 wide (352 at 3840) is affected. The c-values walk ran its first pass and its top edge for pad_size rows and started its bottom edge at height - pad_size whatever the height, so it read image and mask rows past both ends of the frame and wrote them into c_values (Netflix/vmaf#1628). Under ASan, master fails at 1920x2, 1920x16, 1920x64, 1920x128, 1920x160 and 3840x128 at every dispatch level; a release build aborts or segfaults on 1920x64, 1920x160, 2560x224, 3840x256 and 1921x129 4:4:4. Port the upstream fix (Netflix/vmaf#1629) to calculate_c_values() in cambi.c and to the upstream-mirror calculate_c_values_avx2(), and give cambi_calculate_c_values_frame(), the walk the dispatched AVX2 scan, AVX-512 and NEON drivers share, the same three bounds: first pass i < MIN(pad_size, height) top edge i < MIN(pad_size + 1, height) bottom edge i = MAX(height - pad_size, 0) The same walks had the column version of the bug: the scalar and AVX2-mirror first column loops ran to pad_size whatever the width, so on a scale with fewer than pad_size columns (default window: up to 80 wide at 1080 high, 160 at 1920 high) they counted columns past the frame. decimate() works in place, so those columns hold the previous scale's pixels, inside the stride, where no sanitizer sees the read. The shared SIMD walk never visited them, so --cpumask 63 and the default dispatch disagreed, and so did the CUDA, HIP and Metal twins, which run the scalar walk on the host. All eight loops now run to MIN(pad_size, width). This column bound goes beyond upstream Netflix/vmaf#1629, which bounds only the rows. Upstream has the same column loops. Scores are identical to master at --precision max, at the AVX-512, AVX2 and C dispatch levels, for every size the old loops handled: the Netflix pairs, both checkerboard pairs, BBB 3840x2160, and ramp and noise inputs at 1920x176, 2560x240, 3840x352, 96x1080 and 1920x1080. Short frames that master completed on the C path while reading outside the frame change (3840x128 horizontal ramp 19.544347 -> 19.512269). Scores change for frames narrower than pad_size at some scale (measured: 64x1920 vertical ramp master 14.975700714938673 vs branch 14.964394451743877 on the C path; the SIMD paths already agreed, giving 14.964394451743877 on both; another vertical ramp variant moves from 16.141046 to 16.131541; cambi_cuda on the RTX 4090 and cambi_hip on gfx1036 give the new CPU score bit for bit). ADR-1393 records clipping over rejecting such frames in init(); Research-2132 has the measurements. test_calculate_c_values_short_frame and test_calculate_c_values_narrow_frame run every driver the host has on 1 to 10 rows and 1 to pad + 2 columns against a from-scratch clipped-window histogram and a sentinel margin. On master sources the short test fails for 1 to 4 rows on all five drivers without a sanitizer; with the column loops unbounded the narrow test fails on the scalar walk, and with only the AVX2 mirror unbounded on that walk. test_cambi_stage_simd also sweeps 1-row and pad-row frames. test_cambi's AVX2 parity check never ran on master: #1479 changed its gate to vmaf_get_cpu_flags_x86(), but #1483 merged first, and when #1479 was rebased onto it the branch kept its comment and took #1483's helper with the old vmaf_get_cpu_flags() gate. It now reads CPUID. docs/state.md closes T-CAMBI-SHORT-FRAME-OOB-2026-09-30, T-CAMBI-NARROW-FRAME-COLUMNS-2026-09-30 and T-CAMBI-AVX2-PARITY-GATE-LOST-IN-REBASE-2026-09-30, and opens T-CLI-PRE-REGISTRATION-OPTS-DICT-LEAK-2026-09-30 (fix in #1647). calculate_c_values_scan_avx2() carries a cited cppcheck suppression: its non-const picture comes from upstream's VmafCalcCValues callback type. core/test/meson.build raises test_gpu_public_header_docs timeout to 120s for Windows MinGW64.
lusoris
added a commit
that referenced
this pull request
Oct 1, 2026
At the coarsest of CAMBI's five scales a wide, short input can have no more rows than pad_size, half the window: 1920x128 leaves 8 rows against pad_size 11, and with the default window every height up to 176 at 1920 wide (352 at 3840) is affected. The c-values walk ran its first pass and its top edge for pad_size rows and started its bottom edge at height - pad_size whatever the height, so it read image and mask rows past both ends of the frame and wrote them into c_values (Netflix/vmaf#1628). Under ASan, master fails at 1920x2, 1920x16, 1920x64, 1920x128, 1920x160 and 3840x128 at every dispatch level; a release build aborts or segfaults on 1920x64, 1920x160, 2560x224, 3840x256 and 1921x129 4:4:4. Port the upstream fix (Netflix/vmaf#1629) to calculate_c_values() in cambi.c and to the upstream-mirror calculate_c_values_avx2(), and give cambi_calculate_c_values_frame(), the walk the dispatched AVX2 scan, AVX-512 and NEON drivers share, the same three bounds: first pass i < MIN(pad_size, height) top edge i < MIN(pad_size + 1, height) bottom edge i = MAX(height - pad_size, 0) The same walks had the column version of the bug: the scalar and AVX2-mirror first column loops ran to pad_size whatever the width, so on a scale with fewer than pad_size columns (default window: up to 80 wide at 1080 high, 160 at 1920 high) they counted columns past the frame. decimate() works in place, so those columns hold the previous scale's pixels, inside the stride, where no sanitizer sees the read. The shared SIMD walk never visited them, so --cpumask 63 and the default dispatch disagreed, and so did the CUDA, HIP and Metal twins, which run the scalar walk on the host. All eight loops now run to MIN(pad_size, width). This column bound goes beyond upstream Netflix/vmaf#1629, which bounds only the rows. Upstream has the same column loops. Scores are identical to master at --precision max, at the AVX-512, AVX2 and C dispatch levels, for every size the old loops handled: the Netflix pairs, both checkerboard pairs, BBB 3840x2160, and ramp and noise inputs at 1920x176, 2560x240, 3840x352, 96x1080 and 1920x1080. Short frames that master completed on the C path while reading outside the frame change (3840x128 horizontal ramp 19.544347 -> 19.512269). Scores change for frames narrower than pad_size at some scale (measured: 64x1920 vertical ramp master 14.975700714938673 vs branch 14.964394451743877 on the C path; the SIMD paths already agreed, giving 14.964394451743877 on both; another vertical ramp variant moves from 16.141046 to 16.131541; cambi_cuda on the RTX 4090 and cambi_hip on gfx1036 give the new CPU score bit for bit). ADR-1393 records clipping over rejecting such frames in init(); Research-2132 has the measurements. test_calculate_c_values_short_frame and test_calculate_c_values_narrow_frame run every driver the host has on 1 to 10 rows and 1 to pad + 2 columns against a from-scratch clipped-window histogram and a sentinel margin. On master sources the short test fails for 1 to 4 rows on all five drivers without a sanitizer; with the column loops unbounded the narrow test fails on the scalar walk, and with only the AVX2 mirror unbounded on that walk. test_cambi_stage_simd also sweeps 1-row and pad-row frames. test_cambi's AVX2 parity check never ran on master: #1479 changed its gate to vmaf_get_cpu_flags_x86(), but #1483 merged first, and when #1479 was rebased onto it the branch kept its comment and took #1483's helper with the old vmaf_get_cpu_flags() gate. It now reads CPUID. docs/state.md closes T-CAMBI-SHORT-FRAME-OOB-2026-09-30, T-CAMBI-NARROW-FRAME-COLUMNS-2026-09-30 and T-CAMBI-AVX2-PARITY-GATE-LOST-IN-REBASE-2026-09-30, and opens T-CLI-PRE-REGISTRATION-OPTS-DICT-LEAK-2026-09-30 (fix in #1647). calculate_c_values_scan_avx2() carries a cited cppcheck suppression: its non-const picture comes from upstream's VmafCalcCValues callback type. core/test/meson.build raises test_gpu_public_header_docs timeout to 120s for Windows MinGW64.
lusoris
added a commit
that referenced
this pull request
Oct 1, 2026
At the coarsest of CAMBI's five scales a wide, short input can have no more rows than pad_size, half the window: 1920x128 leaves 8 rows against pad_size 11, and with the default window every height up to 176 at 1920 wide (352 at 3840) is affected. The c-values walk ran its first pass and its top edge for pad_size rows and started its bottom edge at height - pad_size whatever the height, so it read image and mask rows past both ends of the frame and wrote them into c_values (Netflix/vmaf#1628). Under ASan, master fails at 1920x2, 1920x16, 1920x64, 1920x128, 1920x160 and 3840x128 at every dispatch level; a release build aborts or segfaults on 1920x64, 1920x160, 2560x224, 3840x256 and 1921x129 4:4:4. Port the upstream fix (Netflix/vmaf#1629) to calculate_c_values() in cambi.c and to the upstream-mirror calculate_c_values_avx2(), and give cambi_calculate_c_values_frame(), the walk the dispatched AVX2 scan, AVX-512 and NEON drivers share, the same three bounds: first pass i < MIN(pad_size, height) top edge i < MIN(pad_size + 1, height) bottom edge i = MAX(height - pad_size, 0) The same walks had the column version of the bug: the scalar and AVX2-mirror first column loops ran to pad_size whatever the width, so on a scale with fewer than pad_size columns (default window: up to 80 wide at 1080 high, 160 at 1920 high) they counted columns past the frame. decimate() works in place, so those columns hold the previous scale's pixels, inside the stride, where no sanitizer sees the read. The shared SIMD walk never visited them, so --cpumask 63 and the default dispatch disagreed, and so did the CUDA, HIP and Metal twins, which run the scalar walk on the host. All eight loops now run to MIN(pad_size, width). This column bound goes beyond upstream Netflix/vmaf#1629, which bounds only the rows. Upstream has the same column loops. Scores are identical to master at --precision max, at the AVX-512, AVX2 and C dispatch levels, for every size the old loops handled: the Netflix pairs, both checkerboard pairs, BBB 3840x2160, and ramp and noise inputs at 1920x176, 2560x240, 3840x352, 96x1080 and 1920x1080. Short frames that master completed on the C path while reading outside the frame change (3840x128 horizontal ramp 19.544347 -> 19.512269). Scores change for frames narrower than pad_size at some scale (measured: 64x1920 vertical ramp master 14.975700714938673 vs branch 14.964394451743877 on the C path; the SIMD paths already agreed, giving 14.964394451743877 on both; another vertical ramp variant moves from 16.141046 to 16.131541; cambi_cuda on the RTX 4090 and cambi_hip on gfx1036 give the new CPU score bit for bit). ADR-1393 records clipping over rejecting such frames in init(); Research-2132 has the measurements. test_calculate_c_values_short_frame and test_calculate_c_values_narrow_frame run every driver the host has on 1 to 10 rows and 1 to pad + 2 columns against a from-scratch clipped-window histogram and a sentinel margin. On master sources the short test fails for 1 to 4 rows on all five drivers without a sanitizer; with the column loops unbounded the narrow test fails on the scalar walk, and with only the AVX2 mirror unbounded on that walk. test_cambi_stage_simd also sweeps 1-row and pad-row frames. test_cambi's AVX2 parity check never ran on master: #1479 changed its gate to vmaf_get_cpu_flags_x86(), but #1483 merged first, and when #1479 was rebased onto it the branch kept its comment and took #1483's helper with the old vmaf_get_cpu_flags() gate. It now reads CPUID. docs/state.md closes T-CAMBI-SHORT-FRAME-OOB-2026-09-30, T-CAMBI-NARROW-FRAME-COLUMNS-2026-09-30 and T-CAMBI-AVX2-PARITY-GATE-LOST-IN-REBASE-2026-09-30, and opens T-CLI-PRE-REGISTRATION-OPTS-DICT-LEAK-2026-09-30 (fix in #1647). calculate_c_values_scan_avx2() carries a cited cppcheck suppression: its non-const picture comes from upstream's VmafCalcCValues callback type. core/test/meson.build raises test_gpu_public_header_docs timeout to 120s for Windows MinGW64.
lusoris
added a commit
that referenced
this pull request
Oct 1, 2026
At the coarsest of CAMBI's five scales a wide, short input can have no more rows than pad_size, half the window: 1920x128 leaves 8 rows against pad_size 11, and with the default window every height up to 176 at 1920 wide (352 at 3840) is affected. The c-values walk ran its first pass and its top edge for pad_size rows and started its bottom edge at height - pad_size whatever the height, so it read image and mask rows past both ends of the frame and wrote them into c_values (Netflix/vmaf#1628). Under ASan, master fails at 1920x2, 1920x16, 1920x64, 1920x128, 1920x160 and 3840x128 at every dispatch level; a release build aborts or segfaults on 1920x64, 1920x160, 2560x224, 3840x256 and 1921x129 4:4:4. Port the upstream fix (Netflix/vmaf#1629) to calculate_c_values() in cambi.c and to the upstream-mirror calculate_c_values_avx2(), and give cambi_calculate_c_values_frame(), the walk the dispatched AVX2 scan, AVX-512 and NEON drivers share, the same three bounds: first pass i < MIN(pad_size, height) top edge i < MIN(pad_size + 1, height) bottom edge i = MAX(height - pad_size, 0) The same walks had the column version of the bug: the scalar and AVX2-mirror first column loops ran to pad_size whatever the width, so on a scale with fewer than pad_size columns (default window: up to 80 wide at 1080 high, 160 at 1920 high) they counted columns past the frame. decimate() works in place, so those columns hold the previous scale's pixels, inside the stride, where no sanitizer sees the read. The shared SIMD walk never visited them, so --cpumask 63 and the default dispatch disagreed, and so did the CUDA, HIP and Metal twins, which run the scalar walk on the host. All eight loops now run to MIN(pad_size, width). This column bound goes beyond upstream Netflix/vmaf#1629, which bounds only the rows. Upstream has the same column loops. Scores are identical to master at --precision max, at the AVX-512, AVX2 and C dispatch levels, for every size the old loops handled: the Netflix pairs, both checkerboard pairs, BBB 3840x2160, and ramp and noise inputs at 1920x176, 2560x240, 3840x352, 96x1080 and 1920x1080. Short frames that master completed on the C path while reading outside the frame change (3840x128 horizontal ramp 19.544347 -> 19.512269). Scores change for frames narrower than pad_size at some scale (measured: 64x1920 vertical ramp master 14.975700714938673 vs branch 14.964394451743877 on the C path; the SIMD paths already agreed, giving 14.964394451743877 on both; another vertical ramp variant moves from 16.141046 to 16.131541; cambi_cuda on the RTX 4090 and cambi_hip on gfx1036 give the new CPU score bit for bit). ADR-1393 records clipping over rejecting such frames in init(); Research-2132 has the measurements. test_calculate_c_values_short_frame and test_calculate_c_values_narrow_frame run every driver the host has on 1 to 10 rows and 1 to pad + 2 columns against a from-scratch clipped-window histogram and a sentinel margin. On master sources the short test fails for 1 to 4 rows on all five drivers without a sanitizer; with the column loops unbounded the narrow test fails on the scalar walk, and with only the AVX2 mirror unbounded on that walk. test_cambi_stage_simd also sweeps 1-row and pad-row frames. test_cambi's AVX2 parity check never ran on master: #1479 changed its gate to vmaf_get_cpu_flags_x86(), but #1483 merged first, and when #1479 was rebased onto it the branch kept its comment and took #1483's helper with the old vmaf_get_cpu_flags() gate. It now reads CPUID. docs/state.md closes T-CAMBI-SHORT-FRAME-OOB-2026-09-30, T-CAMBI-NARROW-FRAME-COLUMNS-2026-09-30 and T-CAMBI-AVX2-PARITY-GATE-LOST-IN-REBASE-2026-09-30, and opens T-CLI-PRE-REGISTRATION-OPTS-DICT-LEAK-2026-09-30 (fix in #1647). calculate_c_values_scan_avx2() carries a cited cppcheck suppression: its non-const picture comes from upstream's VmafCalcCValues callback type. core/test/meson.build raises test_gpu_public_header_docs timeout to 120s for Windows MinGW64.
lusoris
added a commit
that referenced
this pull request
Oct 1, 2026
* fix(cambi): keep the c-values walks inside short and narrow frames At the coarsest of CAMBI's five scales a wide, short input can have no more rows than pad_size, half the window: 1920x128 leaves 8 rows against pad_size 11, and with the default window every height up to 176 at 1920 wide (352 at 3840) is affected. The c-values walk ran its first pass and its top edge for pad_size rows and started its bottom edge at height - pad_size whatever the height, so it read image and mask rows past both ends of the frame and wrote them into c_values (Netflix/vmaf#1628). Under ASan, master fails at 1920x2, 1920x16, 1920x64, 1920x128, 1920x160 and 3840x128 at every dispatch level; a release build aborts or segfaults on 1920x64, 1920x160, 2560x224, 3840x256 and 1921x129 4:4:4. Port the upstream fix (Netflix/vmaf#1629) to calculate_c_values() in cambi.c and to the upstream-mirror calculate_c_values_avx2(), and give cambi_calculate_c_values_frame(), the walk the dispatched AVX2 scan, AVX-512 and NEON drivers share, the same three bounds: first pass i < MIN(pad_size, height) top edge i < MIN(pad_size + 1, height) bottom edge i = MAX(height - pad_size, 0) The same walks had the column version of the bug: the scalar and AVX2-mirror first column loops ran to pad_size whatever the width, so on a scale with fewer than pad_size columns (default window: up to 80 wide at 1080 high, 160 at 1920 high) they counted columns past the frame. decimate() works in place, so those columns hold the previous scale's pixels, inside the stride, where no sanitizer sees the read. The shared SIMD walk never visited them, so --cpumask 63 and the default dispatch disagreed, and so did the CUDA, HIP and Metal twins, which run the scalar walk on the host. All eight loops now run to MIN(pad_size, width). This column bound goes beyond upstream Netflix/vmaf#1629, which bounds only the rows. Upstream has the same column loops. Scores are identical to master at --precision max, at the AVX-512, AVX2 and C dispatch levels, for every size the old loops handled: the Netflix pairs, both checkerboard pairs, BBB 3840x2160, and ramp and noise inputs at 1920x176, 2560x240, 3840x352, 96x1080 and 1920x1080. Short frames that master completed on the C path while reading outside the frame change (3840x128 horizontal ramp 19.544347 -> 19.512269). Scores change for frames narrower than pad_size at some scale (measured: 64x1920 vertical ramp master 14.975700714938673 vs branch 14.964394451743877 on the C path; the SIMD paths already agreed, giving 14.964394451743877 on both; another vertical ramp variant moves from 16.141046 to 16.131541; cambi_cuda on the RTX 4090 and cambi_hip on gfx1036 give the new CPU score bit for bit). ADR-1393 records clipping over rejecting such frames in init(); Research-2132 has the measurements. test_calculate_c_values_short_frame and test_calculate_c_values_narrow_frame run every driver the host has on 1 to 10 rows and 1 to pad + 2 columns against a from-scratch clipped-window histogram and a sentinel margin. On master sources the short test fails for 1 to 4 rows on all five drivers without a sanitizer; with the column loops unbounded the narrow test fails on the scalar walk, and with only the AVX2 mirror unbounded on that walk. test_cambi_stage_simd also sweeps 1-row and pad-row frames. test_cambi's AVX2 parity check never ran on master: #1479 changed its gate to vmaf_get_cpu_flags_x86(), but #1483 merged first, and when #1479 was rebased onto it the branch kept its comment and took #1483's helper with the old vmaf_get_cpu_flags() gate. It now reads CPUID. docs/state.md closes T-CAMBI-SHORT-FRAME-OOB-2026-09-30, T-CAMBI-NARROW-FRAME-COLUMNS-2026-09-30 and T-CAMBI-AVX2-PARITY-GATE-LOST-IN-REBASE-2026-09-30, and opens T-CLI-PRE-REGISTRATION-OPTS-DICT-LEAK-2026-09-30 (fix in #1647). calculate_c_values_scan_avx2() carries a cited cppcheck suppression: its non-const picture comes from upstream's VmafCalcCValues callback type. core/test/meson.build raises test_gpu_public_header_docs timeout to 120s for Windows MinGW64. * docs: regenerate the indexes and the citation map after rebasing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Builds that CI does not gate on were not warning-free, and one NEON file had never been linted.
-Denable_asm=falsebuilds emitted about 30-Wunused-function/-Wunused-const-variable/-Wunused-variablewarnings in 10 SIMD test files. Helpers were defined unconditionally while every caller sat under an ISA guard. Each helper now sits under exactly the union of its callers' guards; nothing is deleted or suppressed. Warnings go from 30 to 0, and the set of tests that runs is unchanged on every configuration:-Denable_asm=falsex86-64 133/133, default x86-64 137/137, aarch64 under qemu 135/135.vif_neon.c. Both VIF statistic kernels advanced ani_dst_stridecounter every row and never read it; upstream has the same dead code. It is removed.vif_neon.chad 36 clang-tidy findings, which no CI lane measures because the cpu lane is x86-only. Touching the file meant cleaning it: the four kernels are now row loops overstatic FORCE_INLINEhelpers, in the style ofvif_avx2.c, and the missingvif_neon.hinclude fixes the linkage findings. It is at 0 findings and 0 NOLINTs, and cppcheck is clean. NEON output is byte-identical: 68/68--precision maxruns match the previous binary per compiler (GCC and Clang cross builds under qemu). The inputs cover 8/10/12-bit, odd and tiny sizes, and four VIF and model configurations. NEON also still equals scalar on all 34 pairs.test_calculate_c_values_scalar_avx2_paritystays under the 60-line HISS-04 limit: its AVX2 leg is now an x86-only helper, and the test releases its pictures before reporting a mismatch..standards-baseline.jsonis re-recorded with the pinned engine from a clean clone. The guards moved three long test functions the line-keyed baseline tracks; debt fell from 1,627 to 1,623.no docs needed: test scaffolding, a dead-variable removal and a behaviour-preserving refactor; no user-visible change.
Type
feat— new featurefix— bug fixperf— performance improvementrefactor— no behavior changedocs— documentation onlytest— test-onlybuild/ci— tooling / infraport— cherry-pick from upstream Netflix/vmafsycl/cuda/simd— backend-specificChecklist
make format && make lintis green locally: pre-commit andpraetorctl auditpass; clang-tidy 0 findings and 0 uncited NOLINTs on every touched file (CPU lane, and a Clang aarch64 cross build forvif_neon.c).meson test -C build: counts as above;test_vif_neonpasses on both aarch64 cross builds./cross-backend-diffand the worst ULP is ≤ 2: 0; byte-identical NEON output before and after, and vs scalar..c/.cpp/.cu/.h/.hpp, it has the appropriate license header: no new files.!orBREAKING CHANGE:: not breaking.docs/adr/_index_fragments/: no ADR.Bug-status hygiene (ADR-0165)
docs/state.md:T-NO-ASM-SIMD-TEST-WARNINGS-2026-09-18closed.Netflix golden-data gate (ADR-0024)
assertAlmostEqual(...)score in the Netflix golden Python tests.Deep-dive deliverables (ADR-0108)
changelog.d/fixed/no-asm-simd-test-unused-warnings.md.docs/rebase-notes.md: helper guards mirror theirrun_tests()call sites;vif_neon.cis split into helpers.Reproducer
Known follow-ups