use cubecl::prelude::*;
use crate::{Bound, Output, OutputArgs, Partitioning, Tile, kind::Write};
#[cube]
pub trait Destination: Send + Sync + 'static {
type Arg<E: Numeric, V: Size>: LaunchArg + CubeType;
fn tile<E: Numeric, V: Size>(
arg: &Self::Arg<E, V>,
#[comptime] partitioning: Partitioning,
) -> Tile<E>;
}
pub trait DestinationLaunch: Destination {
type Operand;
fn arg<E: Numeric, V: Size>(
operand: Self::Operand,
) -> <Self::Arg<E, V> as LaunchArg>::RuntimeArg;
}
pub struct Buffered;
#[cube]
impl Destination for Buffered {
type Arg<E: Numeric, V: Size> = Output<'static, E, V>;
fn tile<E: Numeric, V: Size>(
arg: &Self::Arg<E, V>,
#[comptime] partitioning: Partitioning,
) -> Tile<E> {
arg.tile(partitioning)
}
}
impl DestinationLaunch for Buffered {
type Operand = (Bound, Write);
fn arg<E: Numeric, V: Size>((bound, write): (Bound, Write)) -> OutputArgs<'static, E, V> {
match write {
Write::Replace => bound.output(),
Write::Accumulate => bound.atomic(),
Write::Exclusive(_) => panic!(
"Buffered: a relayed output is opened in the kernel with `TileArg::relay`, which \
takes its turn counters beside it; bind the carry as a plain `TileArg`"
),
}
}
}