commit 44663f537543b39324cf06f9ecd6dfb591440b27
parent 7c1d966586aab3632fc595fdd42404c44d3ed9b7
Author: Nicolas Silva <nical@fastmail.com>
Date: Thu, 8 Jan 2026 09:27:00 +0000
Bug 2006848 - Add an internal unique identifier to spatial nodes and make it part of the quad cache key. r=gw
The internal spatial node is a simple u64 (unlike SpatialNodeUid which is used on the other side of the interner). This avoids bloating the spatial node struct and unnecessary hashing.
Differential Revision: https://phabricator.services.mozilla.com/D276986
Diffstat:
5 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/gfx/wr/webrender/src/prepare.rs b/gfx/wr/webrender/src/prepare.rs
@@ -729,10 +729,10 @@ fn prepare_interned_prim_for_render(
},
);
}
- PrimitiveInstanceKind::LinearGradient { data_handle, ref mut visible_tiles_range, use_legacy_path: cached, .. } => {
+ PrimitiveInstanceKind::LinearGradient { data_handle, ref mut visible_tiles_range, use_legacy_path, .. } => {
profile_scope!("LinearGradient");
let prim_data = &mut data_stores.linear_grad[*data_handle];
- if !*cached {
+ if !*use_legacy_path {
quad::prepare_repeatable_quad(
prim_data,
&prim_data.common.prim_rect,
@@ -925,6 +925,7 @@ fn prepare_interned_prim_for_render(
quad::cache_key(
data_handle.uid(),
prim_spatial_node_index,
+ frame_context.spatial_tree,
&prim_instance.vis.clip_chain,
frame_state.clip_store,
&data_stores.clip,
diff --git a/gfx/wr/webrender/src/quad.rs b/gfx/wr/webrender/src/quad.rs
@@ -42,6 +42,7 @@ const MAX_TILES_PER_QUAD: usize = 4;
pub struct QuadCacheKey {
pub prim: u64,
pub clips: [u64; 3],
+ pub spatial_node: u64,
}
/// Describes how clipping affects the rendering of a quad primitive.
@@ -1020,6 +1021,7 @@ fn get_prim_render_strategy(
pub fn cache_key(
prim_uid: ItemUid,
prim_spatial_node_index: SpatialNodeIndex,
+ spatial_tree: &SpatialTree,
clip_chain: &ClipChainInstance,
clip_store: &ClipStore,
interned_clips: &DataStore<ClipIntern>,
@@ -1041,9 +1043,14 @@ pub fn cache_key(
}
}
+ let spatial_uid = spatial_tree
+ .get_spatial_node(prim_spatial_node_index)
+ .uid;
+
Some(QuadCacheKey {
prim: prim_uid.get_uid(),
- clips: clip_uids
+ clips: clip_uids,
+ spatial_node: spatial_uid,
})
}
diff --git a/gfx/wr/webrender/src/scene_building.rs b/gfx/wr/webrender/src/scene_building.rs
@@ -1651,7 +1651,6 @@ impl<'a> SceneBuilder<'a> {
let mut start = info.gradient.start_point;
let mut end = info.gradient.end_point;
let flags = layout.flags;
-
let optimized = optimize_linear_gradient(
&mut layout.rect,
&mut tile_size,
diff --git a/gfx/wr/webrender/src/spatial_node.rs b/gfx/wr/webrender/src/spatial_node.rs
@@ -301,6 +301,10 @@ pub struct SpatialNode {
/// This is calculated in update(). This will be used to decide whether
/// to override corresponding picture's raster space as an optimisation.
pub is_ancestor_or_self_zooming: bool,
+
+ /// An internal unique identifier for use during frame building (as opposed
+ /// to SpatialNodeUid which is used before interning).
+ pub uid: u64,
}
/// Snap an offset to be incorporated into a transform, where the local space
@@ -1051,4 +1055,3 @@ fn test_cst_perspective_relative_scroll() {
let ref_transform = transform.then_translate(LayoutVector3D::new(0.0, -50.0, 0.0));
assert!(world_transform.approx_eq(&ref_transform));
}
-
diff --git a/gfx/wr/webrender/src/spatial_tree.rs b/gfx/wr/webrender/src/spatial_tree.rs
@@ -10,7 +10,7 @@ use crate::gpu_types::TransformPalette;
use crate::internal_types::{FastHashMap, FastHashSet, FrameMemory, PipelineInstanceId};
use crate::print_tree::{PrintableTree, PrintTree, PrintTreePrinter};
use crate::scene::SceneProperties;
-use crate::spatial_node::{ReferenceFrameInfo, SpatialNode, SpatialNodeType, StickyFrameInfo, SpatialNodeDescriptor};
+use crate::spatial_node::{ReferenceFrameInfo, SpatialNode, SpatialNodeDescriptor, SpatialNodeType, StickyFrameInfo};
use crate::spatial_node::{SpatialNodeUid, ScrollFrameKind, SceneSpatialNode, SpatialNodeInfo, SpatialNodeUidKind};
use std::{ops, u32};
use crate::util::{FastTransform, LayoutToWorldFastTransform, MatrixHelpers, ScaleOffset, scale_factors};
@@ -667,6 +667,8 @@ pub struct SpatialTree {
/// Stack of current state for each parent node while traversing and updating tree
update_state_stack: Vec<TransformUpdateState>,
+
+ next_internal_uid: u64,
}
#[derive(Clone)]
@@ -813,6 +815,7 @@ impl SpatialTree {
coord_systems: Vec::new(),
root_reference_frame_index: SpatialNodeIndex::INVALID,
update_state_stack: Vec::new(),
+ next_internal_uid: 1,
}
}
@@ -878,6 +881,9 @@ impl SpatialTree {
self.get_spatial_node_mut(parent).add_child(SpatialNodeIndex(index as u32));
}
+ let uid = self.next_internal_uid;
+ self.next_internal_uid += 1;
+
let node = SpatialNode {
viewport_transform: ScaleOffset::identity(),
content_transform: ScaleOffset::identity(),
@@ -891,6 +897,7 @@ impl SpatialTree {
invertible: true,
is_async_zooming: false,
is_ancestor_or_self_zooming: false,
+ uid,
};
assert!(index <= self.spatial_nodes.len());
@@ -917,11 +924,15 @@ impl SpatialTree {
self.spatial_nodes[new_parent.0 as usize].add_child(SpatialNodeIndex(index as u32));
}
+ let uid = self.next_internal_uid;
+ self.next_internal_uid += 1;
+
let node = &mut self.spatial_nodes[index];
node.node_type = descriptor.node_type;
node.pipeline_id = descriptor.pipeline_id;
node.parent = parent;
+ node.uid = uid;
}
SpatialTreeUpdate::Remove { index, .. } => {
let node = &mut self.spatial_nodes[index];
@@ -2116,7 +2127,7 @@ fn test_world_transforms() {
PipelineId::dummy(),
&LayoutRect::from_size(LayoutSize::new(400.0, 400.0)),
&LayoutSize::new(400.0, 800.0),
- ScrollFrameKind::Explicit,
+ ScrollFrameKind::Explicit,
LayoutVector2D::new(0.0, 200.0),
APZScrollGeneration::default(),
HasScrollLinkedEffect::No,