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 15:14:48 +02:00
committed by GitHub
parent 59a943f42f
commit 212f08c6c8
66 changed files with 1572 additions and 1577 deletions

View File

@@ -1,5 +1,4 @@
use super::DocumentNode;
use crate::graphene_compiler::Any;
pub use crate::imaginate_input::{ImaginateCache, ImaginateController, ImaginateMaskStartingFill, ImaginateSamplingMethod};
use crate::proto::{Any as DAny, FutureAny};
use crate::wasm_application_io::WasmEditorApi;
@@ -47,7 +46,7 @@ macro_rules! tagged_value {
}
impl<'a> TaggedValue {
/// Converts to a Box<dyn DynAny> - this isn't very neat but I'm not sure of a better approach
pub fn to_any(self) -> Any<'a> {
pub fn to_any(self) -> DAny<'a> {
match self {
Self::None => Box::new(()),
$( Self::$identifier(x) => Box::new(x), )*
@@ -227,9 +226,9 @@ impl UpcastNode {
}
}
#[derive(Default, Debug, Clone, Copy)]
pub struct UpcastAsRefNode<T: AsRef<U>, U>(pub T, PhantomData<U>);
pub struct UpcastAsRefNode<T: AsRef<U> + Sync + Send, U: Sync + Send>(pub T, PhantomData<U>);
impl<'i, T: 'i + AsRef<U>, U: 'i + StaticType> Node<'i, DAny<'i>> for UpcastAsRefNode<T, U> {
impl<'i, T: 'i + AsRef<U> + Sync + Send, U: 'i + StaticType + Sync + Send> Node<'i, DAny<'i>> for UpcastAsRefNode<T, U> {
type Output = FutureAny<'i>;
#[inline(always)]
fn eval(&'i self, _: DAny<'i>) -> Self::Output {
@@ -237,7 +236,7 @@ impl<'i, T: 'i + AsRef<U>, U: 'i + StaticType> Node<'i, DAny<'i>> for UpcastAsRe
}
}
impl<T: AsRef<U>, U> UpcastAsRefNode<T, U> {
impl<T: AsRef<U> + Sync + Send, U: Sync + Send> UpcastAsRefNode<T, U> {
pub const fn new(value: T) -> UpcastAsRefNode<T, U> {
UpcastAsRefNode(value, PhantomData)
}

View File

@@ -1,7 +1,5 @@
use std::error::Error;
use dyn_any::DynAny;
use crate::document::NodeNetwork;
use crate::proto::{LocalFuture, ProtoNetwork};
@@ -36,7 +34,6 @@ impl Compiler {
Ok(proto_network)
}
}
pub type Any<'a> = Box<dyn DynAny<'a> + 'a>;
pub trait Executor<I, O> {
fn execute(&self, input: I) -> LocalFuture<Result<O, Box<dyn Error>>>;

View File

@@ -29,7 +29,7 @@ impl core::hash::Hash for ImaginateCache {
}
}
pub trait ImaginateTerminationHandle: Debug + Send + Sync + 'static {
pub trait ImaginateTerminationHandle: Debug + Send + 'static {
fn terminate(&self);
}

View File

@@ -12,25 +12,34 @@ use std::hash::Hash;
use std::ops::Deref;
use std::pin::Pin;
#[cfg(not(target_arch = "wasm32"))]
pub type DynFuture<'n, T> = Pin<Box<dyn core::future::Future<Output = T> + 'n + Send>>;
#[cfg(target_arch = "wasm32")]
pub type DynFuture<'n, T> = Pin<Box<dyn core::future::Future<Output = T> + 'n>>;
pub type LocalFuture<'n, T> = Pin<Box<dyn core::future::Future<Output = T> + 'n>>;
#[cfg(not(target_arch = "wasm32"))]
pub type Any<'n> = Box<dyn DynAny<'n> + 'n + Send>;
#[cfg(target_arch = "wasm32")]
pub type Any<'n> = Box<dyn DynAny<'n> + 'n>;
pub type FutureAny<'n> = DynFuture<'n, Any<'n>>;
// TODO: is this safe? This is assumed to be send+sync.
#[cfg(not(target_arch = "wasm32"))]
pub type TypeErasedNode<'n> = dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n + Send + Sync;
#[cfg(target_arch = "wasm32")]
pub type TypeErasedNode<'n> = dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n;
pub type TypeErasedPinnedRef<'n> = Pin<&'n TypeErasedNode<'n>>;
pub type TypeErasedRef<'n> = &'n TypeErasedNode<'n>;
pub type TypeErasedBox<'n> = Box<TypeErasedNode<'n>>;
pub type TypeErasedPinned<'n> = Pin<Box<TypeErasedNode<'n>>>;
pub type SharedNodeContainer = std::rc::Rc<NodeContainer>;
pub type SharedNodeContainer = std::sync::Arc<NodeContainer>;
pub type NodeConstructor = fn(Vec<SharedNodeContainer>) -> DynFuture<'static, TypeErasedBox<'static>>;
#[derive(Clone)]
pub struct NodeContainer {
#[cfg(feature = "dealloc_nodes")]
pub node: *mut TypeErasedNode<'static>,
pub node: *const TypeErasedNode<'static>,
#[cfg(not(feature = "dealloc_nodes"))]
pub node: TypeErasedRef<'static>,
}
@@ -40,7 +49,7 @@ impl Deref for NodeContainer {
#[cfg(feature = "dealloc_nodes")]
fn deref(&self) -> &Self::Target {
unsafe { &*(self.node as *const TypeErasedNode) }
unsafe { &*(self.node) }
#[cfg(not(feature = "dealloc_nodes"))]
self.node
}
@@ -50,6 +59,14 @@ impl Deref for NodeContainer {
}
}
/// #Safety
/// Marks NodeContainer as Sync. This dissallows the use of threadlocal stroage for nodes as this would invalidate references to them.
// TODO: implement this on a higher level wrapper to avoid missuse
#[cfg(feature = "dealloc_nodes")]
unsafe impl Send for NodeContainer {}
#[cfg(feature = "dealloc_nodes")]
unsafe impl Sync for NodeContainer {}
#[cfg(feature = "dealloc_nodes")]
impl Drop for NodeContainer {
fn drop(&mut self) {
@@ -71,7 +88,7 @@ impl NodeContainer {
#[cfg(feature = "dealloc_nodes")]
unsafe fn dealloc_unchecked(&mut self) {
std::mem::drop(Box::from_raw(self.node));
std::mem::drop(Box::from_raw(self.node as *mut TypeErasedNode));
}
}

View File

@@ -1,20 +1,17 @@
use dyn_any::StaticType;
#[cfg(target_arch = "wasm32")]
use graphene_core::application_io::SurfaceHandleFrame;
use graphene_core::application_io::{ApplicationError, ApplicationIo, ResourceFuture, SurfaceHandle, SurfaceId};
#[cfg(feature = "wgpu")]
use wgpu_executor::WgpuExecutor;
use core::future::Future;
#[cfg(target_arch = "wasm32")]
use js_sys::{Object, Reflect};
use std::collections::HashMap;
use std::pin::Pin;
#[cfg(target_arch = "wasm32")]
use std::sync::atomic::AtomicU64;
use std::sync::Arc;
#[cfg(not(target_arch = "wasm32"))]
use std::sync::Mutex;
// #[cfg(not(target_arch = "wasm32"))]
// use std::sync::Mutex;
#[cfg(feature = "tokio")]
use tokio::io::AsyncReadExt;
#[cfg(target_arch = "wasm32")]
@@ -32,8 +29,8 @@ pub struct WasmApplicationIo {
ids: AtomicU64,
#[cfg(feature = "wgpu")]
pub(crate) gpu_executor: Option<WgpuExecutor>,
#[cfg(not(target_arch = "wasm32"))]
windows: Mutex<Vec<Arc<winit::window::Window>>>,
// #[cfg(not(target_arch = "wasm32"))]
// windows: Mutex<Vec<Arc<winit::window::Window>>>,
pub resources: HashMap<String, Arc<[u8]>>,
}
@@ -61,8 +58,8 @@ impl WasmApplicationIo {
ids: AtomicU64::new(0),
#[cfg(feature = "wgpu")]
gpu_executor: executor,
#[cfg(not(target_arch = "wasm32"))]
windows: Vec::new().into(),
// #[cfg(not(target_arch = "wasm32"))]
// windows: Vec::new().into(),
resources: HashMap::new(),
};
io.resources.insert("null".to_string(), Arc::from(include_bytes!("null.png").to_vec()));
@@ -92,7 +89,7 @@ impl ApplicationIo for WasmApplicationIo {
#[cfg(target_arch = "wasm32")]
type Surface = HtmlCanvasElement;
#[cfg(not(target_arch = "wasm32"))]
type Surface = Arc<winit::window::Window>;
type Surface = winit::window::Window;
#[cfg(feature = "wgpu")]
type Executor = WgpuExecutor;
#[cfg(not(feature = "wgpu"))]
@@ -147,8 +144,7 @@ impl ApplicationIo for WasmApplicationIo {
.with_inner_size(winit::dpi::PhysicalSize::new(800, 600))
.build(&event_loop)
.unwrap();
let window = Arc::new(window);
self.windows.lock().as_mut().unwrap().push(window.clone());
// self.windows.lock().as_mut().unwrap().push(window.clone());
SurfaceHandle {
surface_id: SurfaceId(window.id().into()),
surface: window,
@@ -199,7 +195,7 @@ impl ApplicationIo for WasmApplicationIo {
let mut data = Vec::new();
reader.read_to_end(&mut data).await.map_err(|_| ApplicationError::NotFound)?;
Ok(Arc::from(data))
}) as Pin<Box<dyn Future<Output = Result<Arc<[u8]>, _>>>>)
}) as ResourceFuture)
}
"http" | "https" => {
let url = url.to_string();
@@ -208,21 +204,19 @@ impl ApplicationIo for WasmApplicationIo {
let response = client.get(url).send().await.map_err(|_| ApplicationError::NotFound)?;
let data = response.bytes().await.map_err(|_| ApplicationError::NotFound)?;
Ok(Arc::from(data.to_vec()))
}) as Pin<Box<dyn Future<Output = Result<Arc<[u8]>, _>>>>)
}) as ResourceFuture)
}
"graphite" => {
let path = url.path();
let path = path.to_owned();
log::trace!("Loading local resource: {path}");
let data = self.resources.get(&path).ok_or(ApplicationError::NotFound)?.clone();
Ok(Box::pin(async move { Ok(data.clone()) }) as Pin<Box<dyn Future<Output = Result<Arc<[u8]>, _>>>>)
Ok(Box::pin(async move { Ok(data.clone()) }) as ResourceFuture)
}
_ => Err(ApplicationError::NotFound),
}
}
}
#[cfg(target_arch = "wasm32")]
pub type WasmSurfaceHandle = SurfaceHandle<HtmlCanvasElement>;
#[cfg(target_arch = "wasm32")]
pub type WasmSurfaceHandleFrame = SurfaceHandleFrame<HtmlCanvasElement>;
pub type WasmSurfaceHandle = SurfaceHandle<wgpu_executor::Window>;
pub type WasmSurfaceHandleFrame = SurfaceHandleFrame<wgpu_executor::Window>;