mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Bump dyn-any version + format code
This commit is contained in:
@@ -1,46 +1,32 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::Node;
|
||||
pub struct FnNode<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O>(
|
||||
T,
|
||||
N,
|
||||
PhantomData<&'n O>,
|
||||
);
|
||||
pub struct FnNode<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O>(T, N, PhantomData<&'n O>);
|
||||
impl<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O> Node<'n> for FnNode<'n, T, N, O> {
|
||||
type Output = O;
|
||||
type Output = O;
|
||||
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0(self.1.eval())
|
||||
}
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0(self.1.eval())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O> FnNode<'n, T, N, O> {
|
||||
pub fn new(f: T, input: N) -> Self {
|
||||
FnNode(f, input, PhantomData)
|
||||
}
|
||||
pub fn new(f: T, input: N) -> Self {
|
||||
FnNode(f, input, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnNodeWithState<
|
||||
'n,
|
||||
T: Fn(<N as Node<'n>>::Output, &'n State) -> O,
|
||||
N: Node<'n>,
|
||||
O,
|
||||
State: 'n,
|
||||
>(T, N, State, PhantomData<&'n O>);
|
||||
impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n> Node<'n>
|
||||
for FnNodeWithState<'n, T, N, O, State>
|
||||
{
|
||||
type Output = O;
|
||||
pub struct FnNodeWithState<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O, State: 'n>(T, N, State, PhantomData<&'n O>);
|
||||
impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n> Node<'n> for FnNodeWithState<'n, T, N, O, State> {
|
||||
type Output = O;
|
||||
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0(self.1.eval(), &self.2)
|
||||
}
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0(self.1.eval(), &self.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n>
|
||||
FnNodeWithState<'n, T, N, O, State>
|
||||
{
|
||||
pub fn new(f: T, input: N, state: State) -> Self {
|
||||
FnNodeWithState(f, input, state, PhantomData)
|
||||
}
|
||||
impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n> FnNodeWithState<'n, T, N, O, State> {
|
||||
pub fn new(f: T, input: N, state: State) -> Self {
|
||||
FnNodeWithState(f, input, state, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,62 +14,62 @@ pub mod ops;
|
||||
pub mod value;
|
||||
|
||||
pub trait Node<'n> {
|
||||
type Output; // TODO: replace with generic associated type
|
||||
type Output; // TODO: replace with generic associated type
|
||||
|
||||
fn eval(&'n self) -> Self::Output;
|
||||
fn eval(&'n self) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<'n, N: Node<'n>> Node<'n> for &'n N {
|
||||
type Output = N::Output;
|
||||
type Output = N::Output;
|
||||
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
Node::eval(*self)
|
||||
}
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
Node::eval(*self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NodeInput {
|
||||
type Nodes;
|
||||
type Nodes;
|
||||
|
||||
fn new(input: Self::Nodes) -> Self;
|
||||
fn new(input: Self::Nodes) -> Self;
|
||||
}
|
||||
|
||||
trait FQN {
|
||||
fn fqn(&self) -> &'static str;
|
||||
fn fqn(&self) -> &'static str;
|
||||
}
|
||||
|
||||
trait Input<I> {
|
||||
unsafe fn input(&self, input: I);
|
||||
unsafe fn input(&self, input: I);
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_trait]
|
||||
pub trait AsyncNode<'n> {
|
||||
type Output; // TODO: replace with generic associated type
|
||||
type Output; // TODO: replace with generic associated type
|
||||
|
||||
async fn eval_async(&'n self) -> Self::Output;
|
||||
async fn eval_async(&'n self) -> Self::Output;
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_trait]
|
||||
impl<'n, N: Node<'n> + Sync> AsyncNode<'n> for N {
|
||||
type Output = N::Output;
|
||||
type Output = N::Output;
|
||||
|
||||
async fn eval_async(&'n self) -> Self::Output {
|
||||
Node::eval(self)
|
||||
}
|
||||
async fn eval_async(&'n self) -> Self::Output {
|
||||
Node::eval(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Cache {
|
||||
fn clear(&mut self);
|
||||
fn clear(&mut self);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "gpu"))]
|
||||
extern crate alloc;
|
||||
#[cfg(not(feature = "gpu"))]
|
||||
impl<'n, I, O: 'n> Node<'n, I> for alloc::boxed::Box<dyn Node<'n, I, Output = O>> {
|
||||
type Output = O;
|
||||
type Output = O;
|
||||
|
||||
fn eval(&'n self, input: &'n I) -> Self::Output {
|
||||
self.as_ref().eval(input)
|
||||
}
|
||||
fn eval(&'n self, input: &'n I) -> Self::Output {
|
||||
self.as_ref().eval(input)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,165 +3,156 @@ use core::{marker::PhantomData, ops::Add};
|
||||
use crate::{Node, NodeInput};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct AddNode<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>>(
|
||||
pub I1,
|
||||
pub I2,
|
||||
PhantomData<&'n (L, R)>,
|
||||
);
|
||||
impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> Node<'n>
|
||||
for AddNode<'n, L, R, I1, I2>
|
||||
{
|
||||
type Output = <L as Add<R>>::Output;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval() + self.1.eval()
|
||||
}
|
||||
pub struct AddNode<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>>(pub I1, pub I2, PhantomData<&'n (L, R)>);
|
||||
impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> Node<'n> for AddNode<'n, L, R, I1, I2> {
|
||||
type Output = <L as Add<R>>::Output;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval() + self.1.eval()
|
||||
}
|
||||
}
|
||||
impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>>
|
||||
AddNode<'n, L, R, I1, I2>
|
||||
{
|
||||
pub fn new(input: (I1, I2)) -> AddNode<'n, L, R, I1, I2> {
|
||||
AddNode(input.0, input.1, PhantomData)
|
||||
}
|
||||
impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> AddNode<'n, L, R, I1, I2> {
|
||||
pub fn new(input: (I1, I2)) -> AddNode<'n, L, R, I1, I2> {
|
||||
AddNode(input.0, input.1, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CloneNode<'n, N: Node<'n, Output = &'n O>, O: Clone + 'n>(pub N, PhantomData<&'n ()>);
|
||||
impl<'n, N: Node<'n, Output = &'n O>, O: Clone> Node<'n> for CloneNode<'n, N, O> {
|
||||
type Output = O;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval().clone()
|
||||
}
|
||||
type Output = O;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval().clone()
|
||||
}
|
||||
}
|
||||
impl<'n, N: Node<'n, Output = &'n O>, O: Clone> CloneNode<'n, N, O> {
|
||||
pub const fn new(node: N) -> CloneNode<'n, N, O> {
|
||||
CloneNode(node, PhantomData)
|
||||
}
|
||||
pub const fn new(node: N) -> CloneNode<'n, N, O> {
|
||||
CloneNode(node, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct FstNode<'n, N: Node<'n>>(pub N, PhantomData<&'n ()>);
|
||||
impl<'n, T: 'n, U, N: Node<'n, Output = (T, U)>> Node<'n> for FstNode<'n, N> {
|
||||
type Output = T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (a, _) = self.0.eval();
|
||||
a
|
||||
}
|
||||
type Output = T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (a, _) = self.0.eval();
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Destructures a Tuple of two values and returns the first one
|
||||
pub struct SndNode<'n, N: Node<'n>>(pub N, PhantomData<&'n ()>);
|
||||
impl<'n, T, U: 'n, N: Node<'n, Output = (T, U)>> Node<'n> for SndNode<'n, N> {
|
||||
type Output = U;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (_, b) = self.0.eval();
|
||||
b
|
||||
}
|
||||
type Output = U;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (_, b) = self.0.eval();
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Return a tuple with two instances of the input argument
|
||||
pub struct DupNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
|
||||
impl<'n, N: Node<'n>> Node<'n> for DupNode<'n, N> {
|
||||
type Output = (N::Output, N::Output);
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
(self.0.eval(), self.0.eval()) //TODO: use Copy/Clone implementation
|
||||
}
|
||||
type Output = (N::Output, N::Output);
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
(self.0.eval(), self.0.eval()) //TODO: use Copy/Clone implementation
|
||||
}
|
||||
}
|
||||
impl<'n, N: Node<'n>> NodeInput for DupNode<'n, N> {
|
||||
type Nodes = N;
|
||||
type Nodes = N;
|
||||
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Return the Input Argument
|
||||
pub struct IdNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
|
||||
impl<'n, N: Node<'n>> Node<'n> for IdNode<'n, N> {
|
||||
type Output = N::Output;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval()
|
||||
}
|
||||
type Output = N::Output;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval()
|
||||
}
|
||||
}
|
||||
impl<'n, N: Node<'n>> NodeInput for IdNode<'n, N> {
|
||||
type Nodes = N;
|
||||
type Nodes = N;
|
||||
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn foo() {
|
||||
let unit = crate::value::UnitNode;
|
||||
let value = IdNode(crate::value::ValueNode(2u32), PhantomData);
|
||||
let value2 = crate::value::ValueNode(4u32);
|
||||
let dup = DupNode(&value, PhantomData);
|
||||
fn int(_: (), state: &u32) -> &u32 {
|
||||
state
|
||||
}
|
||||
fn swap<'n>(input: (&'n u32, &'n u32)) -> (&'n u32, &'n u32) {
|
||||
(input.1, input.0)
|
||||
}
|
||||
let fnn = crate::generic::FnNode::new(swap, &dup);
|
||||
let fns = crate::generic::FnNodeWithState::new(int, &unit, 42u32);
|
||||
let _ = fnn.eval();
|
||||
let _ = fns.eval();
|
||||
let snd = SndNode(&fnn, PhantomData);
|
||||
let _ = snd.eval();
|
||||
let add = AddNode(&snd, value2, PhantomData);
|
||||
let _ = add.eval();
|
||||
let unit = crate::value::UnitNode;
|
||||
let value = IdNode(crate::value::ValueNode(2u32), PhantomData);
|
||||
let value2 = crate::value::ValueNode(4u32);
|
||||
let dup = DupNode(&value, PhantomData);
|
||||
fn int(_: (), state: &u32) -> &u32 {
|
||||
state
|
||||
}
|
||||
fn swap<'n>(input: (&'n u32, &'n u32)) -> (&'n u32, &'n u32) {
|
||||
(input.1, input.0)
|
||||
}
|
||||
let fnn = crate::generic::FnNode::new(swap, &dup);
|
||||
let fns = crate::generic::FnNodeWithState::new(int, &unit, 42u32);
|
||||
let _ = fnn.eval();
|
||||
let _ = fns.eval();
|
||||
let snd = SndNode(&fnn, PhantomData);
|
||||
let _ = snd.eval();
|
||||
let add = AddNode(&snd, value2, PhantomData);
|
||||
let _ = add.eval();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "spirv")]
|
||||
pub mod gpu {
|
||||
//#![deny(warnings)]
|
||||
#[repr(C)]
|
||||
pub struct PushConsts {
|
||||
n: u32,
|
||||
node: u32,
|
||||
}
|
||||
use super::*;
|
||||
use crate::{structural::ComposeNodeOwned, Node};
|
||||
//use crate::Node;
|
||||
use spirv_std::glam::UVec3;
|
||||
const ADD: AddNode<u32> = AddNode(PhantomData);
|
||||
const OPERATION: ComposeNodeOwned<'_, (u32, u32), u32, FstNode<u32, u32>, DupNode<u32>> =
|
||||
ComposeNodeOwned::new(FstNode(PhantomData, PhantomData), DupNode(PhantomData));
|
||||
//#![deny(warnings)]
|
||||
#[repr(C)]
|
||||
pub struct PushConsts {
|
||||
n: u32,
|
||||
node: u32,
|
||||
}
|
||||
use super::*;
|
||||
use crate::{structural::ComposeNodeOwned, Node};
|
||||
//use crate::Node;
|
||||
use spirv_std::glam::UVec3;
|
||||
const ADD: AddNode<u32> = AddNode(PhantomData);
|
||||
const OPERATION: ComposeNodeOwned<'_, (u32, u32), u32, FstNode<u32, u32>, DupNode<u32>> = ComposeNodeOwned::new(FstNode(PhantomData, PhantomData), DupNode(PhantomData));
|
||||
|
||||
#[allow(unused)]
|
||||
#[spirv(compute(threads(64)))]
|
||||
pub fn spread(
|
||||
#[spirv(global_invocation_id)] global_id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [(u32, u32)],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
fn node_graph(input: Input) -> Output {
|
||||
let n0 = ValueNode::new(input);
|
||||
let n1 = IdNode::new(n0);
|
||||
let n2 = IdNode::new(n1);
|
||||
return n2.eval();
|
||||
}
|
||||
let gid = global_id.x as usize;
|
||||
// Only process up to n, which is the length of the buffers.
|
||||
if global_id.x < push_consts.n {
|
||||
y[gid] = node_graph(a[gid]);
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
#[spirv(compute(threads(64)))]
|
||||
pub fn add(
|
||||
#[spirv(global_invocation_id)] global_id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [u32],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
let gid = global_id.x as usize;
|
||||
// Only process up to n, which is the length of the buffers.
|
||||
if global_id.x < push_consts.n {
|
||||
y[gid] = ADD.eval(a[gid]);
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
#[spirv(compute(threads(64)))]
|
||||
pub fn spread(
|
||||
#[spirv(global_invocation_id)] global_id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [(u32, u32)],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
fn node_graph(input: Input) -> Output {
|
||||
let n0 = ValueNode::new(input);
|
||||
let n1 = IdNode::new(n0);
|
||||
let n2 = IdNode::new(n1);
|
||||
return n2.eval();
|
||||
}
|
||||
let gid = global_id.x as usize;
|
||||
// Only process up to n, which is the length of the buffers.
|
||||
if global_id.x < push_consts.n {
|
||||
y[gid] = node_graph(a[gid]);
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
#[spirv(compute(threads(64)))]
|
||||
pub fn add(
|
||||
#[spirv(global_invocation_id)] global_id: UVec3,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [u32],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
let gid = global_id.x as usize;
|
||||
// Only process up to n, which is the length of the buffers.
|
||||
if global_id.x < push_consts.n {
|
||||
y[gid] = ADD.eval(a[gid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,57 +6,57 @@ use crate::Node;
|
||||
|
||||
pub struct IntNode<const N: u32>;
|
||||
impl<'n, const N: u32> Node<'n> for IntNode<N> {
|
||||
type Output = u32;
|
||||
fn eval(&self) -> u32 {
|
||||
N
|
||||
}
|
||||
type Output = u32;
|
||||
fn eval(&self) -> u32 {
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ValueNode<T>(pub T);
|
||||
impl<'n, T: 'n> Node<'n> for ValueNode<T> {
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
&self.0
|
||||
}
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl<T> ValueNode<T> {
|
||||
pub const fn new(value: T) -> ValueNode<T> {
|
||||
ValueNode(value)
|
||||
}
|
||||
pub const fn new(value: T) -> ValueNode<T> {
|
||||
ValueNode(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DefaultNode<T>(PhantomData<T>);
|
||||
impl<'n, T: Default + 'n> Node<'n> for DefaultNode<T> {
|
||||
type Output = T;
|
||||
fn eval(&self) -> T {
|
||||
T::default()
|
||||
}
|
||||
type Output = T;
|
||||
fn eval(&self) -> T {
|
||||
T::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Return the unit value
|
||||
pub struct UnitNode;
|
||||
impl<'n> Node<'n> for UnitNode {
|
||||
type Output = ();
|
||||
fn eval(&'n self) -> Self::Output {}
|
||||
type Output = ();
|
||||
fn eval(&'n self) -> Self::Output {}
|
||||
}
|
||||
|
||||
pub struct InputNode<T>(MaybeUninit<T>, AtomicBool);
|
||||
impl<'n, T: 'n> Node<'n> for InputNode<T> {
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
unsafe { self.0.assume_init_ref() }
|
||||
} else {
|
||||
panic!("tried to access an input before setting it")
|
||||
}
|
||||
}
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
unsafe { self.0.assume_init_ref() }
|
||||
} else {
|
||||
panic!("tried to access an input before setting it")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> InputNode<T> {
|
||||
pub const fn new() -> InputNode<T> {
|
||||
InputNode(MaybeUninit::uninit(), AtomicBool::new(false))
|
||||
}
|
||||
pub const fn new() -> InputNode<T> {
|
||||
InputNode(MaybeUninit::uninit(), AtomicBool::new(false))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user