diff --git a/src/renderer/metrics.rs b/src/renderer/metrics.rs index 08efa2d..4b2663d 100644 --- a/src/renderer/metrics.rs +++ b/src/renderer/metrics.rs @@ -12,6 +12,7 @@ pub struct ShapeEffectCacheMetrics { pub executed_passes: u64, pub composited_results: u64, pub collected_results: u64, + pub collected_masks: u64, } /// Per-frame pipeline switch counts for diagnosing GPU state-change overhead. diff --git a/src/renderer/rendering.rs b/src/renderer/rendering.rs index 773960b..6abbac1 100644 --- a/src/renderer/rendering.rs +++ b/src/renderer/rendering.rs @@ -23,6 +23,7 @@ impl<'a> Renderer<'a> { { self.last_shape_effect_cache_metrics = ShapeEffectCacheMetrics { collected_results: _collected_shape_effect_results as u64, + collected_masks: _collected_shape_effect_masks as u64, ..Default::default() }; } @@ -501,6 +502,7 @@ impl<'a> Renderer<'a> { self.scratch.clip_kind_stack = clip_kind_stack; self.scratch.backdrop_work_textures = backdrop_work_textures; let _collected_shape_effect_results = self.shape_effect_cache.end_frame(); + let _collected_shape_effect_masks = self.shape_effect_mask_cache.end_frame(); self.buffers_pool_manager.tessellation_cache.end_frame(); // println!("Tesselation cache size: {}", self.buffers_pool_manager.tessellation_cache.len()); @@ -508,6 +510,7 @@ impl<'a> Renderer<'a> { #[cfg(feature = "render_metrics")] { shape_effect_cache_metrics.collected_results = _collected_shape_effect_results as u64; + shape_effect_cache_metrics.collected_masks = _collected_shape_effect_masks as u64; self.last_pipeline_switch_counts = frame_pipeline_counts; self.last_shape_effect_cache_metrics = shape_effect_cache_metrics; } diff --git a/src/renderer/shape_effects.rs b/src/renderer/shape_effects.rs index 4f99553..bc291ba 100644 --- a/src/renderer/shape_effects.rs +++ b/src/renderer/shape_effects.rs @@ -550,7 +550,17 @@ impl<'a> Renderer<'a> { downsample_bits: shape_effect_instance.config.downsample.to_bits(), texture_format: self.config.format, }; + let mask_cache_key = ShapeEffectMaskCacheKey { + tessellation: Arc::clone(&cached_shape.cached_shape.tessellation), + local_raster_origin: raster_rect.local_physical_origin, + raster_size: raster_rect.texture_size, + scale_factor_bits: self.scale_factor.to_bits(), + fringe_width_bits: self.fringe_width.to_bits(), + downsample_bits: shape_effect_instance.config.downsample.to_bits(), + texture_format: self.config.format, + }; if let Some(cached_result) = self.shape_effect_cache.get(&cache_key) { + let _cached_mask = self.shape_effect_mask_cache.get(&mask_cache_key); #[cfg(feature = "render_metrics")] { metrics.hits += 1; @@ -577,15 +587,6 @@ impl<'a> Renderer<'a> { // The mask depends only on geometry and rasterization parameters, so it // is cached separately from the effect result and reused across effect // cache misses (e.g. animated effect parameters). - let mask_cache_key = ShapeEffectMaskCacheKey { - tessellation: Arc::clone(&cached_shape.cached_shape.tessellation), - local_raster_origin: raster_rect.local_physical_origin, - raster_size: raster_rect.texture_size, - scale_factor_bits: self.scale_factor.to_bits(), - fringe_width_bits: self.fringe_width.to_bits(), - downsample_bits: shape_effect_instance.config.downsample.to_bits(), - texture_format: self.config.format, - }; let cached_mask = if let Some(cached_mask) = self.shape_effect_mask_cache.get(&mask_cache_key) { diff --git a/tests/visual_regression.rs b/tests/visual_regression.rs index c337c19..4f6540f 100644 --- a/tests/visual_regression.rs +++ b/tests/visual_regression.rs @@ -191,13 +191,14 @@ fn unchanged_shape_effect_reuses_exact_gpu_result_and_collects_when_unused() { let replaced_effect_frame = renderer.last_shape_effect_cache_metrics(); assert_eq!(replaced_effect_frame.misses, 1); assert_eq!(replaced_effect_frame.hits, 0); + assert_eq!(replaced_effect_frame.mask_hits, 1); + assert_eq!(replaced_effect_frame.generated_masks, 0); renderer.remove_shape_effect(shape_id); renderer.render_to_buffer(&mut pixels); - assert_eq!( - renderer.last_shape_effect_cache_metrics().collected_results, - 1 - ); + let unused_effect_frame = renderer.last_shape_effect_cache_metrics(); + assert_eq!(unused_effect_frame.collected_results, 1); + assert_eq!(unused_effect_frame.collected_masks, 1); } #[cfg(feature = "render_metrics")]