SIMD Dispatch

July 14, 2026 · View on GitHub

oximedia-simd runtime-dispatches hot-loop kernels to the best available SIMD backend per CPU. Paths are relative to crates/oximedia-simd/src/.

CPU feature detection

CpuFeatures is defined at src/lib.rs:123. It carries per-feature flags:

  • avx2, avx512f, avx512bw, avx512vl — x86-64.
  • sse4_2 — x86-64 fallback tier.
  • neon — ARM aarch64.

Two entry points:

  • CpuFeatures::detect() — caches via OnceLock on first call; free afterwards.
  • detect_cpu_features() — the same OnceLock under the hood.

The cached value is populated once by an #[cfg(target_arch = "x86_64")] branch calling is_x86_feature_detected!("avx2") (etc.) or an #[cfg(target_arch = "aarch64")] branch using std::arch::is_aarch64_feature_detected!("neon"). On any other target, the returned CpuFeatures has every flag false.

CpuFeatures::best_simd_width() returns 512 / 256 / 128 / 64 based on the widest available register tier.

Backend tiers

SIMD kernels are organised as one file per architecture or intrinsic family:

FileTargetRepresentative kernels
avx512.rsx86-64 AVX-512F/BW/VL/VNNIbgra_to_rgba_avx512, hsum_f32_avx512, scale_i16_avx512, sad_8x8_vnni, sad_4x4_vnni
x86.rsx86-64 AVX2 / SSE4.2AVX2 bilinear scale, SSE4.2 YUV→RGB BT.601
neon.rsARM aarch64 NEONhas_neon probe; NEON kernels
arm.rsARM scalar / fallbackPortable ARM wrappers
amx.rsApple AMX (experimental)AMX tile routines
portable.rsstd::simd portable pathCross-platform 128-bit fallbacks
scalar.rs / scalar_fallback.rsAny targetReference scalar reductions used for correctness checks

The dispatch.rs module (covered below) picks between these at runtime.

AVX-512 VNNI tier

sad_8x8_vnni (avx512.rs:1162) and sad_4x4_vnni (avx512.rs:1202) use _mm512_dpbusd_epi32 to fold sum-of-absolute- differences into a single dot-product-and-accumulate. Both require AVX-512F + BW + VNNI; the call sites gate on these three feature flags.

AVX2 tier (dominant x86 path)

Most x86-64 CPUs support AVX2 but not AVX-512. The AVX2 path in x86.rs handles bilinear scale in 8-pixel batches, YUV→RGB fixed-point in 4-pixel strides, _mm256_maddubs_epi16 reductions, and _mm_prefetch(_MM_HINT_T0) cache hints.

SSE4.2 fallback

Pre-Haswell x86-64 falls to SSE4.2 paths in x86.rs. x86.rs is gated on #[cfg(target_arch = "x86_64")] (core::arch::x86_64 intrinsics) and is never compiled on wasm32; see "WASM SIMD128" below for the unrelated, actual WASM SIMD paths.

NEON tier

On aarch64 the neon.rs module provides NEON implementations. neon::has_neon() (re-exported as oximedia_simd::has_neon) returns true on every aarch64 target (NEON is mandatory), false elsewhere.

WASM SIMD128

oximedia-simd itself has no wasm32-specific code path — there is no wasm32 branch anywhere under crates/oximedia-simd/src/, and its CpuFeatures::detect() x86_64/aarch64 cfg arms simply fall through to the "every flag false" default on wasm32-unknown-unknown. oximedia-simd also does not use WASM SIMD128 by way of another crate: oximedia-codec, the workspace's other SIMD-heavy crate, does not depend on oximedia-simd at all (crates/oximedia-codec/Cargo.toml has no such dependency). In other words, any WASM SIMD tier this document previously described as "reusing the SSE4.2 paths, exercised by an oximedia-codec WASM test matrix" does not exist; oximedia-simd's wasm32 builds compile only the portable scalar fallbacks (scalar.rs / scalar_fallback.rs), selected because detect_cpu_features() reports no SIMD tier available.

Two real, independent WASM SIMD paths exist elsewhere in the workspace:

  • oximedia-codec has its own hand-written WASM SIMD128 backend at crates/oximedia-codec/src/simd/wasm.rs, gated on #[cfg(target_arch = "wasm32")] and #[target_feature(enable = "simd128")], using core::arch::wasm32 intrinsics directly (not anything from oximedia-simd). It implements the crate's own SimdOps/SimdOpsExt traits and falls back to ScalarFallback when simd128 is unavailable or the target isn't wasm32.
  • The web/ workspace (oximedia-web-core and friends, see web/README.md) achieves WASM SIMD acceleration a different way again: no hand-written core::arch::wasm32 intrinsics at all. Kernels are written as ordinary safe Rust over chunks_exact / chunks_exact_mut, compiled with -C target-feature=+simd128 (web/.cargo/config.toml) so LLVM autovectorizes the inner loops into SIMD128 instructions. This keeps every web/crates/* crate at #![forbid(unsafe_code)] with zero unsafe blocks, at the cost of depending on the autovectorizer doing a good job rather than hand-tuning intrinsics.

Dispatch module

src/dispatch.rs is the public safe façade. Every function there follows the same three-line pattern:

  1. #[cfg(target_arch = "x86_64")] block that probes is_x86_feature_detected! and calls the best unsafe intrinsic kernel from avx512.rs / x86.rs.
  2. On match, return after the unsafe call — no further fallback runs.
  3. If no SIMD path matched, fall through to the scalar kernel (avx512::*_scalar or scalar::*).

A minimal example (abridged from dispatch.rs):

pub fn bgra_to_rgba(src: &[u8], dst: &mut [u8]) {
    #[cfg(target_arch = "x86_64")]
    {
        if is_x86_feature_detected!("avx512bw") {
            // SAFETY: avx512f + avx512bw confirmed above.
            unsafe { crate::avx512::bgra_to_rgba_avx512(src, dst) };
            return;
        }
    }
    crate::avx512::bgra_to_rgba_scalar(src, dst);
}

Each dispatched function is fully safe in the public API; unsafe appears only inside the cfg-gated branch, always guarded by a runtime feature check.

Adding a new dispatch entry

  1. Implement the scalar reference in scalar.rs (or <backend>::*_scalar).
  2. Implement the SIMD-accelerated version in the appropriate backend file (avx512.rs, x86.rs, neon.rs, ...). Use #[target_feature] on the function so the intrinsics compile.
  3. Add a safe wrapper in dispatch.rs that probes is_x86_feature_detected! (x86) or std::arch::is_aarch64_feature_detected! (aarch64) and calls the intrinsic under unsafe { ... }, then falls back to scalar.
  4. Add a property test in fuzz_targets.rs or scalar_equivalence.rs asserting the SIMD result bit-matches the scalar reference.

Benchmarks

Criterion suite at crates/oximedia-simd/benches/simd_benchmarks.rs covers the main dispatched kernels. Workspace-level benches live in benches/ (codec_bench.rs, filter_benchmark.rs, quality_metrics.rs).

Safety convention

Every unsafe intrinsic block in oximedia-simd:

  1. Lives inside an #[cfg(target_arch = "...")] guard matching the intrinsic family.
  2. Is additionally guarded by a runtime is_x86_feature_detected! (or is_aarch64_feature_detected!) check on the specific feature(s) used.
  3. Has a SAFETY: comment naming the exact CPU features it relies on.
  4. Is the only statement in its unsafe block — no unrelated logic.

The #![deny(unsafe_op_in_unsafe_fn)] attribute at the top of dispatch.rs enforces the last rule at compile time. A correctness test in scalar_equivalence.rs re-runs every dispatched kernel against its scalar reference on random inputs, ensuring the fast path never drifts from the portable path.

See also