From 1e52715d954f9399c3fa3dd653b8e655832d8aba Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Tue, 27 Jun 2023 22:37:24 +0200 Subject: [PATCH] ICE --- node-graph/compilation-server/src/main.rs | 6 +- node-graph/gcore/src/generic.rs | 11 ++ node-graph/gcore/src/lib.rs | 70 +++++++----- node-graph/gcore/src/memo.rs | 2 +- node-graph/gcore/src/quantization.rs | 103 +++++++++++------- node-graph/gcore/src/structural.rs | 2 +- node-graph/gpu-compiler/src/lib.rs | 8 +- .../src/templates/spirv-template.rs | 8 +- node-graph/graph-craft/src/proto.rs | 10 +- node-graph/graphene-cli/src/main.rs | 2 +- node-graph/gstd/src/gpu_nodes.rs | 49 +++++++-- node-graph/gstd/src/value.rs | 7 +- .../interpreted-executor/src/node_registry.rs | 6 +- 13 files changed, 174 insertions(+), 110 deletions(-) diff --git a/node-graph/compilation-server/src/main.rs b/node-graph/compilation-server/src/main.rs index 90959f43c7..20ac2eb54b 100644 --- a/node-graph/compilation-server/src/main.rs +++ b/node-graph/compilation-server/src/main.rs @@ -43,7 +43,7 @@ async fn post_compile_spirv(State(state): State>, Json(compile_req let result = compile_request.compile(state.compile_dir.path().to_str().expect("non utf8 tempdir path"), &path).map_err(|e| { eprintln!("compilation failed: {}", e); StatusCode::INTERNAL_SERVER_ERROR - }); - state.cache.write().unwrap().insert(compile_request, result.clone()); - result + })?; + state.cache.write().unwrap().insert(compile_request, Ok(result.clone())); + Ok(result) } diff --git a/node-graph/gcore/src/generic.rs b/node-graph/gcore/src/generic.rs index 1b7106fe43..12dccf9be8 100644 --- a/node-graph/gcore/src/generic.rs +++ b/node-graph/gcore/src/generic.rs @@ -16,6 +16,17 @@ impl O, I, O> FnNode { } } +pub struct FnOnceNode O, I, O: Default>(T, PhantomData<(I, O)>); + +impl<'i, T: FnMut(I) -> O + 'i, I: 'i, O: 'i + Default> FnOnceNode { + pub fn new(f: T) -> Self { + FnOnceNode(f, PhantomData) + } + fn eval(&'i mut self, input: I) -> O { + self.0(input) + } +} + pub struct FnNodeWithState<'i, T: Fn(I, &'i State) -> O, I, O, State: 'i>(T, State, PhantomData<(&'i O, I)>); impl<'i, I: 'i, O: 'i, State, T: Fn(I, &'i State) -> O + 'i> Node<'i, I> for FnNodeWithState<'i, T, I, O, State> { type Output = O; diff --git a/node-graph/gcore/src/lib.rs b/node-graph/gcore/src/lib.rs index 018588c4a3..7c8fde37bc 100644 --- a/node-graph/gcore/src/lib.rs +++ b/node-graph/gcore/src/lib.rs @@ -44,7 +44,7 @@ use core::any::TypeId; pub use raster::Color; // pub trait Node: for<'n> NodeIO<'n> { -pub trait Node<'i, Input: 'i>: 'i { +pub trait Node<'i, Input: 'i>: 'i + NodeMut<'i, Input, MutOutput = Self::Output> { type Output: 'i; fn eval(&'i self, input: Input) -> Self::Output; fn reset(&self) {} @@ -55,6 +55,32 @@ pub trait Node<'i, Input: 'i>: 'i { } } +pub trait NodeMut<'i, Input: 'i>: 'i { + type MutOutput: 'i; + fn eval_mut(&'i mut self, input: Input) -> Self::MutOutput; +} + +pub trait NodeOnce<'i, Input> +where + Input: 'i, +{ + type OnceOutput: 'i; + fn eval_once(self, input: Input) -> Self::OnceOutput; +} + +impl<'i, T: Node<'i, I>, I: 'i> NodeOnce<'i, I> for &'i T { + type OnceOutput = T::Output; + fn eval_once(self, input: I) -> Self::OnceOutput { + (self).eval(input) + } +} +impl<'i, T: Node<'i, I> + ?Sized, I: 'i> NodeMut<'i, I> for T { + type MutOutput = T::Output; + fn eval_mut(&'i mut self, input: I) -> Self::MutOutput { + (*self).eval(input) + } +} + #[cfg(feature = "alloc")] mod types; #[cfg(feature = "alloc")] @@ -98,52 +124,40 @@ where { } -impl<'i, 's: 'i, I: 'i, O: 'i, N: Node<'i, I, Output = O>> Node<'i, I> for &'s N { +impl<'i, 's: 'i, I: 'i, N: Node<'i, I> + ?Sized> Node<'i, I> for &'i N { + type Output = N::Output; + fn eval(&'i self, input: I) -> N::Output { + (*self).eval(input) + } +} +#[cfg(feature = "alloc")] +impl<'i, 's: 'i, I: 'i, O: 'i, N: Node<'i, I, Output = O> + ?Sized> Node<'i, I> for Box { type Output = O; - - fn eval(&'i self, input: I) -> Self::Output { + fn eval(&'i self, input: I) -> O { (**self).eval(input) } } #[cfg(feature = "alloc")] -impl<'i, 's: 'i, I: 'i, O: 'i, N: Node<'i, I, Output = O>> Node<'i, I> for Box { +impl<'i, 's: 'i, I: 'i, O: 'i, N: Node<'i, I, Output = O> + ?Sized> Node<'i, I> for alloc::sync::Arc { type Output = O; - - fn eval(&'i self, input: I) -> Self::Output { - (**self).eval(input) - } -} -#[cfg(feature = "alloc")] -impl<'i, 's: 'i, I: 'i, O: 'i, N: Node<'i, I, Output = O>> Node<'i, I> for alloc::sync::Arc { - type Output = O; - - fn eval(&'i self, input: I) -> Self::Output { + fn eval(&'i self, input: I) -> O { (**self).eval(input) } } -impl<'i, I: 'i, O: 'i> Node<'i, I> for &'i dyn Node<'i, I, Output = O> { - type Output = O; - - fn eval(&'i self, input: I) -> Self::Output { - (**self).eval(input) - } -} use core::pin::Pin; use dyn_any::StaticTypeSized; #[cfg(feature = "alloc")] -impl<'i, I: 'i, O: 'i> Node<'i, I> for Pin + 'i>> { +impl<'i, I: 'i, O: 'i> Node<'i, I> for Pin + 'i>> { type Output = O; - - fn eval(&'i self, input: I) -> Self::Output { + fn eval(&'i self, input: I) -> O { (**self).eval(input) } } -impl<'i, I: 'i, O: 'i> Node<'i, I> for Pin<&'i (dyn NodeIO<'i, I, Output = O> + 'i)> { +impl<'i, I: 'i, O: 'i> Node<'i, I> for Pin<&'i (dyn NodeIO<'i, I, Output = O, MutOutput = O> + 'i)> { type Output = O; - - fn eval(&'i self, input: I) -> Self::Output { + fn eval(&'i self, input: I) -> O { (**self).eval(input) } } diff --git a/node-graph/gcore/src/memo.rs b/node-graph/gcore/src/memo.rs index 8ba30abc2a..21d267128c 100644 --- a/node-graph/gcore/src/memo.rs +++ b/node-graph/gcore/src/memo.rs @@ -21,7 +21,7 @@ where // 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 acurate xD type Output = Pin + 'i>>; - fn eval(&'i self, input: ()) -> Self::Output { + fn eval(&'i self, input: ()) -> Pin + 'i>> { Box::pin(async move { if let Some(cached_value) = self.cache.take() { self.cache.set(Some(cached_value.clone())); diff --git a/node-graph/gcore/src/quantization.rs b/node-graph/gcore/src/quantization.rs index 50feb98e69..7aa7859a20 100644 --- a/node-graph/gcore/src/quantization.rs +++ b/node-graph/gcore/src/quantization.rs @@ -1,58 +1,69 @@ use crate::raster::Color; use crate::Node; +use bytemuck::{Pod, Zeroable}; use dyn_any::{DynAny, StaticType}; #[cfg(target_arch = "spirv")] use spirv_std::num_traits::Float; -#[derive(Clone, Debug, DynAny, PartialEq)] +#[derive(Clone, Copy, Debug, DynAny, PartialEq, Pod, Zeroable)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[repr(C)] pub struct Quantization { - pub fn_index: usize, pub a: f32, - pub b: f32, - pub c: f32, - pub d: f32, + pub b_and_bits: u32, +} + +impl Quantization { + pub fn a(&self) -> f32 { + self.a + } + + pub fn b(&self) -> i32 { + (self.b_and_bits >> 16) as i32 + } + + pub fn bits(&self) -> u32 { + self.b_and_bits & 0xFF + } } impl core::hash::Hash for Quantization { fn hash(&self, state: &mut H) { - self.fn_index.hash(state); - self.a.to_bits().hash(state); - self.b.to_bits().hash(state); - self.c.to_bits().hash(state); - self.d.to_bits().hash(state); + self.bits().hash(state); + self.a().to_bits().hash(state); + self.b().hash(state); } } impl Default for Quantization { fn default() -> Self { - Self { - fn_index: Default::default(), - a: 1., - b: Default::default(), - c: Default::default(), - d: Default::default(), - } + Self { a: 1., b_and_bits: 8 } } } pub type QuantizationChannels = [Quantization; 4]; +#[repr(transparent)] +#[derive(DynAny, Clone, Copy, Debug, PartialEq, Eq, Pod, Zeroable)] +pub struct PackedPixel(u32); -fn quantize(value: f32, quantization: &Quantization) -> f32 { - let Quantization { fn_index, a, b, c, d } = quantization; - match fn_index { - 1 => ((value + a) * d).abs().ln() * b + c, - _ => a * value + b, - } +#[inline(always)] +fn quantize(value: f32, offset: u32, quantization: &Quantization) -> u32 { + let a = quantization.a(); + let bits = quantization.bits(); + let b = quantization.b(); + let value = (((a * value) * (1 << bits) as f32) as i32 + b as i32) as u32; + value << (32 - bits - offset) } -fn decode(value: f32, quantization: &Quantization) -> f32 { - let Quantization { fn_index, a, b, c, d } = quantization; - match fn_index { - 1 => -(-c / b).exp() * (a * d * (c / b).exp() - (value / b).exp()) / d, - _ => (value - b) / a, - } +#[inline(always)] +fn decode(value: u32, offset: u32, quantization: &Quantization) -> f32 { + let a = quantization.a(); + let bits = quantization.bits(); + let b = quantization.b(); + let value = (value << offset) >> (32 - bits); + let value = value as i32 - b; + (value as f32 / (1 << bits) as f32) / a } pub struct QuantizeNode { @@ -60,14 +71,18 @@ pub struct QuantizeNode { } #[node_macro::node_fn(QuantizeNode)] -fn quantize_fn<'a>(color: Color, quantization: [Quantization; 4]) -> Color { - let quant = quantization.as_slice(); - let r = quantize(color.r(), &quant[0]); - let g = quantize(color.g(), &quant[1]); - let b = quantize(color.b(), &quant[2]); - let a = quantize(color.a(), &quant[3]); +fn quantize_fn<'a>(color: Color, quantization: [Quantization; 4]) -> PackedPixel { + let quant = quantization; + let mut offset = 0; + let r = quantize(color.r(), offset, &quant[0]); + offset += quant[0].bits(); + let g = quantize(color.g(), offset, &quant[1]); + offset += quant[1].bits(); + let b = quantize(color.b(), offset, &quant[2]); + offset += quant[2].bits(); + let a = quantize(color.a(), offset, &quant[3]); - Color::from_rgbaf32_unchecked(r, g, b, a) + PackedPixel(r | g | b | a) } pub struct DeQuantizeNode { @@ -75,12 +90,16 @@ pub struct DeQuantizeNode { } #[node_macro::node_fn(DeQuantizeNode)] -fn dequantize_fn<'a>(color: Color, quantization: [Quantization; 4]) -> Color { - let quant = quantization.as_slice(); - let r = decode(color.r(), &quant[0]); - let g = decode(color.g(), &quant[1]); - let b = decode(color.b(), &quant[2]); - let a = decode(color.a(), &quant[3]); +fn dequantize_fn<'a>(color: PackedPixel, quantization: [Quantization; 4]) -> Color { + let quant = quantization; + let mut offset = 0; + let r = decode(color.0, offset, &quant[0]); + offset += quant[0].bits(); + let g = decode(color.0, offset, &quant[1]); + offset += quant[1].bits(); + let b = decode(color.0, offset, &quant[2]); + offset += quant[2].bits(); + let a = decode(color.0, offset, &quant[3]); Color::from_rgbaf32_unchecked(r, g, b, a) } diff --git a/node-graph/gcore/src/structural.rs b/node-graph/gcore/src/structural.rs index 273db245c4..157e3522b5 100644 --- a/node-graph/gcore/src/structural.rs +++ b/node-graph/gcore/src/structural.rs @@ -2,7 +2,7 @@ use core::marker::PhantomData; use crate::Node; -#[derive(Clone)] +#[derive(Clone, Copy)] pub struct ComposeNode { first: First, second: Second, diff --git a/node-graph/gpu-compiler/src/lib.rs b/node-graph/gpu-compiler/src/lib.rs index cc07dbbd91..610bd89405 100644 --- a/node-graph/gpu-compiler/src/lib.rs +++ b/node-graph/gpu-compiler/src/lib.rs @@ -216,10 +216,10 @@ pub fn compile(dir: &Path) -> Result = Pin + 'n>>; pub type LocalFuture<'n, T> = Pin + 'n>>; pub type Any<'n> = Box + 'n>; pub type FutureAny<'n> = DynFuture<'n, Any<'n>>; -pub type TypeErasedNode<'n> = dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n; -pub type TypeErasedPinnedRef<'n> = Pin<&'n (dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n)>; -pub type TypeErasedRef<'n> = &'n (dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n); -pub type TypeErasedBox<'n> = Box NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n>; -pub type TypeErasedPinned<'n> = Pin NodeIO<'i, Any<'i>, Output = FutureAny<'i>> + 'n>>; +pub type TypeErasedNode<'n> = dyn for<'i> NodeIO<'i, Any<'i>, Output = FutureAny<'i>, MutOutput = FutureAny<'i>> + 'n; +pub type TypeErasedPinnedRef<'n> = Pin<&'n TypeErasedNode<'n>>; +pub type TypeErasedRef<'n> = &'n TypeErasedNode<'n>; +pub type TypeErasedBox<'n> = Box>; +pub type TypeErasedPinned<'n> = Pin>>; pub type NodeConstructor = for<'a> fn(Vec>) -> DynFuture<'static, TypeErasedBox<'static>>; diff --git a/node-graph/graphene-cli/src/main.rs b/node-graph/graphene-cli/src/main.rs index 7b4e686bb2..0eca3237e5 100644 --- a/node-graph/graphene-cli/src/main.rs +++ b/node-graph/graphene-cli/src/main.rs @@ -44,7 +44,7 @@ async fn main() -> Result<(), Box> { let device = application_io.gpu_executor().unwrap().context.device.clone(); std::thread::spawn(move || loop { - std::thread::sleep(std::time::Duration::from_nanos(1)); + std::thread::sleep(std::time::Duration::from_nanos(10)); device.poll(wgpu::Maintain::Poll); }); diff --git a/node-graph/gstd/src/gpu_nodes.rs b/node-graph/gstd/src/gpu_nodes.rs index e4afc79ff8..48077460be 100644 --- a/node-graph/gstd/src/gpu_nodes.rs +++ b/node-graph/gstd/src/gpu_nodes.rs @@ -4,6 +4,7 @@ use gpu_executor::{GpuExecutor, ShaderIO, ShaderInput}; use graph_craft::document::value::TaggedValue; use graph_craft::document::*; use graph_craft::proto::*; +use graphene_core::quantization::{PackedPixel, QuantizationChannels}; use graphene_core::raster::*; use graphene_core::*; use wgpu_executor::WgpuExecutor; @@ -112,15 +113,27 @@ async fn create_compute_pass_descriptor(node: DocumentNode, image: &ImageFrame>(N, PhantomData<&'n ()>); impl<'n, N: Node<'n, Output = &'n O>, O: DynAny<'n> + 'n> Node<'n> for AnyRefNode<'n, N> { - type Output = &'n (dyn DynAny<'n>); - fn eval(&'n self) -> Self::Output { + fn eval(&'n self) -> &'n (dyn DynAny<'n>) { let value: &O = self.0.eval(); value } @@ -22,8 +21,7 @@ impl<'n, N: Node<'n, Output = &'n O>, O: 'n + ?Sized> AnyRefNode<'n, N> { pub struct StorageNode<'n>(&'n dyn Node<'n, Output = &'n dyn DynAny<'n>>); impl<'n> Node<'n> for StorageNode<'n> { - type Output = &'n (dyn DynAny<'n>); - fn eval(&'n self) -> Self::Output { + fn eval(&'n self) -> &'n (dyn DynAny<'n>) { self.0.eval() } } @@ -36,7 +34,6 @@ impl<'n> StorageNode<'n> { #[derive(Default)] pub struct AnyValueNode<'n, T>(T, PhantomData<&'n ()>); impl<'n, T: 'n + DynAny<'n>> Node<'n> for AnyValueNode<'n, T> { - type Output = &'n dyn DynAny<'n>; fn eval(&'n self) -> &'n dyn DynAny<'n> { &self.0 } diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index 59cf7a8cbf..aef9b81e33 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -1,7 +1,7 @@ use graph_craft::imaginate_input::{ImaginateCache, ImaginateController, ImaginateMaskStartingFill, ImaginateSamplingMethod}; use graph_craft::proto::{NodeConstructor, TypeErasedBox}; use graphene_core::ops::IdNode; -use graphene_core::quantization::QuantizationChannels; +use graphene_core::quantization::{QuantizationChannels, PackedPixel}; use graphene_core::raster::brush_cache::BrushCache; use graphene_core::raster::color::Color; @@ -513,8 +513,8 @@ fn node_registry() -> HashMap, input: Image, params: [DAffine2]), #[cfg(feature = "quantization")] register_node!(graphene_std::quantization::GenerateQuantizationNode<_, _>, input: ImageFrame, params: [u32, u32]), - raster_node!(graphene_core::quantization::QuantizeNode<_>, params: [QuantizationChannels]), - raster_node!(graphene_core::quantization::DeQuantizeNode<_>, params: [QuantizationChannels]), + register_node!(graphene_core::quantization::QuantizeNode<_>, input: Color, params: [QuantizationChannels]), + register_node!(graphene_core::quantization::DeQuantizeNode<_>, input: PackedPixel, params: [QuantizationChannels]), register_node!(graphene_core::ops::CloneNode<_>, input: &QuantizationChannels, params: []), register_node!(graphene_core::transform::TransformNode<_, _, _, _, _>, input: VectorData, params: [DVec2, f32, DVec2, DVec2, DVec2]), register_node!(graphene_core::transform::TransformNode<_, _, _, _, _>, input: ImageFrame, params: [DVec2, f32, DVec2, DVec2, DVec2]),