mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 13:30:48 +00:00
Update graphene-cli
and fix no-std compilation for graphene-core
(#1428)
* Initialize wgpu executor from graphene cli * Make `graphene-core` `no-std` complient again * Implemnt image similarity calculation * Add nan checks * Make image comparison optional * Feature gate quantization to reduce the number of warnings
This commit is contained in:
parent
b9027883a8
commit
7e3469fa3f
14 changed files with 571 additions and 406 deletions
117
Cargo.lock
generated
117
Cargo.lock
generated
|
@ -507,6 +507,12 @@ version = "0.6.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bit_field"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
|
@ -1346,6 +1352,22 @@ version = "2.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||
|
||||
[[package]]
|
||||
name = "exr"
|
||||
version = "1.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "279d3efcc55e19917fff7ab3ddd6c14afb6a90881a0078465196fe2f99d08c56"
|
||||
dependencies = [
|
||||
"bit_field",
|
||||
"flume",
|
||||
"half",
|
||||
"lebe",
|
||||
"miniz_oxide",
|
||||
"rayon-core",
|
||||
"smallvec",
|
||||
"zune-inflate",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
|
@ -1418,6 +1440,19 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.10.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"nanorand",
|
||||
"pin-project",
|
||||
"spin 0.9.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
|
@ -1746,8 +1781,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2062,6 +2109,7 @@ dependencies = [
|
|||
"graph-craft",
|
||||
"graphene-core",
|
||||
"image",
|
||||
"image-compare",
|
||||
"js-sys",
|
||||
"log",
|
||||
"node-macro",
|
||||
|
@ -2533,10 +2581,26 @@ dependencies = [
|
|||
"bytemuck",
|
||||
"byteorder",
|
||||
"color_quant",
|
||||
"exr",
|
||||
"gif",
|
||||
"jpeg-decoder",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"png",
|
||||
"qoi",
|
||||
"tiff",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image-compare"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "419d59423b7202f6a2a95d3b9cf11a8cc9bf83a29cf7dda4d617a90e8c5ccfcf"
|
||||
dependencies = [
|
||||
"image",
|
||||
"itertools",
|
||||
"rayon",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2714,6 +2778,9 @@ name = "jpeg-decoder"
|
|||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
|
||||
dependencies = [
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
|
@ -2775,6 +2842,12 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lebe"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
|
@ -3094,6 +3167,15 @@ dependencies = [
|
|||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
dependencies = [
|
||||
"getrandom 0.2.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.11"
|
||||
|
@ -3931,6 +4013,15 @@ version = "1.0.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46b2164ebdb1dfeec5e337be164292351e11daf63a05174c6776b2f47460f0c9"
|
||||
|
||||
[[package]]
|
||||
name = "qoi"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.23.1"
|
||||
|
@ -5476,6 +5567,17 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiff"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"jpeg-decoder",
|
||||
"weezl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
|
@ -6353,6 +6455,12 @@ dependencies = [
|
|||
"windows-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||
|
||||
[[package]]
|
||||
name = "wgpu"
|
||||
version = "0.17.0"
|
||||
|
@ -7031,6 +7139,15 @@ dependencies = [
|
|||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zune-inflate"
|
||||
version = "0.2.54"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
|
||||
dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "3.15.0"
|
||||
|
|
|
@ -4,6 +4,7 @@ pub struct LogToConsoleNode;
|
|||
|
||||
#[node_macro::node_fn(LogToConsoleNode)]
|
||||
fn log_to_console<T: core::fmt::Debug>(value: T) -> T {
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
debug!("{:#?}", value);
|
||||
value
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ use core::marker::PhantomData;
|
|||
use core::ops::{Add, Div, Mul, Rem, Sub};
|
||||
use num_traits::Pow;
|
||||
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use spirv_std::num_traits::float::Float;
|
||||
|
||||
// Add
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct AddNode;
|
||||
|
|
|
@ -150,13 +150,27 @@ fn dequantize_fn<'a>(color: PackedPixel, quantization: [Quantization; 4]) -> Col
|
|||
|
||||
pub fn dequantize_color(color: PackedPixel, quant: [Quantization; 4]) -> Color {
|
||||
let mut offset = 0;
|
||||
let r = decode(color.0, offset, quant[0]);
|
||||
let mut r = decode(color.0, offset, quant[0]);
|
||||
offset += quant[0].bits();
|
||||
let g = decode(color.0, offset, quant[1]);
|
||||
let mut g = decode(color.0, offset, quant[1]);
|
||||
offset += quant[1].bits();
|
||||
let b = decode(color.0, offset, quant[2]);
|
||||
let mut b = decode(color.0, offset, quant[2]);
|
||||
offset += quant[2].bits();
|
||||
let a = decode(color.0, offset, quant[3]);
|
||||
let mut a = decode(color.0, offset, quant[3]);
|
||||
if a.is_nan() {
|
||||
a = 0.;
|
||||
}
|
||||
|
||||
if r.is_nan() {
|
||||
r = 0.;
|
||||
}
|
||||
|
||||
if g.is_nan() {
|
||||
g = 0.;
|
||||
}
|
||||
if b.is_nan() {
|
||||
b = 0.;
|
||||
}
|
||||
|
||||
Color::from_rgbaf32_unchecked(r, g, b, a)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ use glam::DVec2;
|
|||
|
||||
pub use self::color::{Color, Luma, SRGBA8};
|
||||
|
||||
#[cfg(target_arch = "spirv")]
|
||||
use spirv_std::num_traits::float::Float;
|
||||
|
||||
pub mod adjustments;
|
||||
pub mod bbox;
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
|
@ -14,6 +17,7 @@ pub mod brightness_contrast;
|
|||
#[cfg(not(target_arch = "spirv"))]
|
||||
pub mod brush_cache;
|
||||
pub mod color;
|
||||
#[cfg(not(target_arch = "spirv"))]
|
||||
pub mod curve;
|
||||
pub mod discrete_srgb;
|
||||
pub use adjustments::*;
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#![allow(clippy::too_many_arguments)]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode};
|
||||
use super::{Channel, Color, ImageFrame, Node, RGBMut};
|
||||
use super::{Channel, Color, Node, RGBMut};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use super::ImageFrame;
|
||||
|
||||
use bezier_rs::{Bezier, TValue};
|
||||
use dyn_any::{DynAny, StaticType};
|
||||
|
||||
use core::fmt::Debug;
|
||||
|
@ -890,14 +893,17 @@ fn exposure(color: Color, exposure: f32, offset: f32, gamma_correction: f32) ->
|
|||
|
||||
const WINDOW_SIZE: usize = 1024;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct GenerateCurvesNode<OutputChannel, Curve> {
|
||||
curve: Curve,
|
||||
_channel: core::marker::PhantomData<OutputChannel>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[node_macro::node_fn(GenerateCurvesNode<_Channel>)]
|
||||
fn generate_curves<_Channel: Channel + super::Linear>(_primary: (), curve: Curve) -> ValueMapperNode<_Channel> {
|
||||
use bezier_rs::{Bezier, TValue};
|
||||
let [mut pos, mut param]: [[f32; 2]; 2] = [[0.; 2], curve.first_handle];
|
||||
let mut lut = vec![_Channel::from_f64(0.); WINDOW_SIZE];
|
||||
let end = CurveManipulatorGroup {
|
||||
|
@ -934,11 +940,13 @@ fn generate_curves<_Channel: Channel + super::Linear>(_primary: (), curve: Curve
|
|||
ValueMapperNode::new(lut)
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ColorFillNode<C> {
|
||||
color: C,
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[node_macro::node_fn(ColorFillNode)]
|
||||
pub fn color_fill_node(mut image_frame: ImageFrame<Color>, color: Color) -> ImageFrame<Color> {
|
||||
for pixel in &mut image_frame.image.data {
|
||||
|
@ -951,12 +959,14 @@ pub fn color_fill_node(mut image_frame: ImageFrame<Color>, color: Color) -> Imag
|
|||
image_frame
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
pub struct ColorOverlayNode<Color, BlendMode, Opacity> {
|
||||
color: Color,
|
||||
blend_mode: BlendMode,
|
||||
opacity: Opacity,
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[node_macro::node_fn(ColorOverlayNode)]
|
||||
pub fn color_overlay_node(mut image: ImageFrame<Color>, color: Color, blend_mode: BlendMode, opacity: f32) -> ImageFrame<Color> {
|
||||
let opacity = (opacity / 100.).clamp(0., 1.);
|
||||
|
|
770
node-graph/gpu-compiler/Cargo.lock
generated
770
node-graph/gpu-compiler/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-03-04"
|
||||
channel = "nightly-2023-05-27"
|
||||
components = [
|
||||
"rust-src",
|
||||
"rustc-dev",
|
||||
|
|
|
@ -13,7 +13,7 @@ crate-type = ["dylib", "lib"]
|
|||
libm = { git = "https://github.com/rust-lang/libm", tag = "0.2.5" }
|
||||
|
||||
[dependencies]
|
||||
spirv-std = { version = "0.8" }
|
||||
spirv-std = { version = "0.9" }
|
||||
graphene-core = { path = "{{gcore_path}}", default-features = false, features = [
|
||||
"gpu",
|
||||
] }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2023-03-04"
|
||||
channel = "nightly-2023-05-27"
|
||||
components = [
|
||||
"rust-src",
|
||||
"rustc-dev",
|
||||
|
|
|
@ -21,10 +21,14 @@ wgpu = ["gpu", "wgpu-executor"]
|
|||
quantization = ["autoquant"]
|
||||
wasm = ["wasm-bindgen", "web-sys", "js-sys"]
|
||||
imaginate = ["image/png", "base64", "js-sys", "web-sys", "wasm-bindgen-futures"]
|
||||
image-compare = ["dep:image-compare"]
|
||||
wayland = []
|
||||
|
||||
[dependencies]
|
||||
rand = { version = "0.8.5", features = ["alloc", "small_rng"], default-features = false}
|
||||
rand = { version = "0.8.5", features = [
|
||||
"alloc",
|
||||
"small_rng",
|
||||
], default-features = false }
|
||||
rand_chacha = { version = "0.3.1", default-features = false }
|
||||
autoquant = { git = "https://github.com/truedoctor/autoquant", optional = true, features = [
|
||||
"fitting",
|
||||
|
@ -44,7 +48,10 @@ gpu-compiler-bin-wrapper = { path = "../gpu-compiler/gpu-compiler-bin-wrapper",
|
|||
compilation-client = { path = "../compilation-client", optional = true }
|
||||
bytemuck = { version = "1.13" }
|
||||
tempfile = "3"
|
||||
image = { version = "0.24", default-features = false, features = ["png", "jpeg"] }
|
||||
image = { version = "0.24", default-features = false, features = [
|
||||
"png",
|
||||
"jpeg",
|
||||
] }
|
||||
base64 = { version = "0.21", optional = true }
|
||||
dyn-clone = "1.0"
|
||||
|
||||
|
@ -64,6 +71,7 @@ wasm-bindgen-futures = { version = "0.4.36", optional = true }
|
|||
winit = "0.28.6"
|
||||
url = "2.4.0"
|
||||
tokio = { version = "1.29.0", optional = true, features = ["fs", "io-std"] }
|
||||
image-compare = { version = "0.3.0", optional = true }
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
|
|
|
@ -10,6 +10,9 @@ use graphene_core::raster::*;
|
|||
use graphene_core::*;
|
||||
use wgpu_executor::WgpuExecutor;
|
||||
|
||||
#[cfg(feature = "quantization")]
|
||||
use graphene_core::quantization::PackedPixel;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
@ -74,6 +77,11 @@ async fn map_gpu<'a: 'input>(image: ImageFrame<Color>, node: DocumentNode, edito
|
|||
let quantization = QuantizationChannels::default();
|
||||
log::debug!("quantization: {:?}", quantization);
|
||||
|
||||
#[cfg(feature = "image-compare")]
|
||||
let img: image::DynamicImage = image::Rgba32FImage::from_raw(image.image.width, image.image.height, bytemuck::cast_vec(image.image.data.clone()))
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
#[cfg(feature = "quantization")]
|
||||
let image = ImageFrame {
|
||||
image: Image {
|
||||
|
@ -83,6 +91,7 @@ async fn map_gpu<'a: 'input>(image: ImageFrame<Color>, node: DocumentNode, edito
|
|||
},
|
||||
transform: image.transform,
|
||||
};
|
||||
|
||||
// TODO: The cache should be based on the network topology not the node name
|
||||
let compute_pass_descriptor = if self.cache.borrow().contains_key(&node.name) {
|
||||
self.cache.borrow().get(&node.name).unwrap().clone()
|
||||
|
@ -114,6 +123,14 @@ async fn map_gpu<'a: 'input>(image: ImageFrame<Color>, node: DocumentNode, edito
|
|||
#[cfg(not(feature = "quantization"))]
|
||||
let colors = bytemuck::pod_collect_to_vec::<u8, Color>(result.as_slice());
|
||||
log::debug!("first color: {:?}", colors[0]);
|
||||
|
||||
#[cfg(feature = "image-compare")]
|
||||
let img2: image::DynamicImage = image::Rgba32FImage::from_raw(image.image.width, image.image.height, bytemuck::cast_vec(colors.clone())).unwrap().into();
|
||||
#[cfg(feature = "image-compare")]
|
||||
let score = image_compare::rgb_hybrid_compare(&img.into_rgb8(), &img2.into_rgb8()).unwrap();
|
||||
#[cfg(feature = "image-compare")]
|
||||
log::debug!("score: {:?}", score.score);
|
||||
|
||||
ImageFrame {
|
||||
image: Image {
|
||||
data: colors,
|
||||
|
@ -279,6 +296,10 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(
|
|||
return frame;*/
|
||||
log::debug!("creating buffer");
|
||||
let width_uniform = executor.create_uniform_buffer(image.image.width).unwrap();
|
||||
#[cfg(not(feature = "quantization"))]
|
||||
core::hint::black_box(quantization);
|
||||
|
||||
#[cfg(feature = "quantization")]
|
||||
let quantization_uniform = executor.create_uniform_buffer(quantization).unwrap();
|
||||
let storage_buffer = executor
|
||||
.create_storage_buffer(
|
||||
|
@ -292,7 +313,8 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(
|
|||
)
|
||||
.unwrap();
|
||||
let width_uniform = Arc::new(width_uniform);
|
||||
let _quantization_uniform = Arc::new(quantization_uniform);
|
||||
#[cfg(feature = "quantization")]
|
||||
let quantization_uniform = Arc::new(quantization_uniform);
|
||||
let storage_buffer = Arc::new(storage_buffer);
|
||||
let output_buffer = executor.create_output_buffer(len, concrete!(Color), false).unwrap();
|
||||
let output_buffer = Arc::new(output_buffer);
|
||||
|
|
|
@ -48,7 +48,7 @@ fn generate_quantization(data: Vec<f64>, samples: usize) -> [Quantization; 4] {
|
|||
let merged: ErrorFunction<30> = autoquant::packing::merge_error_functions(&merged, &blue_error);
|
||||
let merged: ErrorFunction<40> = autoquant::packing::merge_error_functions(&merged, &alpha_error);
|
||||
|
||||
let bin_size = 32;
|
||||
let bin_size = 8;
|
||||
let mut distributions = [red, green, blue, alpha].into_iter();
|
||||
|
||||
let bits = &merged.bits[bin_size];
|
||||
|
|
|
@ -56,7 +56,7 @@ impl WasmApplicationIo {
|
|||
None
|
||||
};
|
||||
#[cfg(all(feature = "wgpu", not(target_arch = "wasm32")))]
|
||||
let executor = None;
|
||||
let executor = WgpuExecutor::new().await;
|
||||
let mut io = Self {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
ids: RefCell::new(0),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue