Restore functionality of GPU infrastructure (#1797)

* Update gpu nodes to compile again

Restructure `gpu-executor` and `wgpu-executor`

And libssl to nix shell

Fix graphene-cli and add half percision color format

Fix texture scaling

Remove vulkan executor

Fix compile errors

Improve execution request deduplication

* Fix warnings

* Fix graph compile issues

* Code review

* Remove test file

* Fix lint

* Wip make node futures send

* Make futures Send on non wasm targets

* Fix warnings

* Fix nested use of block_on

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-07-15 13:14:48 +00:00
committed by GitHub
co-authored by Keavon Chambers
parent 59a943f42f
commit 212f08c6c8
66 changed files with 1572 additions and 1577 deletions
+56 -50
View File
@@ -1,46 +1,49 @@
use crate::Node;
use crate::{Node, WasmNotSend};
use core::future::Future;
use core::ops::Deref;
use std::sync::Mutex;
#[cfg(feature = "alloc")]
use alloc::sync::Arc;
use core::cell::Cell;
use core::pin::Pin;
use dyn_any::DynFuture;
/// Caches the output of a given Node and acts as a proxy
#[derive(Default)]
pub struct MemoNode<T, CachedNode> {
cache: Cell<Option<T>>,
cache: Arc<Mutex<Option<T>>>,
node: CachedNode,
}
impl<'i, 'o: 'i, T: 'i + Clone + 'o, CachedNode: 'i> Node<'i, ()> for MemoNode<T, CachedNode>
impl<'i, 'o: 'i, T: 'i + Clone + 'o + WasmNotSend, CachedNode: 'i> Node<'i, ()> for MemoNode<T, CachedNode>
where
CachedNode: for<'any_input> Node<'any_input, ()>,
for<'a> <CachedNode as Node<'a, ()>>::Output: core::future::Future<Output = T> + 'a,
for<'a> <CachedNode as Node<'a, ()>>::Output: core::future::Future<Output = T> + WasmNotSend,
{
// TODO: This should return a reference to the cached cached_value
// but that requires a lot of lifetime magic <- This was suggested by copilot but is pretty accurate xD
type Output = Pin<Box<dyn Future<Output = T> + 'i>>;
fn eval(&'i self, input: ()) -> Pin<Box<dyn Future<Output = T> + 'i>> {
Box::pin(async move {
if let Some(cached_value) = self.cache.take() {
self.cache.set(Some(cached_value.clone()));
cached_value
} else {
let value = self.node.eval(input).await;
self.cache.set(Some(value.clone()));
type Output = DynFuture<'i, T>;
fn eval(&'i self, input: ()) -> Self::Output {
if let Some(cached_value) = self.cache.lock().as_ref().unwrap().deref() {
let data = cached_value.clone();
Box::pin(async move { data })
} else {
let fut = self.node.eval(input);
let cache = self.cache.clone();
Box::pin(async move {
let value = fut.await;
*cache.lock().unwrap() = Some(value.clone());
value
}
})
})
}
}
fn reset(&self) {
self.cache.set(None);
self.cache.lock().unwrap().take();
}
}
impl<T, CachedNode> MemoNode<T, CachedNode> {
pub const fn new(node: CachedNode) -> MemoNode<T, CachedNode> {
MemoNode { cache: Cell::new(None), node }
pub fn new(node: CachedNode) -> MemoNode<T, CachedNode> {
MemoNode { cache: Default::default(), node }
}
}
@@ -50,41 +53,43 @@ impl<T, CachedNode> MemoNode<T, CachedNode> {
/// use with caution.
#[derive(Default)]
pub struct ImpureMemoNode<I, T, CachedNode> {
cache: Cell<Option<T>>,
cache: Arc<Mutex<Option<T>>>,
node: CachedNode,
_phantom: std::marker::PhantomData<I>,
}
impl<'i, 'o: 'i, I: 'i, T: 'i + Clone + 'o, CachedNode: 'i> Node<'i, I> for ImpureMemoNode<I, T, CachedNode>
impl<'i, 'o: 'i, I: 'i, T: 'i + Clone + 'o + WasmNotSend, CachedNode: 'i> Node<'i, I> for ImpureMemoNode<I, T, CachedNode>
where
CachedNode: for<'any_input> Node<'any_input, I>,
for<'a> <CachedNode as Node<'a, I>>::Output: core::future::Future<Output = T> + 'a,
for<'a> <CachedNode as Node<'a, I>>::Output: core::future::Future<Output = T> + WasmNotSend,
{
// TODO: This should return a reference to the cached cached_value
// but that requires a lot of lifetime magic <- This was suggested by copilot but is pretty accurate xD
type Output = Pin<Box<dyn Future<Output = T> + 'i>>;
fn eval(&'i self, input: I) -> Pin<Box<dyn Future<Output = T> + 'i>> {
Box::pin(async move {
if let Some(cached_value) = self.cache.take() {
self.cache.set(Some(cached_value.clone()));
cached_value
} else {
let value = self.node.eval(input).await;
self.cache.set(Some(value.clone()));
type Output = DynFuture<'i, T>;
fn eval(&'i self, input: I) -> Self::Output {
if let Some(cached_value) = self.cache.lock().as_ref().unwrap().deref() {
let data = cached_value.clone();
Box::pin(async move { data })
} else {
let fut = self.node.eval(input);
let cache = self.cache.clone();
Box::pin(async move {
let value = fut.await;
*cache.lock().unwrap() = Some(value.clone());
value
}
})
})
}
}
fn reset(&self) {
self.cache.set(None);
self.cache.lock().unwrap().take();
}
}
impl<T, I, CachedNode> ImpureMemoNode<I, T, CachedNode> {
pub const fn new(node: CachedNode) -> ImpureMemoNode<I, T, CachedNode> {
pub fn new(node: CachedNode) -> ImpureMemoNode<I, T, CachedNode> {
ImpureMemoNode {
cache: Cell::new(None),
cache: Default::default(),
node,
_phantom: core::marker::PhantomData,
}
@@ -102,37 +107,38 @@ pub struct IORecord<I, O> {
/// Caches the output of the last graph evaluation for introspection
#[derive(Default)]
pub struct MonitorNode<I, T, N> {
io: Cell<Option<Arc<IORecord<I, T>>>>,
#[allow(clippy::type_complexity)]
io: Arc<Mutex<Option<Arc<IORecord<I, T>>>>>,
node: N,
}
#[cfg(feature = "alloc")]
impl<'i, 'a: 'i, T, I, N> Node<'i, I> for MonitorNode<I, T, N>
impl<'i, T, I, N> Node<'i, I> for MonitorNode<I, T, N>
where
I: Clone + 'static,
<N as Node<'i, I>>::Output: Future<Output = T>,
T: Clone + 'static,
N: Node<'i, I>,
I: Clone + 'static + Send + Sync,
T: Clone + 'static + Send + Sync,
for<'a> N: Node<'a, I, Output: Future<Output = T> + WasmNotSend> + 'i,
{
type Output = Pin<Box<dyn Future<Output = T> + 'i>>;
type Output = DynFuture<'i, T>;
fn eval(&'i self, input: I) -> Self::Output {
let io = self.io.clone();
let output_fut = self.node.eval(input.clone());
Box::pin(async move {
let output = self.node.eval(input.clone()).await;
self.io.set(Some(Arc::new(IORecord { input, output: output.clone() })));
let output = output_fut.await;
*io.lock().unwrap() = Some(Arc::new(IORecord { input, output: output.clone() }));
output
})
}
fn serialize(&self) -> Option<Arc<dyn core::any::Any>> {
let io = self.io.take();
self.io.set(io.clone());
let io = self.io.lock().unwrap();
(io).as_ref().map(|output| output.clone() as Arc<dyn core::any::Any>)
}
}
#[cfg(feature = "alloc")]
impl<I, T, N> MonitorNode<I, T, N> {
pub const fn new(node: N) -> MonitorNode<I, T, N> {
MonitorNode { io: Cell::new(None), node }
pub fn new(node: N) -> MonitorNode<I, T, N> {
MonitorNode { io: Arc::new(Mutex::new(None)), node }
}
}