From 2aaa286db04dceab310de470239c9a0e74ed9d3f Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Sat, 17 Oct 2026 23:28:54 +0200 Subject: [PATCH] Fix viewport zoom perf regression caused by #3848 When zooming in graphite the intermediate render cache is unused even when not using the outline node. This fixes that regression --- node-graph/libraries/rendering/src/renderer.rs | 5 +++-- node-graph/nodes/gstd/src/render_background.rs | 8 ++++---- node-graph/nodes/gstd/src/render_cache.rs | 7 +++++-- node-graph/nodes/gstd/src/render_node.rs | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/node-graph/libraries/rendering/src/renderer.rs b/node-graph/libraries/rendering/src/renderer.rs index 14ad6b4b02b..1ba2a4186fb 100644 --- a/node-graph/libraries/rendering/src/renderer.rs +++ b/node-graph/libraries/rendering/src/renderer.rs @@ -355,7 +355,7 @@ pub struct RenderParams { pub inside_pattern: bool, pub artboard_background: Option, /// Viewport zoom level (document-space scale). Used to compute constant viewport-pixel stroke widths in Outline mode. - pub viewport_zoom: f64, + pub viewport_zoom: Option, /// The nearest ancestor's appearance, cascading to items that lack their own. pub inherited_appearance: Option, } @@ -450,8 +450,9 @@ fn to_point(p: DVec2) -> kurbo::Point { fn get_outline_styles(render_params: &RenderParams) -> (kurbo::Stroke, peniko::Color) { use core_types::consts::LAYER_OUTLINE_STROKE_WEIGHT; + let zoom = render_params.viewport_zoom.unwrap_or(1.); let outline_stroke = kurbo::Stroke { - width: LAYER_OUTLINE_STROKE_WEIGHT / if render_params.viewport_zoom > 0. { render_params.viewport_zoom } else { 1. }, + width: LAYER_OUTLINE_STROKE_WEIGHT / if zoom > 0. { zoom } else { 1. }, miter_limit: 4., join: Join::Miter, start_cap: Cap::Butt, diff --git a/node-graph/nodes/gstd/src/render_background.rs b/node-graph/nodes/gstd/src/render_background.rs index 45abc4429e4..ae60d18974c 100644 --- a/node-graph/nodes/gstd/src/render_background.rs +++ b/node-graph/nodes/gstd/src/render_background.rs @@ -24,7 +24,7 @@ async fn render_background<'a: 'n>( .downcast_ref::() .expect("Downcasting render params yielded invalid type"); - if !render_params.to_canvas() || render_params.viewport_zoom <= 0.0 { + if !render_params.to_canvas() || render_params.viewport_zoom.unwrap_or(1.) <= 0.0 { return data; } @@ -41,7 +41,7 @@ async fn render_background<'a: 'n>( foreground: foreground_texture.as_ref(), backgrounds: &metadata.backgrounds, document_to_screen: doc_to_screen, - zoom: render_params.viewport_zoom.to_f32(), + zoom: render_params.viewport_zoom.unwrap_or(1.).to_f32(), }) .await; @@ -55,10 +55,10 @@ async fn render_background<'a: 'n>( let logical_transform = glam::DAffine2::from_scale(glam::DVec2::splat(1.0 / render_params.scale)) * render_params.footprint.transform; - if render_params.viewport_zoom > 0. { + if render_params.viewport_zoom.unwrap_or_default() > 0. { let draw_checkerboard = |render: &mut SvgRender, rect: vello::kurbo::Rect, pattern_origin: glam::DVec2, checker_id_prefix: &str| { let checker_id = format!("{checker_id_prefix}-{}", generate_uuid()); - let cell_size = 8. / render_params.viewport_zoom; + let cell_size = 8. / render_params.viewport_zoom.unwrap_or(1.); let pattern_size = cell_size * 2.; write!( diff --git a/node-graph/nodes/gstd/src/render_cache.rs b/node-graph/nodes/gstd/src/render_cache.rs index e2a92f0ff2d..a87c5689d2e 100644 --- a/node-graph/nodes/gstd/src/render_cache.rs +++ b/node-graph/nodes/gstd/src/render_cache.rs @@ -12,6 +12,7 @@ use rendering::{RenderOutputType as RenderOutputTypeRequest, RenderParams}; use std::collections::HashSet; use std::hash::Hash; use std::sync::{Arc, Mutex}; +use vector_types::vector::style::RenderMode; use wgpu_executor::WgpuExecutor; pub const TILE_SIZE: u32 = 256; @@ -330,12 +331,14 @@ pub async fn render_output_cache<'a: 'n>( #[data] tile_cache: TileCache, ) -> Item { let footprint = ctx.footprint(); - let Some(render_params) = ctx.vararg(0).ok().and_then(|v| v.downcast_ref::()) else { + let Some(mut render_params) = ctx.vararg(0).ok().and_then(|v| v.downcast_ref::().cloned()) else { log::warn!("render_output_cache: missing or invalid render params, falling back to direct render"); let context = OwnedContextImpl::from(ctx.clone()).with_footprint(*footprint); return data.eval(context.into_context()).await; }; + render_params.viewport_zoom = if let RenderMode::Outline = render_params.render_mode { render_params.viewport_zoom } else { None }; + // Fall back to direct render for non-Vello or zero-size viewports let physical_resolution = footprint.resolution; if !matches!(render_params.render_output_type, RenderOutputTypeRequest::Vello) || physical_resolution.x == 0 || physical_resolution.y == 0 { @@ -376,7 +379,7 @@ pub async fn render_output_cache<'a: 'n>( if missing_region.tiles.is_empty() { continue; } - let region = render_missing_region(missing_region, |ctx| data.eval(ctx), ctx.clone(), render_params, &footprint.transform, &device_origin_offset).await; + let region = render_missing_region(missing_region, |ctx| data.eval(ctx), ctx.clone(), &render_params, &footprint.transform, &device_origin_offset).await; new_regions.push(region); } diff --git a/node-graph/nodes/gstd/src/render_node.rs b/node-graph/nodes/gstd/src/render_node.rs index 58d23542844..094041fb41a 100644 --- a/node-graph/nodes/gstd/src/render_node.rs +++ b/node-graph/nodes/gstd/src/render_node.rs @@ -173,7 +173,7 @@ async fn create_context<'a: 'n>( for_export: render_config.for_export, render_output_type, scale: render_config.scale, - viewport_zoom: logical_viewport.scale_magnitudes().x, + viewport_zoom: Some(logical_viewport.scale_magnitudes().x), ..Default::default() };