Integrate Vello for vector rendering (#1802)

* Start integrating vello into render pipeline

Cache vello render creation

Implement viewport navigation

Close vello path

Add transform parameter to vello render pass

* Fix render node types

* Fix a bunch of bugs in the path translation

* Avoid panic on empty document

* Fix rendering of holes

* Implement image rendering

* Implement graph recompilation afer editor api change

* Implement preferences toggle for using vello as the renderer

* Make surface creation optional

* Feature gate vello usages

* Implement skeleton for radial gradient

* Rename vello preference

* Fix some gradients

* Only update monitor nodes on graph recompile

* Fix warnings + remove dead code

* Update everything except for thumbnails after a node graph evaluation

* Fix missing click targets for Image frames

* Improve perfamance by removing unecessary widget updates

* Fix node graph paning

* Fix thumbnail loading

* Implement proper hash for vector modification

* Fix test and warnings

* Code review

* Fix dep

* Remove warning

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2024-07-22 10:56:29 +02:00
committed by GitHub
parent 8e774efe9d
commit ab71d26d84
41 changed files with 807 additions and 760 deletions

View File

@@ -248,9 +248,6 @@ pub struct DocumentNode {
/// However sometimes this is not desirable, for example in the case of a [`graphene_core::memo::MonitorNode`] that needs to be accessed outside of the graph.
#[serde(default)]
pub skip_deduplication: bool,
/// Used as a hash of the graph input where applicable. This ensures that proto nodes that depend on the graph's input are always regenerated.
#[serde(default)]
pub world_state_hash: u64,
/// The path to this node and its inputs and outputs as of when [`NodeNetwork::generate_node_paths`] was called.
#[serde(skip)]
pub original_location: OriginalLocation,
@@ -293,7 +290,6 @@ impl Default for DocumentNode {
locked: Default::default(),
metadata: DocumentNodeMetadata::default(),
skip_deduplication: Default::default(),
world_state_hash: Default::default(),
original_location: OriginalLocation::default(),
}
}
@@ -392,7 +388,6 @@ impl DocumentNode {
construction_args: args,
original_location: self.original_location,
skip_deduplication: self.skip_deduplication,
world_state_hash: self.world_state_hash,
}
}

View File

@@ -76,10 +76,6 @@ macro_rules! tagged_value {
x if x == TypeId::of::<RenderOutput>() => Ok(TaggedValue::RenderOutput(*downcast(input).unwrap())),
x if x == TypeId::of::<graphene_core::SurfaceFrame>() => Ok(TaggedValue::SurfaceFrame(*downcast(input).unwrap())),
x if x == TypeId::of::<graphene_core::WasmSurfaceHandleFrame>() => {
let frame = *downcast::<graphene_core::WasmSurfaceHandleFrame>(input).unwrap();
Ok(TaggedValue::SurfaceFrame(frame.into()))
}
_ => Err(format!("Cannot convert {:?} to TaggedValue", DynAny::type_name(input.as_ref()))),
}

View File

@@ -286,27 +286,3 @@ impl std::fmt::Display for ImaginateSamplingMethod {
}
}
}
#[derive(Clone, Debug, PartialEq, Hash, specta::Type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ImaginatePreferences {
pub host_name: String,
}
impl graphene_core::application_io::GetImaginatePreferences for ImaginatePreferences {
fn get_host_name(&self) -> &str {
&self.host_name
}
}
impl Default for ImaginatePreferences {
fn default() -> Self {
Self {
host_name: "http://localhost:7860/".into(),
}
}
}
unsafe impl dyn_any::StaticType for ImaginatePreferences {
type Static = ImaginatePreferences;
}

View File

@@ -224,9 +224,6 @@ pub struct ProtoNode {
pub identifier: ProtoNodeIdentifier,
pub original_location: OriginalLocation,
pub skip_deduplication: bool,
// TODO: This is a hack, figure out a proper solution
/// Represents a global state on which the node depends.
pub world_state_hash: u64,
}
impl Default for ProtoNode {
@@ -237,7 +234,6 @@ impl Default for ProtoNode {
input: ProtoNodeInput::None,
original_location: OriginalLocation::default(),
skip_deduplication: false,
world_state_hash: 0,
}
}
}
@@ -288,7 +284,6 @@ impl ProtoNode {
if self.skip_deduplication {
self.original_location.path.hash(&mut hasher);
}
self.world_state_hash.hash(&mut hasher);
std::mem::discriminant(&self.input).hash(&mut hasher);
match self.input {
ProtoNodeInput::None => (),
@@ -317,7 +312,6 @@ impl ProtoNode {
..Default::default()
},
skip_deduplication: false,
world_state_hash: 0,
}
}
@@ -451,7 +445,6 @@ impl ProtoNetwork {
input,
original_location: OriginalLocation { path, ..Default::default() },
skip_deduplication: false,
world_state_hash: 0,
},
));
@@ -947,12 +940,12 @@ mod test {
assert_eq!(
ids,
vec![
NodeId(8751908307531981068),
NodeId(3279077344149194814),
NodeId(532186116905587629),
NodeId(10764326338085309082),
NodeId(18015434340620913446),
NodeId(11801333199647382191)
NodeId(5686040524603683634),
NodeId(13787140740513543798),
NodeId(1280393769237740322),
NodeId(3100442468152897091),
NodeId(14834729712909816752),
NodeId(8678825113056010444)
]
);
}

View File

@@ -220,3 +220,32 @@ impl ApplicationIo for WasmApplicationIo {
pub type WasmSurfaceHandle = SurfaceHandle<wgpu_executor::Window>;
pub type WasmSurfaceHandleFrame = SurfaceHandleFrame<wgpu_executor::Window>;
#[derive(Clone, Debug, PartialEq, Hash, specta::Type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EditorPreferences {
pub imaginate_hostname: String,
pub use_vello: bool,
}
impl graphene_core::application_io::GetEditorPreferences for EditorPreferences {
fn hostname(&self) -> &str {
&self.imaginate_hostname
}
fn use_vello(&self) -> bool {
self.use_vello
}
}
impl Default for EditorPreferences {
fn default() -> Self {
Self {
imaginate_hostname: "http://localhost:7860/".into(),
use_vello: false,
}
}
}
unsafe impl dyn_any::StaticType for EditorPreferences {
type Static = EditorPreferences;
}