#![allow(non_snake_case)]
use super::maybe_done::{maybe_done, MaybeDone};
use super::{ContextId, GpuTask, Progress};
macro_rules! generate_join {
($(
$(#[$doc:meta])*
($Join:ident, <A, $($B:ident),*>),
)*) => ($(
$(#[$doc])*
pub struct $Join<A, $($B),*, Ec> where A: GpuTask<Ec>, $($B: GpuTask<Ec>),*
{
id: ContextId,
a: MaybeDone<A, A::Output, Ec>,
$($B: MaybeDone<$B, $B::Output, Ec>),*
}
impl<A, $($B),*, Ec> $Join<A, $($B),*, Ec> where A: GpuTask<Ec>, $($B: GpuTask<Ec>),* {
pub(crate) fn new(a: A, $($B: $B),*) -> Self {
let mut id = a.context_id();
$(
id = id.combine($B.context_id()).unwrap();
)*
$Join {
id,
a: maybe_done(a),
$($B: maybe_done($B)),*
}
}
}
unsafe impl<A, $($B),*, Ec> GpuTask<Ec> for $Join<A, $($B),*, Ec>
where
A: GpuTask<Ec>,
$($B: GpuTask<Ec>),*
{
type Output = (A::Output, $($B::Output),*);
fn context_id(&self) -> ContextId {
self.id
}
fn progress(&mut self, execution_context: &mut Ec) -> Progress<Self::Output> {
let mut all_done = self.a.progress(execution_context);
$(
all_done = all_done && self.$B.progress(execution_context);
)*
if all_done {
Progress::Finished((self.a.take(), $(self.$B.take()),*))
} else {
Progress::ContinueFenced
}
}
}
impl<A, $($B),*, Ec> Clone for $Join<A, $($B),*, Ec>
where
A: GpuTask<Ec> + Clone,
A::Output: Clone,
$(
$B: GpuTask<Ec> + Clone,
$B::Output: Clone,
)*
{
fn clone(&self) -> Self {
$Join {
id: self.id.clone(),
a: self.a.clone(),
$($B: self.$B.clone()),*
}
}
}
)*)
}
generate_join! {
(Join, <A, B>),
(Join3, <A, B, C>),
(Join4, <A, B, C, D>),
(Join5, <A, B, C, D, E>),
}
macro_rules! generate_join_left {
($(
$(#[$doc:meta])*
($Join:ident, <A, $($B:ident),*>),
)*) => ($(
$(#[$doc])*
pub struct $Join<A, $($B),*, Ec> where A: GpuTask<Ec>, $($B: GpuTask<Ec>),*
{
id: ContextId,
a: MaybeDone<A, A::Output, Ec>,
$($B: MaybeDone<$B, $B::Output, Ec>),*
}
impl<A, $($B),*, Ec> $Join<A, $($B),*, Ec> where A: GpuTask<Ec>, $($B: GpuTask<Ec>),* {
pub(crate) fn new(a: A, $($B: $B),*) -> Self {
let mut id = a.context_id();
$(
id = id.combine($B.context_id()).unwrap();
)*
$Join {
id,
a: maybe_done(a),
$($B: maybe_done($B)),*
}
}
}
unsafe impl<A, $($B),*, Ec> GpuTask<Ec> for $Join<A, $($B),*, Ec>
where
A: GpuTask<Ec>,
$($B: GpuTask<Ec>),*
{
type Output = A::Output;
fn context_id(&self) -> ContextId {
self.id
}
fn progress(&mut self, execution_context: &mut Ec) -> Progress<Self::Output> {
let mut all_done = self.a.progress(execution_context);
$(
all_done = all_done && self.$B.progress(execution_context);
)*
if all_done {
Progress::Finished(self.a.take())
} else {
Progress::ContinueFenced
}
}
}
impl<A, $($B),*, Ec> Clone for $Join<A, $($B),*, Ec>
where
A: GpuTask<Ec> + Clone,
A::Output: Clone,
$(
$B: GpuTask<Ec> + Clone,
$B::Output: Clone,
)*
{
fn clone(&self) -> Self {
$Join {
id: self.id.clone(),
a: self.a.clone(),
$($B: self.$B.clone()),*
}
}
}
)*)
}
generate_join_left! {
(JoinLeft, <A, B>),
(Join3Left, <A, B, C>),
(Join4Left, <A, B, C, D>),
(Join5Left, <A, B, C, D, E>),
}
macro_rules! generate_join_right {
($(
$(#[$doc:meta])*
($Join:ident, <$($A:ident),*> $B:ident),
)*) => ($(
$(#[$doc])*
pub struct $Join<$($A,)* $B, Ec> where $($A: GpuTask<Ec>,)* $B: GpuTask<Ec>
{
id: ContextId,
$($A: MaybeDone<$A, $A::Output, Ec>,)*
$B: MaybeDone<$B, $B::Output, Ec>,
}
impl<$($A,)* $B, Ec> $Join<$($A,)* $B, Ec> where $($A: GpuTask<Ec>,)* $B: GpuTask<Ec> {
pub(crate) fn new($($A: $A,)* $B: $B) -> Self {
let mut id = ContextId::Any;
$(
id = id.combine($A.context_id()).unwrap();
)*
id = id.combine($B.context_id()).unwrap();
$Join {
id,
$($A: maybe_done($A),)*
$B: maybe_done($B)
}
}
}
unsafe impl<$($A,)* $B, Ec> GpuTask<Ec> for $Join<$($A,)* $B, Ec>
where
$($A: GpuTask<Ec>,)*
$B: GpuTask<Ec>
{
type Output = $B::Output;
fn context_id(&self) -> ContextId {
self.id
}
fn progress(&mut self, execution_context: &mut Ec) -> Progress<Self::Output> {
let mut all_done = true;
$(
all_done = all_done && self.$A.progress(execution_context);
)*
all_done = all_done && self.$B.progress(execution_context);
if all_done {
Progress::Finished(self.$B.take())
} else {
Progress::ContinueFenced
}
}
}
impl<$($A,)* $B, Ec> Clone for $Join<$($A,)* $B, Ec>
where
$(
$A: GpuTask<Ec> + Clone,
$A::Output: Clone,
)*
$B: GpuTask<Ec> + Clone,
$B::Output: Clone,
{
fn clone(&self) -> Self {
$Join {
id: self.id.clone(),
$($A: self.$A.clone(),)*
$B: self.$B.clone(),
}
}
}
)*)
}
generate_join_right! {
(JoinRight, <A> B),
(Join3Right, <A, B> C),
(Join4Right, <A, B, C> D),
(Join5Right, <A, B, C, D> E),
}
#[doc(hidden)]
#[macro_export]
macro_rules! join_all {
($e0:expr, $e1:expr) => (join_all!($e0, $e1,));
($e0:expr, $e1:expr, $($e:expr,)+) => (join_all!($e0, $e1, $($e),*));
($e0:expr, $e1:expr, $($e:expr),*) => {
{
let joined = $crate::task::join($e0, $e1);
$(
let joined = $crate::task::join(joined, $e);
)*
joined
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! join_all_left {
($e0:expr, $e1:expr) => (join_all_left!($e0, $e1,));
($e0:expr, $e1:expr, $($e:expr,)+) => (join_all_left!($e0, $e1, $($e),*));
($e0:expr, $e1:expr, $($e:expr),*) => {
{
let joined = $crate::task::join_all_left($e0, $e1);
$(
let joined = $crate::task::join_all_left(joined, $e);
)*
joined
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! join_all_right {
($e0:expr, $e1:expr) => (join_all_right!($e0, $e1,));
($e0:expr, $e1:expr, $($e:expr,)+) => (join_all_right!($e0, $e1, $($e),*));
($e0:expr, $e1:expr, $($e:expr),*) => {
{
let joined = $crate::task::join_all_right($e0, $e1);
$(
let joined = $crate::task::join_all_right(joined, $e);
)*
joined
}
}
}
pub struct JoinIter<T, Ec> {
id: ContextId,
vec: Vec<MaybeDone<T, (), Ec>>,
}
impl<T, Ec> JoinIter<T, Ec>
where
T: GpuTask<Ec, Output = ()>,
{
fn new<I>(tasks: I) -> Self
where
I: IntoIterator<Item = T>,
{
let mut id = ContextId::Any;
let vec: Vec<MaybeDone<T, (), Ec>> = tasks
.into_iter()
.inspect(|t| {
id = id.combine(t.context_id()).unwrap();
})
.map(|t| maybe_done(t))
.collect();
JoinIter { id, vec }
}
}
unsafe impl<T, Ec> GpuTask<Ec> for JoinIter<T, Ec>
where
T: GpuTask<Ec, Output = ()>,
{
type Output = ();
fn context_id(&self) -> ContextId {
self.id
}
fn progress(&mut self, execution_context: &mut Ec) -> Progress<Self::Output> {
if self.vec.is_empty() {
return Progress::Finished(());
}
let mut all_done = true;
for task in &mut self.vec {
all_done = all_done && task.progress(execution_context);
}
if all_done {
Progress::Finished(())
} else {
Progress::ContinueFenced
}
}
}
impl<T, Ec> Clone for JoinIter<T, Ec>
where
T: Clone,
{
fn clone(&self) -> Self {
JoinIter {
id: self.id.clone(),
vec: self.vec.clone(),
}
}
}
pub fn join<A, B, Ec>(a: A, b: B) -> Join<A, B, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
{
Join::new(a, b)
}
pub fn join_left<A, B, Ec>(a: A, b: B) -> JoinLeft<A, B, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
{
JoinLeft::new(a, b)
}
pub fn join_right<A, B, Ec>(a: A, b: B) -> JoinRight<A, B, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
{
JoinRight::new(a, b)
}
pub fn join3<A, B, C, Ec>(a: A, b: B, c: C) -> Join3<A, B, C, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
{
Join3::new(a, b, c)
}
pub fn join3_left<A, B, C, Ec>(a: A, b: B, c: C) -> Join3Left<A, B, C, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
{
Join3Left::new(a, b, c)
}
pub fn join3_right<A, B, C, Ec>(a: A, b: B, c: C) -> Join3Right<A, B, C, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
{
Join3Right::new(a, b, c)
}
pub fn join4<A, B, C, D, Ec>(a: A, b: B, c: C, d: D) -> Join4<A, B, C, D, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
{
Join4::new(a, b, c, d)
}
pub fn join4_left<A, B, C, D, Ec>(a: A, b: B, c: C, d: D) -> Join4Left<A, B, C, D, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
{
Join4Left::new(a, b, c, d)
}
pub fn join4_right<A, B, C, D, Ec>(a: A, b: B, c: C, d: D) -> Join4Right<A, B, C, D, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
{
Join4Right::new(a, b, c, d)
}
pub fn join5<A, B, C, D, E, Ec>(a: A, b: B, c: C, d: D, e: E) -> Join5<A, B, C, D, E, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
E: GpuTask<Ec>,
{
Join5::new(a, b, c, d, e)
}
pub fn join5_left<A, B, C, D, E, Ec>(a: A, b: B, c: C, d: D, e: E) -> Join5Left<A, B, C, D, E, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
E: GpuTask<Ec>,
{
Join5Left::new(a, b, c, d, e)
}
pub fn join5_right<A, B, C, D, E, Ec>(a: A, b: B, c: C, d: D, e: E) -> Join5Right<A, B, C, D, E, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
E: GpuTask<Ec>,
{
Join5Right::new(a, b, c, d, e)
}
pub fn join_iter<I, Ec>(iterator: I) -> JoinIter<I::Item, Ec>
where
I: IntoIterator,
I::Item: GpuTask<Ec, Output = ()>,
{
JoinIter::new(iterator)
}