#[macro_export]
macro_rules! kernel_params {
(
$name:ident for $P:path {
$( $field:ident : $ty:ty $(= [$($spec:tt)+])? ; )*
}
) => {
#[$crate::gpu_struct]
pub struct $name {
$( pub $field : $ty, )*
}
impl $crate::KernelParams for $name {
const SIZE: usize = <$name>::SIZE;
const ALIGN: usize = <$name>::ALIGN;
}
impl $name {
pub fn from_gpu(
__filter: &::premiere::GpuFilterData,
__rp: &::premiere::RenderParams,
__width: f32,
__height: f32,
) -> Self {
Self {
$( $field: $crate::kernel_params!(@gpu $P, __filter, __rp, __width, __height $(, $($spec)+)?), )*
}
}
pub fn from_cpu(
__params: &::after_effects::Parameters<'_, $P>,
__width: f32,
__height: f32,
__is_premiere: bool,
) -> ::core::result::Result<Self, ::after_effects::Error> {
use $crate::params::CpuParams as _;
Ok(Self {
$( $field: $crate::kernel_params!(@cpu $P, __params, __width, __height, __is_premiere $(, $($spec)+)?), )*
})
}
pub fn from_context(
__ctx: &$crate::effect::FrameDataContext<'_, $P>,
) -> ::core::result::Result<Self, ::after_effects::Error> {
__ctx.extract_kernel_params(Self::from_cpu, Self::from_gpu)
}
}
};
(@gpu $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $ext:ident($v:ident) / $($t:tt)+) => {
$crate::kernel_params!(@gpu_base $ext, $P, $f, $rp, $w, $h, $v) / $($t)+
};
(@gpu $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $ext:ident($v:ident) * $($t:tt)+) => {
$crate::kernel_params!(@gpu_base $ext, $P, $f, $rp, $w, $h, $v) * $($t)+
};
(@gpu $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $ext:ident($v:ident)) => {
$crate::kernel_params!(@gpu_base $ext, $P, $f, $rp, $w, $h, $v)
};
(@gpu $P:path, $f:ident, $rp:ident, $w:ident, $h:ident) => {
Default::default()
};
(@gpu_base float, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {
$crate::params::get_param::<f32, _>($f, <$P>::$v, $rp)
};
(@gpu_base angle, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {
$crate::params::get_param::<f32, _>($f, <$P>::$v, $rp)
};
(@gpu_base checkbox, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {
$crate::params::get_param::<bool, _>($f, <$P>::$v, $rp) as u32
};
(@gpu_base popup, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {
$crate::params::get_param::<i32, _>($f, <$P>::$v, $rp).max(0) as u32
};
(@gpu_base color_r, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __c: $crate::types::Pixel = $crate::params::get_param($f, <$P>::$v, $rp);
__c.red as f32
}};
(@gpu_base color_g, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __c: $crate::types::Pixel = $crate::params::get_param($f, <$P>::$v, $rp);
__c.green as f32
}};
(@gpu_base color_b, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __c: $crate::types::Pixel = $crate::params::get_param($f, <$P>::$v, $rp);
__c.blue as f32
}};
(@gpu_base color_a, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __c: $crate::types::Pixel = $crate::params::get_param($f, <$P>::$v, $rp);
__c.alpha as f32
}};
(@gpu_base point_pct_x, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __p: (f32, f32) = $crate::params::get_param($f, <$P>::$v, $rp);
__p.0
}};
(@gpu_base point_pct_y, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __p: (f32, f32) = $crate::params::get_param($f, <$P>::$v, $rp);
__p.1
}};
(@gpu_base point_px_x, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __p: (f32, f32) = $crate::params::get_param($f, <$P>::$v, $rp);
__p.0 * $w
}};
(@gpu_base point_px_y, $P:path, $f:ident, $rp:ident, $w:ident, $h:ident, $v:ident) => {{
let __p: (f32, f32) = $crate::params::get_param($f, <$P>::$v, $rp);
__p.1 * $h
}};
(@cpu $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $ext:ident($v:ident) / $($t:tt)+) => {
$crate::kernel_params!(@cpu_base $ext, $P, $p, $w, $h, $is_pr, $v) / $($t)+
};
(@cpu $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $ext:ident($v:ident) * $($t:tt)+) => {
$crate::kernel_params!(@cpu_base $ext, $P, $p, $w, $h, $is_pr, $v) * $($t)+
};
(@cpu $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $ext:ident($v:ident)) => {
$crate::kernel_params!(@cpu_base $ext, $P, $p, $w, $h, $is_pr, $v)
};
(@cpu $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident) => {
Default::default()
};
(@cpu_base float, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {
$p.float(<$P>::$v)?
};
(@cpu_base angle, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {
$p.angle(<$P>::$v)?
};
(@cpu_base checkbox, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {
$p.checkbox(<$P>::$v)? as u32
};
(@cpu_base popup, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {
($p.popup(<$P>::$v)? as u32).saturating_sub(1)
};
(@cpu_base color_r, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __c = $p.color(<$P>::$v)?;
__c.red as f32
}};
(@cpu_base color_g, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __c = $p.color(<$P>::$v)?;
__c.green as f32
}};
(@cpu_base color_b, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __c = $p.color(<$P>::$v)?;
__c.blue as f32
}};
(@cpu_base color_a, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __c = $p.color(<$P>::$v)?;
__c.alpha as f32
}};
(@cpu_base point_pct_x, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __pt = $p.point(<$P>::$v)?;
__pt.0 / $w
}};
(@cpu_base point_pct_y, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __pt = $p.point(<$P>::$v)?;
__pt.1 / $h
}};
(@cpu_base point_px_x, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __pt = $p.point(<$P>::$v)?;
__pt.0
}};
(@cpu_base point_px_y, $P:path, $p:ident, $w:ident, $h:ident, $is_pr:ident, $v:ident) => {{
let __pt = $p.point(<$P>::$v)?;
__pt.1
}};
}
#[macro_export]
macro_rules! declare_kernel {
($name:ident, $user_params_ty:ty) => {
pub mod $name {
#[allow(unused_imports)]
use super::*;
pub const SHADER_SRC: &[u8] = {
#[cfg(gpu_backend = "metal")]
{ $crate::include_shader!($name, metal) }
#[cfg(gpu_backend = "cuda")]
{ $crate::include_shader!($name, cuda) }
#[cfg(not(any(gpu_backend = "metal", gpu_backend = "cuda")))]
{ &[] }
};
pub const ENTRY_POINT: &str = stringify!($name);
$crate::paste::paste! {
unsafe extern "C" {
pub fn [<$name _cpu_dispatch>](
gid_x: u32,
gid_y: u32,
buffers: *const *const std::ffi::c_void,
transition_params: *const std::ffi::c_void,
user_params: *const std::ffi::c_void,
);
pub fn [<$name _cpu_dispatch_tile>](
y0: u32,
y1: u32,
width: u32,
buffers: *const *const std::ffi::c_void,
transition_params: *const std::ffi::c_void,
user_params: *const std::ffi::c_void,
);
}
pub const CPU_DISPATCH: $crate::cpu::render::CpuDispatchFn = [<$name _cpu_dispatch>];
pub const CPU_DISPATCH_TILE: $crate::cpu::render::CpuDispatchTileFn = [<$name _cpu_dispatch_tile>];
}
pub unsafe fn gpu(
config: &$crate::types::Configuration,
user_params: $user_params_ty,
) -> Result<(), &'static str> {
$crate::backends::dispatch_kernel::<$user_params_ty>(config, user_params, SHADER_SRC, ENTRY_POINT)
}
pub fn cpu(
in_data: &after_effects::InData,
in_layer: &after_effects::Layer,
out_layer: &mut after_effects::Layer,
config: &$crate::types::Configuration,
user_params: $user_params_ty,
) -> Result<(), after_effects::Error> {
$crate::paste::paste! {
$crate::cpu::render::render_cpu(
stringify!($name),
in_data,
in_layer,
out_layer,
config,
[<$name _cpu_dispatch>],
[<$name _cpu_dispatch_tile>],
&user_params,
)
}
}
pub fn kernel() -> $crate::Kernel<$user_params_ty> {
$crate::Kernel::new(
stringify!($name),
SHADER_SRC,
ENTRY_POINT,
CPU_DISPATCH,
CPU_DISPATCH_TILE,
gpu,
cpu,
)
}
}
$crate::paste::paste! {
#[allow(non_upper_case_globals)]
pub const [<$name:upper _CPU_DISPATCH>]: $crate::cpu::render::CpuDispatchFn = $name::CPU_DISPATCH;
#[allow(non_upper_case_globals)]
pub const [<$name:upper _CPU_DISPATCH_TILE>]: $crate::cpu::render::CpuDispatchTileFn = $name::CPU_DISPATCH_TILE;
}
#[deprecated(note = "use `<name>::gpu` or `<name>::kernel()` for graph execution")]
#[allow(dead_code)]
pub unsafe fn $name(
config: &$crate::types::Configuration,
user_params: $user_params_ty,
) -> Result<(), &'static str> {
unsafe { $name::gpu(config, user_params) }
}
$crate::paste::paste! {
#[deprecated(note = "use `<name>::cpu` or `<name>::kernel()` for graph execution")]
#[allow(dead_code)]
pub fn [<$name _cpu>](
in_data: &after_effects::InData,
in_layer: &after_effects::Layer,
out_layer: &mut after_effects::Layer,
config: &$crate::types::Configuration,
user_params: $user_params_ty,
) -> Result<(), after_effects::Error> {
$name::cpu(in_data, in_layer, out_layer, config, user_params)
}
}
};
}