Skip to main content

av_denoise/nlmeans/
mod.rs

1pub mod kernels;
2pub mod motion;
3pub mod prefilter;
4
5mod align;
6mod denoiser;
7mod dispatch;
8mod noise;
9mod params;
10mod pending;
11
12// Every test in this tree runs against a real GPU runtime (see
13// `tests::helpers::R`), so it only builds when a wgpu-backed feature is
14// enabled. A cpu-only build (`--no-default-features --features cpu`)
15// skips it entirely. `src/denoiser.rs`'s `cpu_smoke_tests` module covers
16// the cpu backend instead.
17#[cfg(all(test, any(feature = "vulkan", feature = "metal")))]
18mod tests;
19
20pub use denoiser::NlmDenoiser;
21pub use motion::{MotionCompensationMode, MotionEstimation};
22pub use params::{
23    ChannelMode,
24    HqParams,
25    MAX_PATCH_RADIUS,
26    MAX_SEARCH_RADIUS,
27    MAX_TEMPORAL_RADIUS,
28    MIN_FRAME_DIM,
29    NlmParams,
30    hq_default_strength,
31    validate_dimensions,
32};
33pub use pending::Pending;
34pub use prefilter::{DEFAULT_PILOT_STRENGTH_SCALE, PrefilterMode};
35
36/// Cube X dimension for tile-heavy fused/separable kernels.
37pub const BLOCK_X: u32 = 32;
38/// Cube Y dimension for tile-heavy fused/separable kernels.
39pub const BLOCK_Y: u32 = 8;
40
41/// Cube shape for the per-pixel `nlm_accumulate` kernel, which has no
42/// SMEM tile. On RDNA-class GPUs it benchmarks 10 to 25% faster at
43/// (32, 16) than at the tile-heavy default, because it's
44/// memory-latency-bound and the extra threads hide load latency.
45pub const BLOCK_X_THIN: u32 = 32;
46pub const BLOCK_Y_THIN: u32 = 16;
47
48/// Maximum 1D grid size for GPU dispatch (WebGPU/Vulkan limit).
49pub(crate) const MAX_GRID_1D: u32 = 65535;
50
51/// Block size for 1D utility kernels (copy, zero).
52pub(crate) const BLOCK_1D: u32 = 256;
53
54pub fn normalize_u8(input: &[u8]) -> Vec<f32> {
55    input.iter().map(|&v| v as f32 / 255.0).collect()
56}
57
58pub fn denormalize_u8(input: &[f32]) -> Vec<u8> {
59    input
60        .iter()
61        .map(|&v| (v * 255.0).round().clamp(0.0, 255.0) as u8)
62        .collect()
63}
64
65pub fn normalize_u16(input: &[u16]) -> Vec<f32> {
66    input.iter().map(|&v| v as f32 / 65535.0).collect()
67}
68
69pub fn denormalize_u16(input: &[f32]) -> Vec<u16> {
70    input
71        .iter()
72        .map(|&v| (v * 65535.0).round().clamp(0.0, 65535.0) as u16)
73        .collect()
74}