Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ use crate::messages::prelude::*;
pub enum PreferencesDialogMessage {
MayRequireRestart,
Confirm,
Update,
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ impl MessageHandler<PreferencesDialogMessage, PreferencesDialogMessageContext<'_
responses.add(DialogMessage::Close);
}
}
PreferencesDialogMessage::Update => {}
}
}

Expand Down Expand Up @@ -244,31 +245,6 @@ impl PreferencesDialogMessageHandler {
graph_wire_style,
];

let checkbox_id = CheckboxId::new();
let vello_description = "Use the experimental Vello renderer instead of SVG-based rendering.".to_string();
#[cfg(target_family = "wasm")]
let mut vello_description = vello_description;
#[cfg(target_family = "wasm")]
vello_description.push_str("\n\n(Your browser must support WebGPU.)");

let use_vello = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
CheckboxInput::new(preferences.use_vello && preferences.supports_wgpu())
.tooltip_label("Vello Renderer")
.tooltip_description(vello_description.clone())
.disabled(!preferences.supports_wgpu())
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::UseVello { use_vello: checkbox_input.checked }.into())
.for_label(checkbox_id)
.widget_instance(),
TextLabel::new("Vello Renderer")
.tooltip_label("Vello Renderer")
.tooltip_description(vello_description)
.disabled(!preferences.supports_wgpu())
.for_checkbox(checkbox_id)
.widget_instance(),
];

let checkbox_id = CheckboxId::new();
let brush_tool_description = "
Enable the Brush tool to support basic raster-based layer painting.\n\
Expand All @@ -294,7 +270,78 @@ impl PreferencesDialogMessageHandler {
.widget_instance(),
];

rows.extend_from_slice(&[header, node_graph_wires_label, graph_wire_style, use_vello, brush_tool]);
let vello_description = "Auto uses Vello renderer when GPU is available.";
let vello_renderer_label = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
TextLabel::new("Vello Renderer")
.tooltip_label("Vello Renderer")
.tooltip_description(vello_description)
.widget_instance(),
];
let vello_preference = RadioInput::new(vec![
RadioEntryData::new("Auto").label("Auto").on_update(move |_| {
PreferencesMessage::VelloPreference {
preference: graph_craft::wasm_application_io::VelloPreference::Auto,
}
.into()
}),
RadioEntryData::new("Disabled").label("Disabled").on_update(move |_| {
PreferencesMessage::VelloPreference {
preference: graph_craft::wasm_application_io::VelloPreference::Disabled,
}
.into()
}),
])
.selected_index(Some(preferences.vello_preference as u32))
.widget_instance();
let vello_preference = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
vello_preference,
];

let max_region_size_description =
"Maximum render region size in total pixels (width × height). Larger values require fewer render passes. If you see rendering artifacts or nothing at all, configure a smaller value.";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we split this explanation in two parts, first explaining for non technical users and a second part going deeper and explaining the exact effect?

let max_region_size_label = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
TextLabel::new("Max Render Region Size")
.tooltip_label("Max Render Region Size")
.tooltip_description(max_region_size_description)
.disabled(!preferences.use_vello())
.widget_instance(),
];
let max_region_size = vec![
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
NumberInput::new(Some(preferences.max_render_region_size as f64))
.tooltip_label("Max Render Region Size")
.tooltip_description(max_region_size_description)
.mode_range()
.int()
.min(65536.)
.max(16777216.)
.increment_step(262144.)
.unit(" pixels")
.disabled(!preferences.use_vello())
.on_update(|number_input: &NumberInput| {
let size = number_input.value.unwrap_or(2073600.) as u32;
PreferencesMessage::MaxRenderRegionSize { size }.into()
})
.widget_instance(),
];

rows.extend_from_slice(&[
header,
node_graph_wires_label,
graph_wire_style,
brush_tool,
vello_renderer_label,
vello_preference,
max_region_size_label,
max_region_size,
]);
}

// =============
Expand Down
5 changes: 3 additions & 2 deletions editor/src/messages/portfolio/portfolio_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1365,10 +1365,11 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
}
}
PortfolioMessage::UpdateVelloPreference => {
let active = if cfg!(target_family = "wasm") { false } else { preferences.use_vello };
// TODO: Resend this message once the GPU context is initialized to avoid having the hole punch be stuck in an invalid state
let active = if cfg!(target_family = "wasm") { false } else { preferences.use_vello() };
responses.add(FrontendMessage::UpdateViewportHolePunch { active });
responses.add(NodeGraphMessage::RunDocumentGraph);
self.persistent_data.use_vello = preferences.use_vello;
self.persistent_data.use_vello = preferences.use_vello();
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion editor/src/messages/preferences/preferences_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ pub enum PreferencesMessage {
ResetToDefaults,

// Per-preference messages
UseVello { use_vello: bool },
VelloPreference { preference: graph_craft::wasm_application_io::VelloPreference },
SelectionMode { selection_mode: SelectionMode },
BrushTool { enabled: bool },
ModifyLayout { zoom_with_scroll: bool },
GraphWireStyle { style: GraphWireStyle },
ViewportZoomWheelRate { rate: f64 },
UIScale { scale: f64 },
DisableUIAcceleration { disable_ui_acceleration: bool },
MaxRenderRegionSize { size: u32 },
}
24 changes: 19 additions & 5 deletions editor/src/messages/preferences/preferences_message_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::messages::preferences::SelectionMode;
use crate::messages::prelude::*;
use crate::messages::tool::utility_types::ToolType;
use graph_craft::wasm_application_io::EditorPreferences;
use graphene_std::application_io::GetEditorPreferences;

#[derive(ExtractField)]
pub struct PreferencesMessageContext<'a> {
Expand All @@ -16,12 +17,13 @@ pub struct PreferencesMessageContext<'a> {
pub struct PreferencesMessageHandler {
pub selection_mode: SelectionMode,
pub zoom_with_scroll: bool,
pub use_vello: bool,
pub vello_preference: graph_craft::wasm_application_io::VelloPreference,
pub brush_tool: bool,
pub graph_wire_style: GraphWireStyle,
pub viewport_zoom_wheel_rate: f64,
pub ui_scale: f64,
pub disable_ui_acceleration: bool,
pub max_render_region_size: u32,
}

impl PreferencesMessageHandler {
Expand All @@ -35,26 +37,32 @@ impl PreferencesMessageHandler {

pub fn editor_preferences(&self) -> EditorPreferences {
EditorPreferences {
use_vello: self.use_vello && self.supports_wgpu(),
vello_preference: self.vello_preference,
max_render_region_size: self.max_render_region_size,
}
}

pub fn supports_wgpu(&self) -> bool {
graph_craft::wasm_application_io::wgpu_available().unwrap_or_default()
}

pub fn use_vello(&self) -> bool {
self.editor_preferences().use_vello()
}
}

impl Default for PreferencesMessageHandler {
fn default() -> Self {
Self {
selection_mode: SelectionMode::Touched,
zoom_with_scroll: matches!(MappingVariant::default(), MappingVariant::ZoomWithScroll),
use_vello: EditorPreferences::default().use_vello,
vello_preference: EditorPreferences::default().vello_preference,
brush_tool: false,
graph_wire_style: GraphWireStyle::default(),
viewport_zoom_wheel_rate: VIEWPORT_ZOOM_WHEEL_RATE,
ui_scale: UI_SCALE_DEFAULT,
disable_ui_acceleration: false,
max_render_region_size: 1920 * 1080,
}
}
}
Expand Down Expand Up @@ -82,10 +90,11 @@ impl MessageHandler<PreferencesMessage, PreferencesMessageContext<'_>> for Prefe
}

// Per-preference messages
PreferencesMessage::UseVello { use_vello } => {
self.use_vello = use_vello;
PreferencesMessage::VelloPreference { preference } => {
self.vello_preference = preference;
responses.add(PortfolioMessage::UpdateVelloPreference);
responses.add(PortfolioMessage::EditorPreferences);
responses.add(PreferencesDialogMessage::Update);
}
PreferencesMessage::BrushTool { enabled } => {
self.brush_tool = enabled;
Expand Down Expand Up @@ -120,6 +129,11 @@ impl MessageHandler<PreferencesMessage, PreferencesMessageContext<'_>> for Prefe
PreferencesMessage::DisableUIAcceleration { disable_ui_acceleration } => {
self.disable_ui_acceleration = disable_ui_acceleration;
}
PreferencesMessage::MaxRenderRegionSize { size } => {
self.max_render_region_size = size;
responses.add(PortfolioMessage::UpdateVelloPreference);
responses.add(PortfolioMessage::EditorPreferences);
}
}

responses.add(FrontendMessage::TriggerSavePreferences { preferences: self.clone() });
Expand Down
1 change: 1 addition & 0 deletions editor/src/node_graph_executor/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ impl NodeRuntime {

executor.context.queue.submit([encoder.finish()]);
surface_texture.present();
// image_texture.texture.destroy();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// image_texture.texture.destroy();


let frame = graphene_std::application_io::SurfaceFrame {
surface_id: surface.window_id,
Expand Down
22 changes: 11 additions & 11 deletions frontend/wasm/src/editor_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,20 +202,20 @@ impl EditorHandle {
if !EDITOR_HAS_CRASHED.load(Ordering::SeqCst) {
handle(|handle| {
// Process all messages that have been queued up
let messages = MESSAGE_BUFFER.take();

for message in messages {
handle.dispatch(message);
}

handle.dispatch(InputPreprocessorMessage::CurrentTime {
timestamp: js_sys::Date::now() as u64,
});
handle.dispatch(AnimationMessage::IncrementFrameCounter);
let mut messages = MESSAGE_BUFFER.take();
messages.push(
InputPreprocessorMessage::CurrentTime {
timestamp: js_sys::Date::now() as u64,
}
.into(),
);
messages.push(AnimationMessage::IncrementFrameCounter.into());

// Used by auto-panning, but this could possibly be refactored in the future, see:
// <https://github.com/GraphiteEditor/Graphite/pull/2562#discussion_r2041102786>
handle.dispatch(BroadcastMessage::TriggerEvent(EventMessage::AnimationFrame));
messages.push(BroadcastMessage::TriggerEvent(EventMessage::AnimationFrame).into());

handle.dispatch(Message::Batched { messages: messages.into() });
});
}

Expand Down
25 changes: 19 additions & 6 deletions node-graph/graph-craft/src/wasm_application_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,24 +332,37 @@ pub type WasmSurfaceHandle = SurfaceHandle<wgpu_executor::Window>;
#[cfg(feature = "wgpu")]
pub type WasmSurfaceHandleFrame = graphene_application_io::SurfaceHandleFrame<wgpu_executor::Window>;

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, specta::Type, serde::Serialize, serde::Deserialize)]
pub enum VelloPreference {
Auto,
Disabled,
}

#[derive(Clone, Debug, PartialEq, Hash, specta::Type, serde::Serialize, serde::Deserialize)]
pub struct EditorPreferences {
pub use_vello: bool,
pub vello_preference: VelloPreference,
/// Maximum render region size in pixels (area = width * height). Default: 2,073,600 (1080p area)
pub max_render_region_size: u32,
}

impl graphene_application_io::GetEditorPreferences for EditorPreferences {
fn use_vello(&self) -> bool {
self.use_vello
match self.vello_preference {
VelloPreference::Auto => wgpu_available().unwrap_or(false),
VelloPreference::Disabled => false,
}
}

fn max_render_region_size(&self) -> u32 {
self.max_render_region_size
}
}

impl Default for EditorPreferences {
fn default() -> Self {
Self {
#[cfg(target_family = "wasm")]
use_vello: false,
#[cfg(not(target_family = "wasm"))]
use_vello: true,
vello_preference: VelloPreference::Auto,
max_render_region_size: 1920 * 1080,
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion node-graph/graphene-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
let wgpu_executor_ref = application_io_arc.gpu_executor().unwrap();
let device = wgpu_executor_ref.context.device.clone();

let preferences = EditorPreferences { use_vello: true };
let preferences = EditorPreferences {
vello_preference: graph_craft::wasm_application_io::VelloPreference::Auto,
max_render_region_size: 1920 * 1080,
};
let editor_api = Arc::new(WasmEditorApi {
font_cache: FontCache::default(),
application_io: Some(application_io_for_api),
Expand Down
1 change: 1 addition & 0 deletions node-graph/interpreted-executor/src/node_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
#[cfg(feature = "gpu")]
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => Arc<WasmSurfaceHandle>, Context => graphene_std::ContextFeatures]),
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => RenderIntermediate, Context => graphene_std::ContextFeatures]),
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => RenderOutput, Context => graphene_std::ContextFeatures]),
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => WgpuSurface, Context => graphene_std::ContextFeatures]),
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => Option<WgpuSurface>, Context => graphene_std::ContextFeatures]),
async_node!(graphene_core::context_modification::ContextModificationNode<_, _>, input: Context, fn_params: [Context => WindowHandle, Context => graphene_std::ContextFeatures]),
Expand Down
19 changes: 15 additions & 4 deletions node-graph/interpreted-executor/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<WasmEdito
let render_node = DocumentNode {
inputs: vec![NodeInput::node(NodeId(0), 0)],
implementation: DocumentNodeImplementation::Network(NodeNetwork {
exports: vec![NodeInput::node(NodeId(2), 0)],
exports: vec![NodeInput::node(NodeId(3), 0)],
nodes: [
DocumentNode {
call_argument: concrete!(Context),
inputs: vec![NodeInput::import(core_types::Type::Fn(Box::new(concrete!(Context)), Box::new(generic!(T))), 0)],
implementation: DocumentNodeImplementation::ProtoNode(graphene_std::render_node::render_intermediate::IDENTIFIER),
context_features: graphene_std::ContextDependencies {
extract: ContextFeatures::VARARGS,
inject: ContextFeatures::empty(),
inject: ContextFeatures::INDEX,
},
..Default::default()
},
Expand All @@ -51,12 +51,23 @@ pub fn wrap_network_in_scope(mut network: NodeNetwork, editor_api: Arc<WasmEdito
},
..Default::default()
},
DocumentNode {
call_argument: concrete!(Context),
inputs: vec![NodeInput::scope("editor-api"), NodeInput::node(NodeId(1), 0)],
implementation: DocumentNodeImplementation::ProtoNode(graphene_std::render_cache::render_output_cache::IDENTIFIER),
context_features: graphene_std::ContextDependencies {
extract: ContextFeatures::FOOTPRINT | ContextFeatures::VARARGS,
inject: ContextFeatures::VARARGS,
},
..Default::default()
},
DocumentNode {
call_argument: concrete!(graphene_std::application_io::RenderConfig),
inputs: vec![NodeInput::node(NodeId(1), 0)],
inputs: vec![NodeInput::node(NodeId(2), 0)],
implementation: DocumentNodeImplementation::ProtoNode(graphene_std::render_node::create_context::IDENTIFIER),
context_features: graphene_std::ContextDependencies {
extract: ContextFeatures::empty(),
// We add the extract index annotation here to force the compiler to add a context nullification node before this node so the render context is properly nullified so the render cache node can do its's work
extract: ContextFeatures::INDEX,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we add a separate ContextFeature for this purpose?

inject: ContextFeatures::REAL_TIME | ContextFeatures::ANIMATION_TIME | ContextFeatures::POINTER_POSITION | ContextFeatures::FOOTPRINT | ContextFeatures::VARARGS,
},
..Default::default()
Expand Down
Loading