use crate::kernel::SobelKernel;
use crate::nms::nms_and_threshold_slice;
use crate::pipeline_ptr::{SendConstPtr, SendPtr};
use crate::workspace::CannyWorkspace;
use rayon::prelude::*;
const TILE_SIZE: usize = 64;
pub fn execute_tiled_pipeline(
src: &[f32],
workspace: &mut CannyWorkspace,
low_thresh: f32,
high_thresh: f32,
) {
let w = workspace.width;
let h = workspace.height;
let src_sp = SendConstPtr::new(src.as_ptr());
let mag_sp = SendPtr::new(workspace.buffer_a.as_mut_ptr());
let dir_sp = SendPtr::new(workspace.dir_map.as_mut_ptr());
let edge_sp = SendPtr::new(workspace.edge_map.as_mut_ptr());
let kernel_ref = workspace.kernel();
let kernel_parts: [usize; 2] = unsafe {
std::mem::transmute(kernel_ref as *const dyn SobelKernel)
};
let num_tiles_x = (w + TILE_SIZE - 1) / TILE_SIZE;
let num_tiles_y = (h + TILE_SIZE - 1) / TILE_SIZE;
(0..num_tiles_y).into_par_iter().for_each(move |ty| {
let kernel: &dyn SobelKernel = unsafe {
let ptr: *const dyn SobelKernel = std::mem::transmute(kernel_parts);
&*ptr
};
let start_y = (ty * TILE_SIZE).max(1);
let end_y = ((ty + 1) * TILE_SIZE).min(h - 1);
for tx in 0..num_tiles_x {
let start_x = (tx * TILE_SIZE).max(1);
let end_x = ((tx + 1) * TILE_SIZE).min(w - 1);
let src_slice = unsafe { std::slice::from_raw_parts(src_sp.get(), w * h) };
let mag_slice = unsafe { std::slice::from_raw_parts_mut(mag_sp.get(), w * h) };
let dir_slice = unsafe { std::slice::from_raw_parts_mut(dir_sp.get(), w * h) };
for y in start_y..end_y {
kernel.process_row_slice(
src_slice, mag_slice, dir_slice,
w, start_x, end_x, y,
);
}
let nms_start_y = start_y.max(2);
let nms_end_y = end_y.min(h - 2);
let nms_start_x = start_x.max(2);
let nms_end_x = end_x.min(w - 2);
let mag_slice = unsafe { std::slice::from_raw_parts(mag_sp.get(), w * h) };
let dir_slice = unsafe { std::slice::from_raw_parts(dir_sp.get(), w * h) };
let edge_slice = unsafe { std::slice::from_raw_parts_mut(edge_sp.get(), w * h) };
for y in nms_start_y..nms_end_y {
nms_and_threshold_slice(
mag_slice, dir_slice, edge_slice,
w, nms_start_x, nms_end_x, y,
low_thresh, high_thresh,
);
}
}
});
}