#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum Family {
Itx = 0,
McPut = 1,
McPrep = 2,
McOther = 3,
Cdef = 4,
LoopFilter = 5,
LoopRestoration = 6,
IntraPred = 7,
FilmGrain = 8,
}
impl Family {
pub const ALL: &'static [Family] = &[
Family::Itx,
Family::McPut,
Family::McPrep,
Family::McOther,
Family::Cdef,
Family::LoopFilter,
Family::LoopRestoration,
Family::IntraPred,
Family::FilmGrain,
];
pub const fn name(self) -> &'static str {
match self {
Family::Itx => "itx",
Family::McPut => "mc_put",
Family::McPrep => "mc_prep",
Family::McOther => "mc_other",
Family::Cdef => "cdef",
Family::LoopFilter => "loopfilter",
Family::LoopRestoration => "looprestoration",
Family::IntraPred => "ipred",
Family::FilmGrain => "filmgrain",
}
}
pub fn from_name(s: &str) -> Option<Family> {
Family::ALL.iter().copied().find(|f| f.name() == s)
}
#[cfg(feature = "__ablate")]
const fn bit(self) -> u32 {
1u32 << (self as u32)
}
}
pub const ENABLED: bool = cfg!(feature = "__ablate");
#[cfg(feature = "__ablate")]
static DISABLED: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0);
pub fn set_disabled(families: &[Family]) {
#[cfg(feature = "__ablate")]
{
let mut mask = 0u32;
for f in families {
mask |= f.bit();
}
DISABLED.store(mask, std::sync::atomic::Ordering::SeqCst);
}
#[cfg(not(feature = "__ablate"))]
let _ = families;
}
#[cfg(feature = "__ablate")]
#[inline(always)]
pub fn is_off(f: Family) -> bool {
DISABLED.load(std::sync::atomic::Ordering::Relaxed) & f.bit() != 0
}
#[cfg(not(feature = "__ablate"))]
#[inline(always)]
pub fn is_off(_f: Family) -> bool {
false
}
#[cfg(feature = "__ablate")]
static ACTIVITY: [std::sync::atomic::AtomicU64; 9] =
[const { std::sync::atomic::AtomicU64::new(0) }; 9];
#[inline(always)]
pub fn note(f: Family, units: u64) {
#[cfg(feature = "__ablate")]
ACTIVITY[f as usize].fetch_add(units, std::sync::atomic::Ordering::Relaxed);
#[cfg(not(feature = "__ablate"))]
let _ = (f, units);
}
pub fn activity_snapshot() -> [u64; 9] {
#[cfg(feature = "__ablate")]
{
let mut out = [0u64; 9];
for (i, slot) in ACTIVITY.iter().enumerate() {
out[i] = slot.load(std::sync::atomic::Ordering::Relaxed);
}
out
}
#[cfg(not(feature = "__ablate"))]
[0u64; 9]
}
pub fn activity_reset() {
#[cfg(feature = "__ablate")]
for slot in ACTIVITY.iter() {
slot.store(0, std::sync::atomic::Ordering::Relaxed);
}
}
#[cfg(feature = "__ablate")]
const ITX_SIZES: usize = 19;
#[cfg(feature = "__ablate")]
static ITX_SHAPES: [[std::sync::atomic::AtomicU64; ITX_SIZES]; 4] =
[const { [const { std::sync::atomic::AtomicU64::new(0) }; ITX_SIZES] }; 4];
#[inline(always)]
pub fn note_itx_shape(tx_size: usize, bitdepth: u8, handled: bool) {
#[cfg(feature = "__ablate")]
{
let row = (bitdepth != 8) as usize * 2 + handled as usize;
if tx_size < ITX_SIZES {
ITX_SHAPES[row][tx_size].fetch_add(1, std::sync::atomic::Ordering::Relaxed);
}
}
#[cfg(not(feature = "__ablate"))]
let _ = (tx_size, bitdepth, handled);
}
#[cfg(feature = "__ablate")]
pub fn itx_shape_report() -> String {
use crate::src::levels::TxfmSize;
use core::fmt::Write as _;
let mut out = String::from(ITX_CENSUS_HEADER);
for row in 0..4 {
for i in 0..ITX_SIZES {
let n = ITX_SHAPES[row][i].load(std::sync::atomic::Ordering::Relaxed);
if n == 0 {
continue;
}
let (w, h) = match TxfmSize::from_repr(i) {
Some(t) => t.to_wh(),
None => continue,
};
let _ = writeln!(
out,
"{}\t{}\t{}x{}\t{}\t{}",
if row >= 2 { "16bpc" } else { "8bpc" },
if row % 2 == 1 { "simd" } else { "SCALAR" },
w,
h,
n,
n * (w * h) as u64,
);
}
}
out
}
#[cfg(not(feature = "__ablate"))]
pub fn itx_shape_report() -> String {
String::from(ITX_CENSUS_HEADER)
}
const ITX_CENSUS_HEADER: &str = "depth\tpath\tshape\tcalls\tcoeff_area\n";
pub fn itx_shape_reset() {
#[cfg(feature = "__ablate")]
for row in ITX_SHAPES.iter() {
for slot in row.iter() {
slot.store(0, std::sync::atomic::Ordering::Relaxed);
}
}
}