Skip to content

Commit 0531769

Browse files
TrueDoctorKeavon
andauthored
Cache Vello render output as stitchable textures (#3722)
* WIP render caching * Hook up render cache to render pipeline * Fixed offsets * Initial cleanup * Integrate cache with context invalidation * Cleanup * Improve rounding and reduce tile size to fix vello not rendering * Include pointer position in cache key * Avoid unwraps and zero sized textures * Destroy textures after blitting to surface * Fix context dependencies * Exclude footprint from render params * Batch animation frame messages * Add vello max render size to preference dialogue * Remove unused import * Reorder vello preference * Clean up preferences dialog * Apply review suggestions * Cap max render region size --------- Co-authored-by: Keavon Chambers <keavon@keavon.com>
1 parent 5aca75d commit 0531769

File tree

19 files changed

+840
-105
lines changed

19 files changed

+840
-105
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editor/src/messages/dialog/preferences_dialog/preferences_dialog_message.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ use crate::messages::prelude::*;
55
pub enum PreferencesDialogMessage {
66
MayRequireRestart,
77
Confirm,
8+
Update,
89
}

editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs

Lines changed: 153 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::messages::layout::utility_types::widget_prelude::*;
33
use crate::messages::portfolio::document::utility_types::wires::GraphWireStyle;
44
use crate::messages::preferences::SelectionMode;
55
use crate::messages::prelude::*;
6+
use graphene_std::render_node::{EditorPreferences, wgpu_available};
67

78
#[derive(ExtractField)]
89
pub struct PreferencesDialogMessageContext<'a> {
@@ -34,6 +35,7 @@ impl MessageHandler<PreferencesDialogMessage, PreferencesDialogMessageContext<'_
3435
responses.add(DialogMessage::Close);
3536
}
3637
}
38+
PreferencesDialogMessage::Update => {}
3739
}
3840
}
3941

@@ -57,7 +59,12 @@ impl PreferencesDialogMessageHandler {
5759
{
5860
let header = vec![TextLabel::new("Navigation").italic(true).widget_instance()];
5961

60-
let zoom_rate_description = "Adjust how fast zooming occurs when using the scroll wheel or pinch gesture (relative to a default of 50).";
62+
let zoom_rate_description = "
63+
Adjust how fast zooming occurs when using the scroll wheel or pinch gesture.\n\
64+
\n\
65+
*Default: 50.*
66+
"
67+
.trim();
6168
let zoom_rate_label = vec![
6269
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
6370
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
@@ -85,7 +92,12 @@ impl PreferencesDialogMessageHandler {
8592
];
8693

8794
let checkbox_id = CheckboxId::new();
88-
let zoom_with_scroll_description = "Use the scroll wheel for zooming instead of vertically panning (not recommended for trackpads).";
95+
let zoom_with_scroll_description = "
96+
Use the scroll wheel for zooming instead of vertically panning (not recommended for trackpads).\n\
97+
\n\
98+
*Default: Off.*
99+
"
100+
.trim();
89101
let zoom_with_scroll = vec![
90102
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
91103
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
@@ -116,12 +128,18 @@ impl PreferencesDialogMessageHandler {
116128
{
117129
let header = vec![TextLabel::new("Editing").italic(true).widget_instance()];
118130

131+
let selection_label_description = "
132+
Choose how targets are selected within dragged rectangular and lasso areas.\n\
133+
\n\
134+
*Default: Touched.*
135+
"
136+
.trim();
119137
let selection_label = vec![
120138
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
121139
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
122140
TextLabel::new("Selection")
123141
.tooltip_label("Selection")
124-
.tooltip_description("Choose how targets are selected within dragged rectangular and lasso areas.")
142+
.tooltip_description(selection_label_description)
125143
.widget_instance(),
126144
];
127145

@@ -175,7 +193,12 @@ impl PreferencesDialogMessageHandler {
175193
{
176194
let header = vec![TextLabel::new("Interface").italic(true).widget_instance()];
177195

178-
let scale_description = "Adjust the scale of the entire user interface (100% is default).";
196+
let scale_description = "
197+
Adjust the scale of the entire user interface.\n\
198+
\n\
199+
*Default: 100%.*
200+
"
201+
.trim();
179202
let scale_label = vec![
180203
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
181204
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
@@ -215,7 +238,12 @@ impl PreferencesDialogMessageHandler {
215238
{
216239
let header = vec![TextLabel::new("Experimental").italic(true).widget_instance()];
217240

218-
let node_graph_section_description = "Configure the appearance of the wires running between node connections in the graph.";
241+
let node_graph_section_description = "
242+
Configure the appearance of the wires running between node connections in the graph.\n\
243+
\n\
244+
*Default: Direct.*
245+
"
246+
.trim();
219247
let node_graph_wires_label = vec![
220248
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
221249
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
@@ -244,39 +272,16 @@ impl PreferencesDialogMessageHandler {
244272
graph_wire_style,
245273
];
246274

247-
let checkbox_id = CheckboxId::new();
248-
let vello_description = "Use the experimental Vello renderer instead of SVG-based rendering.".to_string();
249-
#[cfg(target_family = "wasm")]
250-
let mut vello_description = vello_description;
251-
#[cfg(target_family = "wasm")]
252-
vello_description.push_str("\n\n(Your browser must support WebGPU.)");
253-
254-
let use_vello = vec![
255-
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
256-
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
257-
CheckboxInput::new(preferences.use_vello && preferences.supports_wgpu())
258-
.tooltip_label("Vello Renderer")
259-
.tooltip_description(vello_description.clone())
260-
.disabled(!preferences.supports_wgpu())
261-
.on_update(|checkbox_input: &CheckboxInput| PreferencesMessage::UseVello { use_vello: checkbox_input.checked }.into())
262-
.for_label(checkbox_id)
263-
.widget_instance(),
264-
TextLabel::new("Vello Renderer")
265-
.tooltip_label("Vello Renderer")
266-
.tooltip_description(vello_description)
267-
.disabled(!preferences.supports_wgpu())
268-
.for_checkbox(checkbox_id)
269-
.widget_instance(),
270-
];
271-
272275
let checkbox_id = CheckboxId::new();
273276
let brush_tool_description = "
274-
Enable the Brush tool to support basic raster-based layer painting.\n\
275-
\n\
276-
This legacy experimental tool has performance and quality limitations and is slated for replacement in future versions of Graphite that will have a renewed focus on raster graphics editing.\n\
277-
\n\
278-
Content created with the Brush tool may not be compatible with future versions of Graphite.
279-
"
277+
Enable the Brush tool to support basic raster-based layer painting.\n\
278+
\n\
279+
This legacy experimental tool has performance and quality limitations and is slated for replacement in future versions of Graphite that will have a renewed focus on raster graphics editing.\n\
280+
\n\
281+
Content created with the Brush tool may not be compatible with future versions of Graphite.\n\
282+
\n\
283+
*Default: Off.*
284+
"
280285
.trim();
281286
let brush_tool = vec![
282287
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
@@ -294,49 +299,126 @@ impl PreferencesDialogMessageHandler {
294299
.widget_instance(),
295300
];
296301

297-
rows.extend_from_slice(&[header, node_graph_wires_label, graph_wire_style, use_vello, brush_tool]);
302+
rows.extend_from_slice(&[header, node_graph_wires_label, graph_wire_style, brush_tool]);
298303
}
299304

300305
// =============
301306
// COMPATIBILITY
302307
// =============
303-
#[cfg(not(target_family = "wasm"))]
304308
{
305-
let header = vec![TextLabel::new("Compatibility").italic(true).widget_instance()];
306-
307-
let ui_acceleration_description = "
308-
Use the CPU to draw the Graphite user interface (areas outside of the canvas) instead of the GPU. This does not affect the rendering of artwork in the canvas, which remains hardware accelerated.\n\
309-
\n\
310-
Disabling UI acceleration may slightly degrade performance, so this should be used as a workaround only if issues are observed with displaying the UI. This setting may become enabled automatically if Graphite launches, detects that it cannot draw the UI normally, and restarts in compatibility mode.
311-
"
312-
.trim();
309+
let wgpu_available = wgpu_available().unwrap_or(false);
310+
let is_desktop = cfg!(not(target_family = "wasm"));
311+
if wgpu_available || is_desktop {
312+
let header = vec![TextLabel::new("Compatibility").italic(true).widget_instance()];
313+
rows.push(header);
314+
}
313315

314-
let checkbox_id = CheckboxId::new();
315-
let ui_acceleration = vec![
316-
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
317-
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
318-
CheckboxInput::new(preferences.disable_ui_acceleration)
319-
.tooltip_label("Disable UI Acceleration")
320-
.tooltip_description(ui_acceleration_description)
321-
.on_update(|number_input: &CheckboxInput| Message::Batched {
322-
messages: Box::new([
323-
PreferencesDialogMessage::MayRequireRestart.into(),
324-
PreferencesMessage::DisableUIAcceleration {
325-
disable_ui_acceleration: number_input.checked,
326-
}
327-
.into(),
328-
]),
329-
})
330-
.for_label(checkbox_id)
331-
.widget_instance(),
332-
TextLabel::new("Disable UI Acceleration")
333-
.tooltip_label("Disable UI Acceleration")
334-
.tooltip_description(ui_acceleration_description)
335-
.for_checkbox(checkbox_id)
336-
.widget_instance(),
337-
];
316+
if wgpu_available {
317+
let vello_description = "Auto uses Vello renderer when GPU is available.";
318+
let vello_renderer_label = vec![
319+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
320+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
321+
TextLabel::new("Vello Renderer")
322+
.tooltip_label("Vello Renderer")
323+
.tooltip_description(vello_description)
324+
.widget_instance(),
325+
];
326+
let vello_preference = RadioInput::new(vec![
327+
RadioEntryData::new("Auto").label("Auto").on_update(move |_| {
328+
PreferencesMessage::VelloPreference {
329+
preference: graph_craft::wasm_application_io::VelloPreference::Auto,
330+
}
331+
.into()
332+
}),
333+
RadioEntryData::new("Disabled").label("Disabled").on_update(move |_| {
334+
PreferencesMessage::VelloPreference {
335+
preference: graph_craft::wasm_application_io::VelloPreference::Disabled,
336+
}
337+
.into()
338+
}),
339+
])
340+
.selected_index(Some(preferences.vello_preference as u32))
341+
.widget_instance();
342+
let vello_preference = vec![
343+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
344+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
345+
vello_preference,
346+
];
347+
rows.extend_from_slice(&[vello_renderer_label, vello_preference]);
348+
349+
let render_tile_resolution_description = "
350+
Maximum X or Y resolution per render tile. Larger tiles may improve performance but can cause flickering or missing content in complex artwork if set too high.\n\
351+
\n\
352+
*Default: 1280 px.*
353+
"
354+
.trim();
355+
let render_tile_resolution_label = vec![
356+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
357+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
358+
TextLabel::new("Render Tile Resolution")
359+
.tooltip_label("Render Tile Resolution")
360+
.tooltip_description(render_tile_resolution_description)
361+
.widget_instance(),
362+
];
363+
let render_tile_resolution = vec![
364+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
365+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
366+
NumberInput::new(Some(preferences.max_render_region_size as f64))
367+
.tooltip_label("Render Tile Resolution")
368+
.tooltip_description(render_tile_resolution_description)
369+
.mode_range()
370+
.int()
371+
.min(256.)
372+
.max(4096.)
373+
.increment_step(256.)
374+
.unit(" px")
375+
.on_update(|number_input: &NumberInput| {
376+
let size = number_input.value.unwrap_or(EditorPreferences::default().max_render_region_size as f64) as u32;
377+
PreferencesMessage::MaxRenderRegionSize { size }.into()
378+
})
379+
.widget_instance(),
380+
];
381+
382+
rows.extend_from_slice(&[render_tile_resolution_label, render_tile_resolution]);
383+
}
338384

339-
rows.extend_from_slice(&[header, ui_acceleration]);
385+
if is_desktop {
386+
let ui_acceleration_description = "
387+
Use the CPU to draw the Graphite user interface (areas outside of the canvas) instead of the GPU. This does not affect the rendering of artwork in the canvas, which remains hardware accelerated.\n\
388+
\n\
389+
Disabling UI acceleration may slightly degrade performance, so this should be used as a workaround only if issues are observed with displaying the UI. This setting may become enabled automatically if Graphite launches, detects that it cannot draw the UI normally, and restarts in compatibility mode.\n\
390+
\n\
391+
*Default: Off.*
392+
"
393+
.trim();
394+
395+
let checkbox_id = CheckboxId::new();
396+
let ui_acceleration = vec![
397+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
398+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
399+
CheckboxInput::new(preferences.disable_ui_acceleration)
400+
.tooltip_label("Disable UI Acceleration")
401+
.tooltip_description(ui_acceleration_description)
402+
.on_update(|number_input: &CheckboxInput| Message::Batched {
403+
messages: Box::new([
404+
PreferencesDialogMessage::MayRequireRestart.into(),
405+
PreferencesMessage::DisableUIAcceleration {
406+
disable_ui_acceleration: number_input.checked,
407+
}
408+
.into(),
409+
]),
410+
})
411+
.for_label(checkbox_id)
412+
.widget_instance(),
413+
TextLabel::new("Disable UI Acceleration")
414+
.tooltip_label("Disable UI Acceleration")
415+
.tooltip_description(ui_acceleration_description)
416+
.for_checkbox(checkbox_id)
417+
.widget_instance(),
418+
];
419+
420+
rows.push(ui_acceleration);
421+
}
340422
}
341423

342424
Layout(rows.into_iter().map(|r| LayoutGroup::Row { widgets: r }).collect())

editor/src/messages/portfolio/document/document_message_handler.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ pub struct DocumentMessageHandler {
9292
pub document_ptz: PTZ,
9393
/// The current mode that the user has set for rendering the document within the viewport.
9494
/// This is usually "Normal" but can be set to "Outline" or "Pixels" to see the canvas differently.
95-
#[serde(alias = "view_mode")]
9695
pub render_mode: RenderMode,
9796
/// Sets whether or not all the viewport overlays should be drawn on top of the artwork.
9897
/// This includes tool interaction visualizations (like the transform cage and path anchors/handles), the grid, and more.

editor/src/messages/portfolio/portfolio_message_handler.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,10 +1365,11 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
13651365
}
13661366
}
13671367
PortfolioMessage::UpdateVelloPreference => {
1368-
let active = if cfg!(target_family = "wasm") { false } else { preferences.use_vello };
1368+
// TODO: Resend this message once the GPU context is initialized to avoid having the hole punch be stuck in an invalid state
1369+
let active = if cfg!(target_family = "wasm") { false } else { preferences.use_vello() };
13691370
responses.add(FrontendMessage::UpdateViewportHolePunch { active });
13701371
responses.add(NodeGraphMessage::RunDocumentGraph);
1371-
self.persistent_data.use_vello = preferences.use_vello;
1372+
self.persistent_data.use_vello = preferences.use_vello();
13721373
}
13731374
}
13741375
}

editor/src/messages/preferences/preferences_message.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ pub enum PreferencesMessage {
1010
ResetToDefaults,
1111

1212
// Per-preference messages
13-
UseVello { use_vello: bool },
13+
VelloPreference { preference: graph_craft::wasm_application_io::VelloPreference },
1414
SelectionMode { selection_mode: SelectionMode },
1515
BrushTool { enabled: bool },
1616
ModifyLayout { zoom_with_scroll: bool },
1717
GraphWireStyle { style: GraphWireStyle },
1818
ViewportZoomWheelRate { rate: f64 },
1919
UIScale { scale: f64 },
2020
DisableUIAcceleration { disable_ui_acceleration: bool },
21+
MaxRenderRegionSize { size: u32 },
2122
}

0 commit comments

Comments
 (0)