mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-16 14:58:05 +08:00
Instance tables refactor part 1: wrap graphical data in the new Instances<T> struct (#2230)
* Port VectorData to Instances<VectorData> * Port ImageFrame<P> and TextureFrame to Instances<ImageFrame<P>> and Instances<TextureFrame> * Avoid mutation with the TransformMut trait * Port GraphicGroup to Instances<GraphicGroup> * It compiles! * Organize debugging * Document upgrading * Fix Brush node * Restore TransformMut in lieu of TransformSet trait * Fix tests * Final code review
This commit is contained in:
@@ -4,7 +4,8 @@ use graph_craft::document::value::TaggedValue;
|
||||
use graph_craft::document::*;
|
||||
use graph_craft::proto::*;
|
||||
use graphene_core::application_io::ApplicationIo;
|
||||
use graphene_core::raster::*;
|
||||
use graphene_core::raster::image::{ImageFrame, ImageFrameTable};
|
||||
use graphene_core::raster::{BlendMode, Image, Pixel};
|
||||
use graphene_core::*;
|
||||
use wgpu_executor::{Bindgroup, PipelineLayout, Shader, ShaderIO, ShaderInput, WgpuExecutor, WgpuShaderInput};
|
||||
|
||||
@@ -61,7 +62,10 @@ impl Clone for ComputePass {
|
||||
}
|
||||
|
||||
#[node_macro::old_node_impl(MapGpuNode)]
|
||||
async fn map_gpu<'a: 'input>(image: ImageFrame<Color>, node: DocumentNode, editor_api: &'a graphene_core::application_io::EditorApi<WasmApplicationIo>) -> ImageFrame<Color> {
|
||||
async fn map_gpu<'a: 'input>(image: ImageFrameTable<Color>, node: DocumentNode, editor_api: &'a graphene_core::application_io::EditorApi<WasmApplicationIo>) -> ImageFrameTable<Color> {
|
||||
let image_frame_table = ℑ
|
||||
let image = image.one_item();
|
||||
|
||||
log::debug!("Executing gpu node");
|
||||
let executor = &editor_api.application_io.as_ref().and_then(|io| io.gpu_executor()).unwrap();
|
||||
|
||||
@@ -75,9 +79,9 @@ async fn map_gpu<'a: 'input>(image: ImageFrame<Color>, node: DocumentNode, edito
|
||||
self.cache.lock().as_ref().unwrap().get("placeholder").unwrap().clone()
|
||||
} else {
|
||||
let name = "placeholder".to_string();
|
||||
let Ok(compute_pass_descriptor) = create_compute_pass_descriptor(node, &image, executor).await else {
|
||||
let Ok(compute_pass_descriptor) = create_compute_pass_descriptor(node, image_frame_table, executor).await else {
|
||||
log::error!("Error creating compute pass descriptor in 'map_gpu()");
|
||||
return ImageFrame::empty();
|
||||
return ImageFrameTable::default();
|
||||
};
|
||||
self.cache.lock().as_mut().unwrap().insert(name, compute_pass_descriptor.clone());
|
||||
log::error!("created compute pass");
|
||||
@@ -105,7 +109,7 @@ async fn map_gpu<'a: 'input>(image: ImageFrame<Color>, node: DocumentNode, edito
|
||||
#[cfg(feature = "image-compare")]
|
||||
log::debug!("score: {:?}", score.score);
|
||||
|
||||
ImageFrame {
|
||||
let result = ImageFrame {
|
||||
image: Image {
|
||||
data: colors,
|
||||
width: image.image.width,
|
||||
@@ -114,7 +118,9 @@ async fn map_gpu<'a: 'input>(image: ImageFrame<Color>, node: DocumentNode, edito
|
||||
},
|
||||
transform: image.transform,
|
||||
alpha_blending: image.alpha_blending,
|
||||
}
|
||||
};
|
||||
|
||||
ImageFrameTable::new(result)
|
||||
}
|
||||
|
||||
impl<Node, EditorApi> MapGpuNode<Node, EditorApi> {
|
||||
@@ -127,7 +133,13 @@ impl<Node, EditorApi> MapGpuNode<Node, EditorApi> {
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node: DocumentNode, image: &ImageFrame<T>, executor: &&WgpuExecutor) -> Result<ComputePass, String> {
|
||||
async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node: DocumentNode, image: &ImageFrameTable<T>, executor: &&WgpuExecutor) -> Result<ComputePass, String>
|
||||
where
|
||||
GraphicElement: From<ImageFrame<T>>,
|
||||
T::Static: Pixel,
|
||||
{
|
||||
let image = image.one_item();
|
||||
|
||||
let compiler = graph_craft::graphene_compiler::Compiler {};
|
||||
let inner_network = NodeNetwork::value_network(node);
|
||||
|
||||
@@ -145,40 +157,37 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::ops::IdentityNode".into()),
|
||||
..Default::default()
|
||||
},
|
||||
/*DocumentNode {
|
||||
name: "Index".into(),
|
||||
// inputs: vec![NodeInput::Network(concrete!(UVec3))],
|
||||
inputs: vec![NodeInput::Inline(InlineRust::new("i1.x as usize".into(), concrete![u32]))],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::CopiedNode".into()),
|
||||
..Default::default()
|
||||
},*/
|
||||
/*
|
||||
DocumentNode {
|
||||
name: "Get Node".into(),
|
||||
inputs: vec![NodeInput::node(NodeId(1), 0), NodeInput::node(NodeId(0), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::storage::GetNode".into()),
|
||||
..Default::default()
|
||||
},*/
|
||||
// DocumentNode {
|
||||
// name: "Index".into(),
|
||||
// // inputs: vec![NodeInput::Network(concrete!(UVec3))],
|
||||
// inputs: vec![NodeInput::Inline(InlineRust::new("i1.x as usize".into(), concrete![u32]))],
|
||||
// implementation: DocumentNodeImplementation::ProtoNode("graphene_core::value::CopiedNode".into()),
|
||||
// ..Default::default()
|
||||
// },
|
||||
// DocumentNode {
|
||||
// name: "Get Node".into(),
|
||||
// inputs: vec![NodeInput::node(NodeId(1), 0), NodeInput::node(NodeId(0), 0)],
|
||||
// implementation: DocumentNodeImplementation::ProtoNode("graphene_core::storage::GetNode".into()),
|
||||
// ..Default::default()
|
||||
// },
|
||||
DocumentNode {
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
||||
implementation: DocumentNodeImplementation::Network(inner_network),
|
||||
..Default::default()
|
||||
},
|
||||
/*
|
||||
DocumentNode {
|
||||
name: "Save Node".into(),
|
||||
inputs: vec![
|
||||
NodeInput::node(NodeId(5), 0),
|
||||
NodeInput::Inline(InlineRust::new(
|
||||
"|x| o0[(_global_index.y * i1 + _global_index.x) as usize] = x".into(),
|
||||
// "|x|()".into(),
|
||||
Type::Fn(Box::new(concrete!(PackedPixel)), Box::new(concrete!(()))),
|
||||
)),
|
||||
],
|
||||
implementation: DocumentNodeImplementation::ProtoNode("graphene_core::generic::FnMutNode".into()),
|
||||
..Default::default()
|
||||
},
|
||||
*/
|
||||
// DocumentNode {
|
||||
// name: "Save Node".into(),
|
||||
// inputs: vec![
|
||||
// NodeInput::node(NodeId(5), 0),
|
||||
// NodeInput::Inline(InlineRust::new(
|
||||
// "|x| o0[(_global_index.y * i1 + _global_index.x) as usize] = x".into(),
|
||||
// // "|x|()".into(),
|
||||
// Type::Fn(Box::new(concrete!(PackedPixel)), Box::new(concrete!(()))),
|
||||
// )),
|
||||
// ],
|
||||
// implementation: DocumentNodeImplementation::ProtoNode("graphene_core::generic::FnMutNode".into()),
|
||||
// ..Default::default()
|
||||
// },
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
@@ -204,7 +213,7 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
// return ImageFrame::empty();
|
||||
|
||||
let len: usize = image.image.data.len();
|
||||
|
||||
let storage_buffer = executor
|
||||
@@ -218,21 +227,22 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
/*
|
||||
let canvas = editor_api.application_io.create_surface();
|
||||
|
||||
let surface = unsafe { executor.create_surface(canvas) }.unwrap();
|
||||
let surface_id = surface.surface_id;
|
||||
// let canvas = editor_api.application_io.create_surface();
|
||||
|
||||
let texture = executor.create_texture_buffer(image.image.clone(), TextureBufferOptions::Texture).unwrap();
|
||||
// let surface = unsafe { executor.create_surface(canvas) }.unwrap();
|
||||
// let surface_id = surface.surface_id;
|
||||
|
||||
// executor.create_render_pass(texture, surface).unwrap();
|
||||
// let texture = executor.create_texture_buffer(image.image.clone(), TextureBufferOptions::Texture).unwrap();
|
||||
|
||||
// // executor.create_render_pass(texture, surface).unwrap();
|
||||
|
||||
// let frame = SurfaceFrame {
|
||||
// surface_id,
|
||||
// transform: image.transform,
|
||||
// };
|
||||
// return frame;
|
||||
|
||||
let frame = SurfaceFrame {
|
||||
surface_id,
|
||||
transform: image.transform,
|
||||
};
|
||||
return frame;*/
|
||||
log::debug!("creating buffer");
|
||||
let width_uniform = executor.create_uniform_buffer(image.image.width).unwrap();
|
||||
|
||||
@@ -269,9 +279,13 @@ async fn create_compute_pass_descriptor<T: Clone + Pixel + StaticTypeSized>(node
|
||||
}
|
||||
|
||||
#[node_macro::node(category("Debug: GPU"))]
|
||||
async fn blend_gpu_image(_: (), foreground: ImageFrame<Color>, background: ImageFrame<Color>, blend_mode: BlendMode, opacity: f64) -> ImageFrame<Color> {
|
||||
async fn blend_gpu_image(_: (), foreground: ImageFrameTable<Color>, background: ImageFrameTable<Color>, blend_mode: BlendMode, opacity: f64) -> ImageFrameTable<Color> {
|
||||
let foreground = foreground.one_item();
|
||||
let background = background.one_item();
|
||||
|
||||
let foreground_size = DVec2::new(foreground.image.width as f64, foreground.image.height as f64);
|
||||
let background_size = DVec2::new(background.image.width as f64, background.image.height as f64);
|
||||
|
||||
// Transforms a point from the background image to the foreground image
|
||||
let bg_to_fg = DAffine2::from_scale(foreground_size) * foreground.transform.inverse() * background.transform * DAffine2::from_scale(1. / background_size);
|
||||
|
||||
@@ -320,7 +334,7 @@ async fn blend_gpu_image(_: (), foreground: ImageFrame<Color>, background: Image
|
||||
let proto_networks: Result<Vec<_>, _> = compiler.compile(network.clone()).collect();
|
||||
let Ok(proto_networks_result) = proto_networks else {
|
||||
log::error!("Error compiling network in 'blend_gpu_image()");
|
||||
return ImageFrame::empty();
|
||||
return ImageFrameTable::default();
|
||||
};
|
||||
let proto_networks = proto_networks_result;
|
||||
log::debug!("compiling shader");
|
||||
@@ -430,7 +444,7 @@ async fn blend_gpu_image(_: (), foreground: ImageFrame<Color>, background: Image
|
||||
let result = executor.read_output_buffer(readback_buffer).await.unwrap();
|
||||
let colors = bytemuck::pod_collect_to_vec::<u8, Color>(result.as_slice());
|
||||
|
||||
ImageFrame {
|
||||
let result = ImageFrame {
|
||||
image: Image {
|
||||
data: colors,
|
||||
width: background.image.width,
|
||||
@@ -439,5 +453,7 @@ async fn blend_gpu_image(_: (), foreground: ImageFrame<Color>, background: Image
|
||||
},
|
||||
transform: background.transform,
|
||||
alpha_blending: background.alpha_blending,
|
||||
}
|
||||
};
|
||||
|
||||
ImageFrameTable::new(result)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user