Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ jobs:
os: ubuntu-latest
rust: stable
cargo_args: '--no-default-features'
- name: Linux x86_64 (native CPU)
os: ubuntu-latest
rust: stable
cargo_args: '--all-features'
rustflags: '-C target-cpu=native'
- name: Linux ARM64
os: ubuntu-24.04-arm
rust: stable
Expand Down Expand Up @@ -78,6 +83,8 @@ jobs:

- name: Build and test
run: cargo test --verbose ${{ matrix.cargo_args }}
env:
RUSTFLAGS: ${{ matrix.rustflags || '' }}

build-windows:
name: Windows x86_64 (GNU)
Expand Down Expand Up @@ -111,6 +118,45 @@ jobs:
- name: Build and test
run: cargo test --target x86_64-pc-windows-gnu --verbose

build-windows-msvc:
name: Windows x86_64 (MSVC)
runs-on: windows-latest

steps:
- uses: actions/checkout@v6

- uses: actions/setup-python@v6
with:
python-version: '3.x'

- name: Install native dependencies
run: |
python -m pip install meson ninja
choco install nasm --no-progress -y
$tools = Join-Path $env:RUNNER_TEMP 'vmaf-tools'
New-Item -ItemType Directory -Force -Path $tools | Out-Null
Copy-Item 'C:\Program Files\Git\usr\bin\xxd.exe' $tools
$tools | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
& (Join-Path $tools 'xxd.exe') -v

- name: Set up MSVC
uses: ilammy/msvc-dev-cmd@v1

- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
targets: x86_64-pc-windows-msvc

- name: Build and test
run: cargo test --target x86_64-pc-windows-msvc --verbose

- name: Build and test with native CPU tuning
run: cargo test --target x86_64-pc-windows-msvc --verbose
env:
CARGO_TARGET_DIR: target/native
RUSTFLAGS: -C target-cpu=native

build-ios:
name: iOS compile and link
runs-on: macos-latest
Expand Down Expand Up @@ -241,6 +287,11 @@ jobs:
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings

- name: Test build configuration
run: |
rustc --edition=2021 --test build.rs -o target/build-script-tests
target/build-script-tests

- name: Verify package
run: cargo package

Expand Down
9 changes: 6 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@ This repository publishes `vmaf-head-sys`, raw Rust FFI bindings to a statically
## Generated And Vendored Files

- Do not edit `src/bindings.rs` by hand. Change `vendor_vmaf.py`, then run `python3 vendor_vmaf.py --bindings-only`.
- Update `vendored/vmaf` only through `python3 vendor_vmaf.py`. Preserve upstream source, licenses, formatting, and model data byte-for-byte.
- Update `vendored/vmaf` only through `python3 vendor_vmaf.py`. Keep local source changes in ordered `patches/*.patch` files; the script applies them after copying upstream. Never edit the vendored tree by hand.
- Keep patches focused, preserve untouched upstream source and model data byte-for-byte, and fail clearly when a patch no longer applies.
- `vendored/VMAF_VERSION` must identify the exact upstream commit. Verify it with `python3 check_vmaf_version.py`.
- Keep bindgen output target-independent. In particular, retain `--no-layout-tests` so committed bindings compile on 32-bit targets.

## Native Build Invariants

- `build.rs` owns Meson configuration, static linking, platform runtime libraries, and generated iOS/Android cross files.
- Meson and Ninja are required for native builds. `xxd` is required for built-in models.
- x86 and x86_64 builds always compile NASM and AVX2 paths, including with `--no-default-features`; runtime CPUID dispatch must remain enabled.
- Meson and Ninja are required for native builds. `xxd` is required for built-in models. NASM 2.14 or later is required on x86 targets so AVX-512 support cannot silently degrade.
- x86 and x86_64 builds compile NASM and AVX2/AVX-512 paths, including with `--no-default-features` and MSVC; runtime CPUID and operating-system dispatch checks must remain enabled.
- `build.rs` propagates Rust native CPU and explicit x86 target-feature settings to the C/C++ compiler. Host-native flags must never be applied while cross-compiling.
- MSVC builds use private pthread and POSIX translation headers added by the vendor patch under `vendored/vmaf/libvmaf/src/compat/msvc`.
- AArch64 builds use VMAF's NEON paths when the `asm` feature is enabled.
- Preserve compile-and-link support for every target in `.github/workflows/ci.yml`, including iOS device/simulators and all four Android ABIs.
- Android uses NDK libc++ (`c++_shared`), not GNU `stdc++`. NDK r29 x86 links require Clang builtins through `cargo-ndk --link-builtins`.
Expand Down
34 changes: 32 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Building requires:
- Meson and Ninja
- A C and C++ compiler
- `xxd` when `built-in-models` is enabled
- NASM on x86 and x86_64 platforms
- NASM 2.14 or later on x86 and x86_64 platforms

CUDA is intentionally disabled. This crate binds the portable CPU API and does not expose `libvmaf_cuda.h`.

Expand All @@ -30,7 +30,23 @@ CUDA is intentionally disabled. This crate binds the portable CPU API and does n
- `asm` - enable optional architecture-specific optimizations (default)
- `float` - compile floating-point feature extractors

On x86 and x86_64, NASM support and AVX2 kernels are always built, including with `--no-default-features`. VMAF still uses CPUID runtime dispatch, so AVX2 instructions execute only when both the CPU and operating system support them. This avoids illegal-instruction crashes on older x86 systems.
On x86 and x86_64, NASM support and AVX2/AVX-512 kernels are always built, including with `--no-default-features` and MSVC. VMAF uses CPUID and operating-system state checks at runtime, so optimized instructions execute only on supported machines. Portable builds therefore include the fastest available VMAF kernels without raising the binary's baseline CPU requirement.

MSVC builds use a private Windows-native pthread translation layer. The optimized x86 sources use the same runtime dispatch as Windows GNU builds.

AArch64 builds use VMAF's NEON kernels when the `asm` feature is enabled. ARMv7 feature kernels remain scalar.

### CPU tuning

The native library is compiled with Meson's release optimization level. Rust target settings are also propagated to the C and C++ compilers:

```bash
RUSTFLAGS="-C target-cpu=native" cargo build --release
```

For a host build, `target-cpu=native` adds `-march=native -mtune=native` on x86 GCC/Clang, `-mcpu=native` on ARM GCC/Clang, or the highest compatible resolved `/arch:AVX*` level on MSVC. Explicit Rust x86 target features such as `+avx2`, `+fma`, and `+avx512f` are forwarded to GCC/Clang as matching compiler flags. MSVC selects an aggregate `/arch` level only when Rust enables every feature that compiler level may assume.

Native and explicit target-feature tuning may raise the application's baseline CPU requirement. C/C++ tuning is intentionally ignored for cross-compilation; runtime-dispatched VMAF kernels remain enabled in cross-built x86 binaries.

## Usage

Expand All @@ -57,6 +73,8 @@ CI compiles and links these mobile targets:
- `x86_64-linux-android`
- `i686-linux-android` (`x86`)

CI also builds and runs the test suite for both `x86_64-pc-windows-gnu` and `x86_64-pc-windows-msvc`.

For Android final binaries, `c++_shared` must be packaged with the application. With `cargo-ndk` and NDK r29, use:

```bash
Expand All @@ -72,6 +90,18 @@ The vendored VMAF source is tracked in `vendored/VMAF_VERSION`. Run the update s
python vendor_vmaf.py
```

The update script applies the ordered patches under `patches/` after copying upstream VMAF. Patch failures stop the update so upstream changes cannot silently drop local platform fixes.

The current patch set keeps upstream changes individually attributable:

- `ya_getopt.patch` - [Netflix/VMAF#1410](https://github.com/Netflix/vmaf/pull/1410)
- `msvc_no_vla.patch` - [Netflix/VMAF#1428](https://github.com/Netflix/vmaf/pull/1428)
- `avx2_simd_portability.patch` - [Netflix/VMAF#1475](https://github.com/Netflix/vmaf/pull/1475)
- `vif_void_pointer.patch` - [Netflix/VMAF#1476](https://github.com/Netflix/vmaf/pull/1476)
- `msvc_pthread.patch` and `msvc_simd_build.patch` - private Windows threading and SIMD build integration
- `avx2_fma_dispatch.patch` - require FMA before selecting VMAF's AVX2/FMA kernels
- `vif_size_overflow.patch` - checked copy-size arithmetic

Regenerate bindings without downloading VMAF:

```bash
Expand Down
Loading
Loading