use cubecl::prelude::*;
use cubecl::server::Handle;
#[doc(hidden)]
#[derive(Debug, Clone, PartialEq)]
pub struct MotionSnapshot {
pub blocks_x: u32,
pub blocks_y: u32,
pub step: u32,
pub blksize: u32,
pub offsets: Vec<i32>,
pub vectors: Vec<Vec<[i32; 2]>>,
pub confidence: Vec<Vec<f32>>,
}
pub(super) struct LastFields {
pub mv_field: Handle,
pub confidence: Handle,
pub mv_stride: u32,
pub conf_stride: u32,
pub neighbours: u32,
}
pub(super) fn read_snapshot<R: Runtime>(
client: &ComputeClient<R>,
fields: &LastFields,
radius: u32,
blocks_x: u32,
blocks_y: u32,
step: u32,
blksize: u32,
) -> MotionSnapshot {
let blocks = (blocks_x * blocks_y) as usize;
let mv_bytes = client
.read_one(fields.mv_field.clone())
.expect("motion field readback failed");
let mv = i32::from_bytes(&mv_bytes);
let conf_bytes = client
.read_one(fields.confidence.clone())
.expect("confidence readback failed");
let conf = f32::from_bytes(&conf_bytes);
let mut offsets = Vec::with_capacity(fields.neighbours as usize);
let mut vectors = Vec::with_capacity(fields.neighbours as usize);
let mut confidence = Vec::with_capacity(fields.neighbours as usize);
for t in 0..fields.neighbours {
let k = if t < radius {
t as i32 - radius as i32
} else {
t as i32 - radius as i32 + 1
};
offsets.push(k);
let mv_base = (t * fields.mv_stride) as usize;
vectors.push(
(0..blocks)
.map(|b| [mv[mv_base + 2 * b], mv[mv_base + 2 * b + 1]])
.collect(),
);
let c_base = (t * fields.conf_stride) as usize;
confidence.push(conf[c_base..c_base + blocks].to_vec());
}
MotionSnapshot {
blocks_x,
blocks_y,
step,
blksize,
offsets,
vectors,
confidence,
}
}