#![allow(non_snake_case)]
use super::maybe_done::{maybe_done, MaybeDone};
use super::{ContextId, GpuTask, Progress};
macro_rules! generate_sequence {
($(
$(#[$doc:meta])*
($Sequence:ident, <A, $($B:ident),*>),
)*) => ($(
$(#[$doc])*
pub struct $Sequence<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> $Sequence<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();
)*
$Sequence {
id,
a: maybe_done(a),
$($B: maybe_done($B)),*
}
}
}
unsafe impl<A, $($B),*, Ec> GpuTask<Ec> for $Sequence<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> {
if !self.a.progress(execution_context) {
return Progress::ContinueFenced;
}
$(
if !self.$B.progress(execution_context) {
return Progress::ContinueFenced;
}
)*
Progress::Finished((self.a.take(), $(self.$B.take()),*))
}
}
impl<A, $($B),*, Ec> Clone for $Sequence<A, $($B),*, Ec>
where
A: GpuTask<Ec> + Clone,
A::Output: Clone,
$(
$B: GpuTask<Ec> + Clone,
$B::Output: Clone,
)*
{
fn clone(&self) -> Self {
$Sequence {
id: self.id.clone(),
a: self.a.clone(),
$($B: self.$B.clone()),*
}
}
}
)*)
}
generate_sequence! {
(Sequence, <A, B>),
(Sequence3, <A, B, C>),
(Sequence4, <A, B, C, D>),
(Sequence5, <A, B, C, D, E>),
}
macro_rules! generate_sequence_left {
($(
$(#[$doc:meta])*
($Sequence:ident, <A, $($B:ident),*>),
)*) => ($(
$(#[$doc])*
pub struct $Sequence<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> $Sequence<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();
)*
$Sequence {
id,
a: maybe_done(a),
$($B: maybe_done($B)),*
}
}
}
unsafe impl<A, $($B),*, Ec> GpuTask<Ec> for $Sequence<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> {
if !self.a.progress(execution_context) {
return Progress::ContinueFenced;
}
$(
if !self.$B.progress(execution_context) {
return Progress::ContinueFenced;
}
)*
Progress::Finished(self.a.take())
}
}
impl<A, $($B),*, Ec> Clone for $Sequence<A, $($B),*, Ec>
where
A: GpuTask<Ec> + Clone,
A::Output: Clone,
$(
$B: GpuTask<Ec> + Clone,
$B::Output: Clone,
)*
{
fn clone(&self) -> Self {
$Sequence {
id: self.id.clone(),
a: self.a.clone(),
$($B: self.$B.clone()),*
}
}
}
)*)
}
generate_sequence_left! {
(SequenceLeft, <A, B>),
(Sequence3Left, <A, B, C>),
(Sequence4Left, <A, B, C, D>),
(Sequence5Left, <A, B, C, D, E>),
}
macro_rules! generate_sequence_right {
($(
$(#[$doc:meta])*
($Sequence:ident, <$($A:ident),*> $B:ident),
)*) => ($(
$(#[$doc])*
pub struct $Sequence<$($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> $Sequence<$($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();
$Sequence {
id,
$($A: maybe_done($A),)*
$B: maybe_done($B)
}
}
}
unsafe impl<$($A,)* $B, Ec> GpuTask<Ec> for $Sequence<$($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> {
$(
if !self.$A.progress(execution_context) {
return Progress::ContinueFenced;
}
)*
if !self.$B.progress(execution_context) {
return Progress::ContinueFenced;
}
Progress::Finished(self.$B.take())
}
}
impl<$($A,)* $B, Ec> Clone for $Sequence<$($A,)* $B, Ec>
where
$(
$A: GpuTask<Ec> + Clone,
$A::Output: Clone,
)*
$B: GpuTask<Ec> + Clone,
$B::Output: Clone,
{
fn clone(&self) -> Self {
$Sequence {
id: self.id.clone(),
$($A: self.$A.clone(),)*
$B: self.$B.clone(),
}
}
}
)*)
}
generate_sequence_right! {
(SequenceRight, <A> B),
(Sequence3Right, <A, B> C),
(Sequence4Right, <A, B, C> D),
(Sequence5Right, <A, B, C, D> E),
}
#[doc(hidden)]
#[macro_export]
macro_rules! sequence_all {
($e0:expr, $e1:expr) => (sequence_all!($e0, $e1,));
($e0:expr, $e1:expr, $($e:expr,)+) => (sequence_all!($e0, $e1, $($e),*));
($e0:expr, $e1:expr, $($e:expr),*) => {
{
let sequenced = $crate::task::sequence($e0, $e1);
$(
let sequenced = $crate::task::sequence(sequenced, $e);
)*
sequenced
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! sequence_all_left {
($e0:expr, $e1:expr) => (sequence_all_left!($e0, $e1,));
($e0:expr, $e1:expr, $($e:expr,)+) => (sequence_all_left!($e0, $e1, $($e),*));
($e0:expr, $e1:expr, $($e:expr),*) => {
{
let sequenced = $crate::task::sequence_left($e0, $e1);
$(
let sequenced = $crate::task::sequence_left(sequenced, $e);
)*
sequenced
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! sequence_all_right {
($e0:expr, $e1:expr) => (sequence_all_right!($e0, $e1,));
($e0:expr, $e1:expr, $($e:expr,)+) => (sequence_all_right!($e0, $e1, $($e),*));
($e0:expr, $e1:expr, $($e:expr),*) => {
{
let sequenced = $crate::task::sequence_right($e0, $e1);
$(
let sequenced = $crate::task::sequence_right(sequenced, $e);
)*
sequenced
}
}
}
pub struct SequenceIter<T, Ec> {
id: ContextId,
vec: Vec<MaybeDone<T, (), Ec>>,
}
impl<T, Ec> SequenceIter<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()
.map(|t| {
id = id.combine(t.context_id()).unwrap();
maybe_done(t)
})
.collect();
SequenceIter { id, vec }
}
}
unsafe impl<T, Ec> GpuTask<Ec> for SequenceIter<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> {
for task in &mut self.vec {
if !task.progress(execution_context) {
return Progress::ContinueFenced;
}
}
Progress::Finished(())
}
}
impl<T, Ec> Clone for SequenceIter<T, Ec>
where
T: Clone,
{
fn clone(&self) -> Self {
SequenceIter {
id: self.id.clone(),
vec: self.vec.clone(),
}
}
}
pub fn sequence<A, B, Ec>(a: A, b: B) -> Sequence<A, B, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
{
Sequence::new(a, b)
}
pub fn sequence_left<A, B, Ec>(a: A, b: B) -> SequenceLeft<A, B, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
{
SequenceLeft::new(a, b)
}
pub fn sequence_right<A, B, Ec>(a: A, b: B) -> SequenceRight<A, B, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
{
SequenceRight::new(a, b)
}
pub fn sequence3<A, B, C, Ec>(a: A, b: B, c: C) -> Sequence3<A, B, C, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
{
Sequence3::new(a, b, c)
}
pub fn sequence3_left<A, B, C, Ec>(a: A, b: B, c: C) -> Sequence3Left<A, B, C, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
{
Sequence3Left::new(a, b, c)
}
pub fn sequence3_right<A, B, C, Ec>(a: A, b: B, c: C) -> Sequence3Right<A, B, C, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
{
Sequence3Right::new(a, b, c)
}
pub fn sequence4<A, B, C, D, Ec>(a: A, b: B, c: C, d: D) -> Sequence4<A, B, C, D, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
{
Sequence4::new(a, b, c, d)
}
pub fn sequence4_left<A, B, C, D, Ec>(a: A, b: B, c: C, d: D) -> Sequence4Left<A, B, C, D, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
{
Sequence4Left::new(a, b, c, d)
}
pub fn sequence4_right<A, B, C, D, Ec>(a: A, b: B, c: C, d: D) -> Sequence4Right<A, B, C, D, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
{
Sequence4Right::new(a, b, c, d)
}
pub fn sequence5<A, B, C, D, E, Ec>(a: A, b: B, c: C, d: D, e: E) -> Sequence5<A, B, C, D, E, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
E: GpuTask<Ec>,
{
Sequence5::new(a, b, c, d, e)
}
pub fn sequence5_left<A, B, C, D, E, Ec>(
a: A,
b: B,
c: C,
d: D,
e: E,
) -> Sequence5Left<A, B, C, D, E, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
E: GpuTask<Ec>,
{
Sequence5Left::new(a, b, c, d, e)
}
pub fn sequence5_right<A, B, C, D, E, Ec>(
a: A,
b: B,
c: C,
d: D,
e: E,
) -> Sequence5Right<A, B, C, D, E, Ec>
where
A: GpuTask<Ec>,
B: GpuTask<Ec>,
C: GpuTask<Ec>,
D: GpuTask<Ec>,
E: GpuTask<Ec>,
{
Sequence5Right::new(a, b, c, d, e)
}
pub fn sequence_iter<I, Ec>(iterator: I) -> SequenceIter<I::Item, Ec>
where
I: IntoIterator,
I::Item: GpuTask<Ec, Output = ()>,
{
SequenceIter::new(iterator)
}