mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 23:08:05 +08:00
ICE
This commit is contained in:
committed by
Keavon Chambers
parent
edb33e0c82
commit
1e52715d95
@@ -16,6 +16,17 @@ impl<T: Fn(I) -> O, I, O> FnNode<T, I, O> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnOnceNode<T: FnMut(I) -> O, I, O: Default>(T, PhantomData<(I, O)>);
|
||||
|
||||
impl<'i, T: FnMut(I) -> O + 'i, I: 'i, O: 'i + Default> FnOnceNode<T, I, O> {
|
||||
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;
|
||||
|
||||
@@ -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<N> {
|
||||
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<N> {
|
||||
impl<'i, 's: 'i, I: 'i, O: 'i, N: Node<'i, I, Output = O> + ?Sized> Node<'i, I> for alloc::sync::Arc<N> {
|
||||
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<N> {
|
||||
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<Box<dyn Node<'i, I, Output = O> + 'i>> {
|
||||
impl<'i, I: 'i, O: 'i> Node<'i, I> for Pin<Box<dyn Node<'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)
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Box<dyn Future<Output = T> + 'i>>;
|
||||
fn eval(&'i self, input: ()) -> Self::Output {
|
||||
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()));
|
||||
|
||||
@@ -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<H: core::hash::Hasher>(&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<Quantization> {
|
||||
@@ -60,14 +71,18 @@ pub struct QuantizeNode<Quantization> {
|
||||
}
|
||||
|
||||
#[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<Quantization> {
|
||||
@@ -75,12 +90,16 @@ pub struct DeQuantizeNode<Quantization> {
|
||||
}
|
||||
|
||||
#[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)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use core::marker::PhantomData;
|
||||
|
||||
use crate::Node;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ComposeNode<First, Second, I> {
|
||||
first: First,
|
||||
second: Second,
|
||||
|
||||
Reference in New Issue
Block a user