1#![allow(unreachable_code)]
79use zune_core::options::DecoderOptions;
80
81use crate::components::UpSampler;
82
83#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
84#[cfg(feature = "x86")]
85mod avx2;
86#[cfg(target_arch = "aarch64")]
87#[cfg(feature = "neon")]
88mod neon;
89#[cfg(feature = "portable_simd")]
90mod portable_simd;
91mod scalar;
92
93#[allow(unused_variables)]
95pub fn choose_horizontal_samp_function(options: &DecoderOptions) -> UpSampler {
96 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
97 #[cfg(feature = "x86")]
98 if options.use_avx2() {
99 return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
100 unsafe { avx2::upsample_horizontal_avx2(a, b, c, d, e) }
102 };
103 }
104 #[cfg(target_arch = "aarch64")]
105 #[cfg(feature = "neon")]
106 if options.use_neon() {
107 return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
108 unsafe { neon::upsample_horizontal_neon(a, b, c, d, e) }
110 };
111 }
112 #[cfg(feature = "portable_simd")]
113 return portable_simd::upsample_horizontal_simd;
114 return scalar::upsample_horizontal;
115}
116
117#[allow(unused_variables)]
118pub fn choose_hv_samp_function(options: &DecoderOptions) -> UpSampler {
119 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
120 #[cfg(feature = "x86")]
121 if options.use_avx2() {
122 return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
123 unsafe { avx2::upsample_hv_avx2(a, b, c, d, e) }
125 };
126 }
127 #[cfg(target_arch = "aarch64")]
128 #[cfg(feature = "neon")]
129 if options.use_neon() {
130 return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
131 unsafe { neon::upsample_hv_neon(a, b, c, d, e) }
133 };
134 }
135 #[cfg(feature = "portable_simd")]
136 return portable_simd::upsample_hv_simd;
137 return scalar::upsample_hv;
138}
139
140#[allow(unused_variables)]
141pub fn choose_v_samp_function(options: &DecoderOptions) -> UpSampler {
142 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
143 #[cfg(feature = "x86")]
144 if options.use_avx2() {
145 return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
146 unsafe { avx2::upsample_vertical_avx2(a, b, c, d, e) }
148 };
149 }
150 #[cfg(target_arch = "aarch64")]
151 #[cfg(feature = "neon")]
152 if options.use_neon() {
153 return |a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
154 unsafe { neon::upsample_vertical_neon(a, b, c, d, e) }
156 };
157 }
158 #[cfg(feature = "portable_simd")]
159 return portable_simd::upsample_vertical_simd;
160 return scalar::upsample_vertical;
161}
162
163pub fn upsample_no_op(
166 _input: &[i16],
167 _in_ref: &[i16],
168 _in_near: &[i16],
169 _scratch_space: &mut [i16],
170 _output: &mut [i16],
171) {
172}
173
174pub fn generic_sampler() -> UpSampler {
175 scalar::upsample_generic
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[cfg(feature = "portable_simd")]
183 mod portable_simd_impl {
184 use super::*;
185
186 #[test]
187 fn portable_simd_vertical() {
188 _test_vertical(portable_simd::upsample_vertical_simd)
189 }
190
191 #[test]
192 fn portable_simd_horizontal() {
193 _test_horizontal(portable_simd::upsample_horizontal_simd)
194 }
195
196 #[test]
197 fn portable_simd_hv() {
198 _test_hv(portable_simd::upsample_hv_simd)
199 }
200 }
201
202 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
203 #[cfg(feature = "x86")]
204 #[cfg(target_feature = "avx2")]
205 mod avx2_impl {
206 use super::*;
207
208 #[test]
209 fn avx2_vertical() {
210 _test_vertical(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
211 unsafe { avx2::upsample_vertical_avx2(a, b, c, d, e) }
213 })
214 }
215
216 #[test]
217 fn avx2_horizontal() {
218 _test_horizontal(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
219 unsafe { avx2::upsample_horizontal_avx2(a, b, c, d, e) }
221 })
222 }
223
224 #[test]
225 fn avx2_hv() {
226 _test_hv(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
227 unsafe { avx2::upsample_hv_avx2(a, b, c, d, e) }
229 })
230 }
231 }
232
233 #[cfg(target_arch = "aarch64")]
234 #[cfg(feature = "neon")]
235 #[cfg(target_feature = "neon")]
236 mod neon_impl {
237 use super::*;
238
239 #[test]
240 fn neon_vertical() {
241 _test_vertical(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
242 unsafe { neon::upsample_vertical_neon(a, b, c, d, e) }
244 })
245 }
246
247 #[test]
248 fn neon_horizontal() {
249 _test_horizontal(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
250 unsafe { neon::upsample_horizontal_neon(a, b, c, d, e) }
252 })
253 }
254
255 #[test]
256 fn neon_hv() {
257 _test_hv(|a: &[i16], b: &[i16], c: &[i16], d: &mut [i16], e: &mut [i16]| {
258 unsafe { neon::upsample_hv_neon(a, b, c, d, e) }
260 })
261 }
262 }
263
264 fn _test_vertical(upsampler: UpSampler) {
265 let width = 1024;
266 let input: Vec<i16> = (0..width).map(|x| ((x + 10) % 256) as i16).collect();
267 let in_near: Vec<i16> = (0..width).map(|x| ((x + 20) % 256) as i16).collect();
268 let in_far: Vec<i16> = (0..width).map(|x| ((x + 30) % 256) as i16).collect();
269 let mut scratch = vec![0i16; width];
270
271 let mut output_scalar = vec![0i16; width * 2];
272 let mut output_fast = vec![0i16; width * 2];
273
274 scalar::upsample_vertical(&input, &in_near, &in_far, &mut scratch, &mut output_scalar);
275 upsampler(&input, &in_near, &in_far, &mut scratch, &mut output_fast);
276
277 assert_eq!(output_scalar, output_fast);
278 }
279
280 fn _test_horizontal(upsampler: UpSampler) {
281 _test_horizontal_even_width(upsampler);
282 _test_horizontal_odd_width(upsampler);
283 }
284
285 fn _test_horizontal_even_width(upsampler: UpSampler) {
286 let width = 1024;
287 let input: Vec<i16> = (0..width).map(|x| ((x + 10) % 256) as i16).collect();
288
289 let mut scratch = vec![0i16; width];
290
291 let mut output_scalar = vec![0i16; width * 2];
292 let mut output_fast = vec![0i16; width * 2];
293
294 scalar::upsample_horizontal(&input, &[], &[], &mut scratch, &mut output_scalar);
295 upsampler(&input, &[], &[], &mut scratch, &mut output_fast);
296
297 assert_eq!(output_scalar, output_fast);
298 }
299
300 fn _test_horizontal_odd_width(upsampler: UpSampler) {
301 let width = 33;
302 let input: Vec<i16> = (0..width).map(|x| ((x + 10) % 256) as i16).collect();
303 let mut scratch = vec![0i16; width];
304 let mut output_scalar = vec![0i16; width * 2];
305 let mut output_fast = vec![0i16; width * 2];
306
307 scalar::upsample_horizontal(&input, &[], &[], &mut scratch, &mut output_scalar);
308 upsampler(&input, &[], &[], &mut scratch, &mut output_fast);
309
310 assert_eq!(output_scalar, output_fast);
311 }
312
313 fn _test_hv(upsampler: UpSampler) {
314 let width = 512;
315 let input: Vec<i16> = (0..width).map(|x| ((x + 10) % 256) as i16).collect();
316 let in_near: Vec<i16> = (0..width).map(|x| ((x + 20) % 256) as i16).collect();
317 let in_far: Vec<i16> = (0..width).map(|x| ((x + 30) % 256) as i16).collect();
318
319 let mut scratch_scalar = vec![0i16; width * 2];
322 let mut scratch_fast = vec![0i16; width * 2];
323 let mut output_scalar = vec![0i16; width * 4];
324 let mut output_fast = vec![0i16; width * 4];
325
326 scalar::upsample_hv(
327 &input,
328 &in_near,
329 &in_far,
330 &mut scratch_scalar,
331 &mut output_scalar,
332 );
333 upsampler(
334 &input,
335 &in_near,
336 &in_far,
337 &mut scratch_fast,
338 &mut output_fast,
339 );
340
341 assert_eq!(output_scalar, output_fast);
342 }
343}