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 viaOnceLockon first call; free afterwards.detect_cpu_features()— the sameOnceLockunder 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:
| File | Target | Representative kernels |
|---|---|---|
avx512.rs | x86-64 AVX-512F/BW/VL/VNNI | bgra_to_rgba_avx512, hsum_f32_avx512, scale_i16_avx512, sad_8x8_vnni, sad_4x4_vnni |
x86.rs | x86-64 AVX2 / SSE4.2 | AVX2 bilinear scale, SSE4.2 YUV→RGB BT.601 |
neon.rs | ARM aarch64 NEON | has_neon probe; NEON kernels |
arm.rs | ARM scalar / fallback | Portable ARM wrappers |
amx.rs | Apple AMX (experimental) | AMX tile routines |
portable.rs | std::simd portable path | Cross-platform 128-bit fallbacks |
scalar.rs / scalar_fallback.rs | Any target | Reference 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-codechas its own hand-written WASM SIMD128 backend atcrates/oximedia-codec/src/simd/wasm.rs, gated on#[cfg(target_arch = "wasm32")]and#[target_feature(enable = "simd128")], usingcore::arch::wasm32intrinsics directly (not anything fromoximedia-simd). It implements the crate's ownSimdOps/SimdOpsExttraits and falls back toScalarFallbackwhensimd128is unavailable or the target isn'twasm32.- The
web/workspace (oximedia-web-coreand friends, seeweb/README.md) achieves WASM SIMD acceleration a different way again: no hand-writtencore::arch::wasm32intrinsics at all. Kernels are written as ordinary safe Rust overchunks_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 everyweb/crates/*crate at#![forbid(unsafe_code)]with zerounsafeblocks, 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:
#[cfg(target_arch = "x86_64")]block that probesis_x86_feature_detected!and calls the bestunsafeintrinsic kernel fromavx512.rs/x86.rs.- On match,
returnafter the unsafe call — no further fallback runs. - If no SIMD path matched, fall through to the scalar kernel
(
avx512::*_scalarorscalar::*).
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
- Implement the scalar reference in
scalar.rs(or<backend>::*_scalar). - 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. - Add a safe wrapper in
dispatch.rsthat probesis_x86_feature_detected!(x86) orstd::arch::is_aarch64_feature_detected!(aarch64) and calls the intrinsic underunsafe { ... }, then falls back to scalar. - Add a property test in
fuzz_targets.rsorscalar_equivalence.rsasserting 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:
- Lives inside an
#[cfg(target_arch = "...")]guard matching the intrinsic family. - Is additionally guarded by a runtime
is_x86_feature_detected!(oris_aarch64_feature_detected!) check on the specific feature(s) used. - Has a
SAFETY:comment naming the exact CPU features it relies on. - Is the only statement in its
unsafeblock — 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
docs/rate_control.md— the encoder hot loops that these SIMD kernels back.docs/codec_status.md— decoder-side status.docs/wave5_deltas.md— what 0.1.5 added.