#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
mod avx2;
mod rust;
#[cfg(test)]
mod tests;
use std::num::NonZeroUsize;
use crate::util::Pixel;
#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
pub const MAX_REFS_SIZE: usize = 12;
pub type DegrainFn = unsafe fn(
dest: *mut u8,
dest_stride_bytes: NonZeroUsize,
src: *const u8,
src_stride_bytes: NonZeroUsize,
refs: &[*const u8],
refs_strides_bytes: &[NonZeroUsize],
w_src: i32,
w_refs: &[i32],
);
#[must_use]
#[inline]
pub fn select_degrain<T: Pixel, const RADIUS: usize>(
width: NonZeroUsize,
height: NonZeroUsize,
) -> DegrainFn {
#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
if crate::util::has_avx2() {
return select_degrain_avx2::<T, RADIUS>(width, height);
}
select_degrain_rust::<T, RADIUS>(width, height)
}
#[must_use]
fn select_degrain_rust<T: Pixel, const RADIUS: usize>(
width: NonZeroUsize,
height: NonZeroUsize,
) -> DegrainFn {
match (width.get(), height.get()) {
(2, 2) => rust::degrain::<T, RADIUS, 2, 2>,
(2, 4) => rust::degrain::<T, RADIUS, 2, 4>,
(4, 2) => rust::degrain::<T, RADIUS, 4, 2>,
(4, 4) => rust::degrain::<T, RADIUS, 4, 4>,
(4, 8) => rust::degrain::<T, RADIUS, 4, 8>,
(8, 1) => rust::degrain::<T, RADIUS, 8, 1>,
(8, 2) => rust::degrain::<T, RADIUS, 8, 2>,
(8, 4) => rust::degrain::<T, RADIUS, 8, 4>,
(8, 8) => rust::degrain::<T, RADIUS, 8, 8>,
(8, 16) => rust::degrain::<T, RADIUS, 8, 16>,
(16, 1) => rust::degrain::<T, RADIUS, 16, 1>,
(16, 2) => rust::degrain::<T, RADIUS, 16, 2>,
(16, 4) => rust::degrain::<T, RADIUS, 16, 4>,
(16, 8) => rust::degrain::<T, RADIUS, 16, 8>,
(16, 16) => rust::degrain::<T, RADIUS, 16, 16>,
(16, 32) => rust::degrain::<T, RADIUS, 16, 32>,
(32, 8) => rust::degrain::<T, RADIUS, 32, 8>,
(32, 16) => rust::degrain::<T, RADIUS, 32, 16>,
(32, 32) => rust::degrain::<T, RADIUS, 32, 32>,
(32, 64) => rust::degrain::<T, RADIUS, 32, 64>,
(64, 16) => rust::degrain::<T, RADIUS, 64, 16>,
(64, 32) => rust::degrain::<T, RADIUS, 64, 32>,
(64, 64) => rust::degrain::<T, RADIUS, 64, 64>,
(64, 128) => rust::degrain::<T, RADIUS, 64, 128>,
(128, 32) => rust::degrain::<T, RADIUS, 128, 32>,
(128, 64) => rust::degrain::<T, RADIUS, 128, 64>,
(128, 128) => rust::degrain::<T, RADIUS, 128, 128>,
_ => unreachable!(),
}
}
#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
#[must_use]
pub(super) fn select_degrain_avx2<T: Pixel, const RADIUS: usize>(
width: NonZeroUsize,
height: NonZeroUsize,
) -> DegrainFn {
match std::mem::size_of::<T>() {
1 => select_degrain_avx2_u8::<RADIUS>(width, height),
2 => select_degrain_avx2_u16::<RADIUS>(width, height),
_ => unreachable!(),
}
}
#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
#[must_use]
fn select_degrain_avx2_u8<const RADIUS: usize>(
width: NonZeroUsize,
height: NonZeroUsize,
) -> DegrainFn {
match (width.get(), height.get()) {
(2, 2) => avx2::degrain_u8::<RADIUS, 2, 2>,
(2, 4) => avx2::degrain_u8::<RADIUS, 2, 4>,
(4, 2) => avx2::degrain_u8::<RADIUS, 4, 2>,
(4, 4) => avx2::degrain_u8::<RADIUS, 4, 4>,
(4, 8) => avx2::degrain_u8::<RADIUS, 4, 8>,
(8, 1) => avx2::degrain_u8::<RADIUS, 8, 1>,
(8, 2) => avx2::degrain_u8::<RADIUS, 8, 2>,
(8, 4) => avx2::degrain_u8::<RADIUS, 8, 4>,
(8, 8) => avx2::degrain_u8::<RADIUS, 8, 8>,
(8, 16) => avx2::degrain_u8::<RADIUS, 8, 16>,
(16, 1) => avx2::degrain_u8::<RADIUS, 16, 1>,
(16, 2) => avx2::degrain_u8::<RADIUS, 16, 2>,
(16, 4) => avx2::degrain_u8::<RADIUS, 16, 4>,
(16, 8) => avx2::degrain_u8::<RADIUS, 16, 8>,
(16, 16) => avx2::degrain_u8::<RADIUS, 16, 16>,
(16, 32) => avx2::degrain_u8::<RADIUS, 16, 32>,
(32, 8) => avx2::degrain_u8::<RADIUS, 32, 8>,
(32, 16) => avx2::degrain_u8::<RADIUS, 32, 16>,
(32, 32) => avx2::degrain_u8::<RADIUS, 32, 32>,
(32, 64) => avx2::degrain_u8::<RADIUS, 32, 64>,
(64, 16) => avx2::degrain_u8::<RADIUS, 64, 16>,
(64, 32) => avx2::degrain_u8::<RADIUS, 64, 32>,
(64, 64) => avx2::degrain_u8::<RADIUS, 64, 64>,
(64, 128) => avx2::degrain_u8::<RADIUS, 64, 128>,
(128, 32) => avx2::degrain_u8::<RADIUS, 128, 32>,
(128, 64) => avx2::degrain_u8::<RADIUS, 128, 64>,
(128, 128) => avx2::degrain_u8::<RADIUS, 128, 128>,
_ => unreachable!(),
}
}
#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
#[must_use]
fn select_degrain_avx2_u16<const RADIUS: usize>(
width: NonZeroUsize,
height: NonZeroUsize,
) -> DegrainFn {
match (width.get(), height.get()) {
(2, 2) => avx2::degrain_u16::<RADIUS, 2, 2>,
(2, 4) => avx2::degrain_u16::<RADIUS, 2, 4>,
(4, 2) => avx2::degrain_u16::<RADIUS, 4, 2>,
(4, 4) => avx2::degrain_u16::<RADIUS, 4, 4>,
(4, 8) => avx2::degrain_u16::<RADIUS, 4, 8>,
(8, 1) => avx2::degrain_u16::<RADIUS, 8, 1>,
(8, 2) => avx2::degrain_u16::<RADIUS, 8, 2>,
(8, 4) => avx2::degrain_u16::<RADIUS, 8, 4>,
(8, 8) => avx2::degrain_u16::<RADIUS, 8, 8>,
(8, 16) => avx2::degrain_u16::<RADIUS, 8, 16>,
(16, 1) => avx2::degrain_u16::<RADIUS, 16, 1>,
(16, 2) => avx2::degrain_u16::<RADIUS, 16, 2>,
(16, 4) => avx2::degrain_u16::<RADIUS, 16, 4>,
(16, 8) => avx2::degrain_u16::<RADIUS, 16, 8>,
(16, 16) => avx2::degrain_u16::<RADIUS, 16, 16>,
(16, 32) => avx2::degrain_u16::<RADIUS, 16, 32>,
(32, 8) => avx2::degrain_u16::<RADIUS, 32, 8>,
(32, 16) => avx2::degrain_u16::<RADIUS, 32, 16>,
(32, 32) => avx2::degrain_u16::<RADIUS, 32, 32>,
(32, 64) => avx2::degrain_u16::<RADIUS, 32, 64>,
(64, 16) => avx2::degrain_u16::<RADIUS, 64, 16>,
(64, 32) => avx2::degrain_u16::<RADIUS, 64, 32>,
(64, 64) => avx2::degrain_u16::<RADIUS, 64, 64>,
(64, 128) => avx2::degrain_u16::<RADIUS, 64, 128>,
(128, 32) => avx2::degrain_u16::<RADIUS, 128, 32>,
(128, 64) => avx2::degrain_u16::<RADIUS, 128, 64>,
(128, 128) => avx2::degrain_u16::<RADIUS, 128, 128>,
_ => unreachable!(),
}
}