1use api::{DebugFlags, Parameter, BoolParameter, PrimitiveFlags, MinimapData};
12use api::{DocumentId, ExternalScrollId, HitTestResult};
13use api::{IdNamespace, PipelineId, RenderNotifier, SampledScrollOffset};
14use api::{NotificationRequest, Checkpoint, QualitySettings};
15use api::{FramePublishId, PrimitiveKeyKind, RenderReasons};
16use api::units::*;
17use api::channel::{single_msg_channel, Sender, Receiver};
18use crate::bump_allocator::ChunkPool;
19use crate::AsyncPropertySampler;
20use crate::box_shadow::BoxShadow;
21#[cfg(any(feature = "capture", feature = "replay"))]
22use crate::render_api::CaptureBits;
23#[cfg(feature = "replay")]
24use crate::render_api::CapturedDocument;
25use crate::render_api::{MemoryReport, TransactionMsg, ResourceUpdate, ApiMsg, FrameMsg, ClearCache, DebugCommand};
26use crate::clip::{ClipIntern, PolygonIntern, ClipStoreScratchBuffer};
27use crate::filterdata::FilterDataIntern;
28#[cfg(any(feature = "capture", feature = "replay"))]
29use crate::capture::CaptureConfig;
30use crate::composite::{CompositorKind, CompositeDescriptor};
31use crate::frame_builder::{FrameBuilder, FrameBuilderConfig, FrameScratchBuffer};
32use glyph_rasterizer::FontInstance;
33use crate::gpu_cache::GpuCache;
34use crate::hit_test::{HitTest, HitTester, SharedHitTester};
35use crate::intern::DataStore;
36#[cfg(any(feature = "capture", feature = "replay"))]
37use crate::internal_types::DebugOutput;
38use crate::internal_types::{FastHashMap, FrameId, FrameStamp, RenderedDocument, ResultMsg};
39use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
40use crate::picture::{PictureScratchBuffer, SliceId, TileCacheInstance, TileCacheParams, SurfaceInfo, RasterConfig};
41use crate::picture::PicturePrimitive;
42use crate::prim_store::{PrimitiveScratchBuffer, PrimitiveInstance};
43use crate::prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData};
44use crate::prim_store::interned::*;
45use crate::profiler::{self, TransactionProfile};
46use crate::render_task_graph::RenderTaskGraphBuilder;
47use crate::renderer::{FullFrameStats, PipelineInfo};
48use crate::resource_cache::ResourceCache;
49#[cfg(feature = "replay")]
50use crate::resource_cache::PlainCacheOwn;
51#[cfg(feature = "replay")]
52use crate::resource_cache::PlainResources;
53#[cfg(feature = "replay")]
54use crate::scene::Scene;
55use crate::scene::{BuiltScene, SceneProperties};
56use crate::scene_builder_thread::*;
57use crate::spatial_tree::SpatialTree;
58#[cfg(feature = "replay")]
59use crate::spatial_tree::SceneSpatialTree;
60use crate::telemetry::Telemetry;
61#[cfg(feature = "capture")]
62use serde::Serialize;
63#[cfg(feature = "replay")]
64use serde::Deserialize;
65#[cfg(feature = "replay")]
66use std::collections::hash_map::Entry::{Occupied, Vacant};
67use std::sync::Arc;
68use std::sync::atomic::{AtomicUsize, Ordering};
69use std::{mem, u32};
70#[cfg(feature = "capture")]
71use std::path::PathBuf;
72#[cfg(feature = "replay")]
73use crate::frame_builder::Frame;
74use core::time::Duration;
75use crate::util::{Recycler, VecHelper, drain_filter};
76#[cfg(feature = "debugger")]
77use crate::debugger::DebugQueryKind;
78
79#[cfg_attr(feature = "capture", derive(Serialize))]
80#[cfg_attr(feature = "replay", derive(Deserialize))]
81#[derive(Copy, Clone)]
82pub struct DocumentView {
83 scene: SceneView,
84}
85
86#[cfg_attr(feature = "capture", derive(Serialize))]
88#[cfg_attr(feature = "replay", derive(Deserialize))]
89#[derive(Copy, Clone)]
90pub struct SceneView {
91 pub device_rect: DeviceIntRect,
92 pub quality_settings: QualitySettings,
93}
94
95enum RenderBackendStatus {
96 Continue,
97 StopRenderBackend,
98 ShutDown(Option<Sender<()>>),
99}
100
101macro_rules! declare_data_stores {
102 ( $( $name:ident : $ty:ty, )+ ) => {
103 #[cfg_attr(feature = "capture", derive(Serialize))]
106 #[cfg_attr(feature = "replay", derive(Deserialize))]
107 #[derive(Default)]
108 pub struct DataStores {
109 $(
110 pub $name: DataStore<$ty>,
111 )+
112 }
113
114 impl DataStores {
115 fn report_memory(&self, ops: &mut MallocSizeOfOps, r: &mut MemoryReport) {
117 $(
118 r.interning.data_stores.$name += self.$name.size_of(ops);
119 )+
120 }
121
122 fn apply_updates(
123 &mut self,
124 updates: InternerUpdates,
125 profile: &mut TransactionProfile,
126 ) {
127 $(
128 self.$name.apply_updates(
129 updates.$name,
130 profile,
131 );
132 )+
133 }
134 }
135 }
136}
137
138crate::enumerate_interners!(declare_data_stores);
139
140impl DataStores {
141 pub fn get_local_prim_rect(
145 &self,
146 prim_instance: &PrimitiveInstance,
147 pictures: &[PicturePrimitive],
148 surfaces: &[SurfaceInfo],
149 ) -> LayoutRect {
150 match prim_instance.kind {
151 PrimitiveInstanceKind::Picture { pic_index, .. } => {
152 let pic = &pictures[pic_index.0];
153
154 match pic.raster_config {
155 Some(RasterConfig { surface_index, ref composite_mode, .. }) => {
156 let surface = &surfaces[surface_index.0];
157
158 composite_mode.get_rect(surface, None)
159 }
160 None => {
161 panic!("bug: get_local_prim_rect should not be called for pass-through pictures");
162 }
163 }
164 }
165 _ => {
166 self.as_common_data(prim_instance).prim_rect
167 }
168 }
169 }
170
171 pub fn get_local_prim_coverage_rect(
175 &self,
176 prim_instance: &PrimitiveInstance,
177 pictures: &[PicturePrimitive],
178 surfaces: &[SurfaceInfo],
179 ) -> LayoutRect {
180 match prim_instance.kind {
181 PrimitiveInstanceKind::Picture { pic_index, .. } => {
182 let pic = &pictures[pic_index.0];
183
184 match pic.raster_config {
185 Some(RasterConfig { surface_index, ref composite_mode, .. }) => {
186 let surface = &surfaces[surface_index.0];
187
188 composite_mode.get_coverage(surface, None)
189 }
190 None => {
191 panic!("bug: get_local_prim_coverage_rect should not be called for pass-through pictures");
192 }
193 }
194 }
195 _ => {
196 self.as_common_data(prim_instance).prim_rect
197 }
198 }
199 }
200
201 pub fn prim_may_need_repetition(
205 &self,
206 prim_instance: &PrimitiveInstance,
207 ) -> bool {
208 match prim_instance.kind {
209 PrimitiveInstanceKind::Picture { .. } => {
210 false
211 }
212 _ => {
213 self.as_common_data(prim_instance).may_need_repetition
214 }
215 }
216 }
217
218 pub fn prim_has_anti_aliasing(
220 &self,
221 prim_instance: &PrimitiveInstance,
222 ) -> bool {
223 match prim_instance.kind {
224 PrimitiveInstanceKind::Picture { .. } => {
225 false
226 }
227 _ => {
228 self.as_common_data(prim_instance).flags.contains(PrimitiveFlags::ANTIALISED)
229 }
230 }
231 }
232
233 pub fn as_common_data(
234 &self,
235 prim_inst: &PrimitiveInstance
236 ) -> &PrimTemplateCommonData {
237 match prim_inst.kind {
238 PrimitiveInstanceKind::Rectangle { data_handle, .. } |
239 PrimitiveInstanceKind::Clear { data_handle, .. } => {
240 let prim_data = &self.prim[data_handle];
241 &prim_data.common
242 }
243 PrimitiveInstanceKind::Image { data_handle, .. } => {
244 let prim_data = &self.image[data_handle];
245 &prim_data.common
246 }
247 PrimitiveInstanceKind::ImageBorder { data_handle, .. } => {
248 let prim_data = &self.image_border[data_handle];
249 &prim_data.common
250 }
251 PrimitiveInstanceKind::LineDecoration { data_handle, .. } => {
252 let prim_data = &self.line_decoration[data_handle];
253 &prim_data.common
254 }
255 PrimitiveInstanceKind::LinearGradient { data_handle, .. }
256 | PrimitiveInstanceKind::CachedLinearGradient { data_handle, .. } => {
257 let prim_data = &self.linear_grad[data_handle];
258 &prim_data.common
259 }
260 PrimitiveInstanceKind::NormalBorder { data_handle, .. } => {
261 let prim_data = &self.normal_border[data_handle];
262 &prim_data.common
263 }
264 PrimitiveInstanceKind::Picture { .. } => {
265 panic!("BUG: picture prims don't have common data!");
266 }
267 PrimitiveInstanceKind::RadialGradient { data_handle, .. } => {
268 let prim_data = &self.radial_grad[data_handle];
269 &prim_data.common
270 }
271 PrimitiveInstanceKind::ConicGradient { data_handle, .. } => {
272 let prim_data = &self.conic_grad[data_handle];
273 &prim_data.common
274 }
275 PrimitiveInstanceKind::TextRun { data_handle, .. } => {
276 let prim_data = &self.text_run[data_handle];
277 &prim_data.common
278 }
279 PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
280 let prim_data = &self.yuv_image[data_handle];
281 &prim_data.common
282 }
283 PrimitiveInstanceKind::BackdropCapture { data_handle, .. } => {
284 let prim_data = &self.backdrop_capture[data_handle];
285 &prim_data.common
286 }
287 PrimitiveInstanceKind::BackdropRender { data_handle, .. } => {
288 let prim_data = &self.backdrop_render[data_handle];
289 &prim_data.common
290 }
291 PrimitiveInstanceKind::BoxShadow { data_handle, .. } => {
292 let prim_data = &self.box_shadow[data_handle];
293 &prim_data.common
294 }
295 }
296 }
297}
298
299#[derive(Default)]
300pub struct ScratchBuffer {
301 pub primitive: PrimitiveScratchBuffer,
302 pub picture: PictureScratchBuffer,
303 pub frame: FrameScratchBuffer,
304 pub clip_store: ClipStoreScratchBuffer,
305}
306
307impl ScratchBuffer {
308 pub fn begin_frame(&mut self) {
309 self.primitive.begin_frame();
310 self.picture.begin_frame();
311 self.frame.begin_frame();
312 }
313
314 pub fn end_frame(&mut self) {
315 self.primitive.end_frame();
316 }
317
318 pub fn recycle(&mut self, recycler: &mut Recycler) {
319 self.primitive.recycle(recycler);
320 self.picture.recycle(recycler);
321 }
322
323 pub fn memory_pressure(&mut self) {
324 self.picture = Default::default();
327 self.frame = Default::default();
328 self.clip_store = Default::default();
329 }
330}
331
332struct Document {
333 id: DocumentId,
335
336 removed_pipelines: Vec<(PipelineId, DocumentId)>,
339
340 view: DocumentView,
341
342 stamp: FrameStamp,
344
345 scene: BuiltScene,
348
349 frame_builder: FrameBuilder,
351
352 rg_builder: RenderTaskGraphBuilder,
354
355 hit_tester: Option<Arc<HitTester>>,
358 shared_hit_tester: Arc<SharedHitTester>,
361
362 dynamic_properties: SceneProperties,
365
366 frame_is_valid: bool,
369 hit_tester_is_valid: bool,
370 rendered_frame_is_valid: bool,
371 has_built_scene: bool,
374
375 data_stores: DataStores,
376
377 spatial_tree: SpatialTree,
379
380 minimap_data: FastHashMap<ExternalScrollId, MinimapData>,
381
382 scratch: ScratchBuffer,
386
387 #[cfg(feature = "replay")]
388 loaded_scene: Scene,
389
390 prev_composite_descriptor: CompositeDescriptor,
392
393 dirty_rects_are_valid: bool,
396
397 profile: TransactionProfile,
398 frame_stats: Option<FullFrameStats>,
399}
400
401impl Document {
402 pub fn new(
403 id: DocumentId,
404 size: DeviceIntSize,
405 ) -> Self {
406 Document {
407 id,
408 removed_pipelines: Vec::new(),
409 view: DocumentView {
410 scene: SceneView {
411 device_rect: size.into(),
412 quality_settings: QualitySettings::default(),
413 },
414 },
415 stamp: FrameStamp::first(id),
416 scene: BuiltScene::empty(),
417 frame_builder: FrameBuilder::new(),
418 hit_tester: None,
419 shared_hit_tester: Arc::new(SharedHitTester::new()),
420 dynamic_properties: SceneProperties::new(),
421 frame_is_valid: false,
422 hit_tester_is_valid: false,
423 rendered_frame_is_valid: false,
424 has_built_scene: false,
425 data_stores: DataStores::default(),
426 spatial_tree: SpatialTree::new(),
427 minimap_data: FastHashMap::default(),
428 scratch: ScratchBuffer::default(),
429 #[cfg(feature = "replay")]
430 loaded_scene: Scene::new(),
431 prev_composite_descriptor: CompositeDescriptor::empty(),
432 dirty_rects_are_valid: true,
433 profile: TransactionProfile::new(),
434 rg_builder: RenderTaskGraphBuilder::new(),
435 frame_stats: None,
436 }
437 }
438
439 fn can_render(&self) -> bool {
440 self.scene.has_root_pipeline
441 }
442
443 fn has_pixels(&self) -> bool {
444 !self.view.scene.device_rect.is_empty()
445 }
446
447 fn process_frame_msg(
448 &mut self,
449 message: FrameMsg,
450 ) -> DocumentOps {
451 match message {
452 FrameMsg::UpdateEpoch(pipeline_id, epoch) => {
453 self.scene.pipeline_epochs.insert(pipeline_id, epoch);
454 }
455 FrameMsg::HitTest(point, tx) => {
456 if !self.hit_tester_is_valid {
457 self.rebuild_hit_tester();
458 }
459
460 let result = match self.hit_tester {
461 Some(ref hit_tester) => {
462 hit_tester.hit_test(HitTest::new(point))
463 }
464 None => HitTestResult { items: Vec::new() },
465 };
466
467 tx.send(result).unwrap();
468 }
469 FrameMsg::RequestHitTester(tx) => {
470 tx.send(self.shared_hit_tester.clone()).unwrap();
471 }
472 FrameMsg::SetScrollOffsets(id, offset) => {
473 profile_scope!("SetScrollOffset");
474
475 if self.set_scroll_offsets(id, offset) {
476 self.hit_tester_is_valid = false;
477 self.frame_is_valid = false;
478 }
479
480 return DocumentOps {
481 scroll: true,
482 ..DocumentOps::nop()
483 };
484 }
485 FrameMsg::ResetDynamicProperties => {
486 self.dynamic_properties.reset_properties();
487 }
488 FrameMsg::AppendDynamicProperties(property_bindings) => {
489 self.dynamic_properties.add_properties(property_bindings);
490 }
491 FrameMsg::AppendDynamicTransformProperties(property_bindings) => {
492 self.dynamic_properties.add_transforms(property_bindings);
493 }
494 FrameMsg::SetIsTransformAsyncZooming(is_zooming, animation_id) => {
495 if let Some(node_index) = self.spatial_tree.find_spatial_node_by_anim_id(animation_id) {
496 let node = self.spatial_tree.get_spatial_node_mut(node_index);
497
498 if node.is_async_zooming != is_zooming {
499 node.is_async_zooming = is_zooming;
500 self.frame_is_valid = false;
501 }
502 }
503 }
504 FrameMsg::SetMinimapData(id, minimap_data) => {
505 self.minimap_data.insert(id, minimap_data);
506 }
507 }
508
509 DocumentOps::nop()
510 }
511
512 fn build_frame(
513 &mut self,
514 resource_cache: &mut ResourceCache,
515 gpu_cache: &mut GpuCache,
516 debug_flags: DebugFlags,
517 tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
518 frame_stats: Option<FullFrameStats>,
519 present: bool,
520 render_reasons: RenderReasons,
521 chunk_pool: Arc<ChunkPool>,
522 ) -> RenderedDocument {
523 let frame_build_start_time = zeitstempel::now();
524
525 self.stamp.advance();
527
528 assert!(self.stamp.frame_id() != FrameId::INVALID,
529 "First frame increment must happen before build_frame()");
530
531 let frame = {
532 let frame = self.frame_builder.build(
533 &mut self.scene,
534 present,
535 resource_cache,
536 gpu_cache,
537 &mut self.rg_builder,
538 self.stamp,
539 self.view.scene.device_rect.min,
540 &self.dynamic_properties,
541 &mut self.data_stores,
542 &mut self.scratch,
543 debug_flags,
544 tile_caches,
545 &mut self.spatial_tree,
546 self.dirty_rects_are_valid,
547 &mut self.profile,
548 mem::take(&mut self.minimap_data),
552 chunk_pool,
553 );
554
555 frame
556 };
557
558 self.frame_is_valid = true;
559 self.dirty_rects_are_valid = true;
560
561 self.has_built_scene = false;
562
563 let frame_build_time_ms =
564 profiler::ns_to_ms(zeitstempel::now() - frame_build_start_time);
565 self.profile.set(profiler::FRAME_BUILDING_TIME, frame_build_time_ms);
566 self.profile.start_time(profiler::FRAME_SEND_TIME);
567
568 let frame_stats = frame_stats.map(|mut stats| {
569 stats.frame_build_time += frame_build_time_ms;
570 stats
571 });
572
573 RenderedDocument {
574 frame,
575 profile: self.profile.take_and_reset(),
576 frame_stats: frame_stats,
577 render_reasons,
578 }
579 }
580
581 fn process_offscreen_scene(
587 &mut self,
588 mut txn: OffscreenBuiltScene,
589 resource_cache: &mut ResourceCache,
590 gpu_cache: &mut GpuCache,
591 chunk_pool: Arc<ChunkPool>,
592 debug_flags: DebugFlags,
593 ) -> RenderedDocument {
594 let mut profile = TransactionProfile::new();
595 self.stamp.advance();
596
597 let mut data_stores = DataStores::default();
598 data_stores.apply_updates(txn.interner_updates, &mut profile);
599
600 let mut spatial_tree = SpatialTree::new();
601 spatial_tree.apply_updates(txn.spatial_tree_updates);
602
603 let mut tile_caches = FastHashMap::default();
604 self.update_tile_caches_for_new_scene(
605 mem::take(&mut txn.scene.tile_cache_config.tile_caches),
606 &mut tile_caches,
607 resource_cache,
608 );
609
610 let present = false;
611
612 let frame = self.frame_builder.build(
613 &mut txn.scene,
614 present,
615 resource_cache,
616 gpu_cache,
617 &mut self.rg_builder,
618 self.stamp, self.view.scene.device_rect.min,
620 &self.dynamic_properties,
621 &mut data_stores,
622 &mut self.scratch,
623 debug_flags,
624 &mut tile_caches,
625 &mut spatial_tree,
626 self.dirty_rects_are_valid,
627 &mut profile,
628 mem::take(&mut self.minimap_data),
632 chunk_pool,
633 );
634
635 RenderedDocument {
636 frame,
637 profile,
638 render_reasons: RenderReasons::SNAPSHOT,
639 frame_stats: None,
640 }
641 }
642
643
644 fn rebuild_hit_tester(&mut self) {
645 self.spatial_tree.update_tree(&self.dynamic_properties);
646
647 let hit_tester = Arc::new(self.scene.create_hit_tester(&self.spatial_tree));
648 self.hit_tester = Some(Arc::clone(&hit_tester));
649 self.shared_hit_tester.update(hit_tester);
650 self.hit_tester_is_valid = true;
651 }
652
653 pub fn updated_pipeline_info(&mut self) -> PipelineInfo {
654 let removed_pipelines = self.removed_pipelines.take_and_preallocate();
655 PipelineInfo {
656 epochs: self.scene.pipeline_epochs.iter()
657 .map(|(&pipeline_id, &epoch)| ((pipeline_id, self.id), epoch)).collect(),
658 removed_pipelines,
659 }
660 }
661
662 pub fn set_scroll_offsets(
664 &mut self,
665 id: ExternalScrollId,
666 offsets: Vec<SampledScrollOffset>,
667 ) -> bool {
668 self.spatial_tree.set_scroll_offsets(id, offsets)
669 }
670
671 fn update_tile_caches_for_new_scene(
675 &mut self,
676 mut requested_tile_caches: FastHashMap<SliceId, TileCacheParams>,
677 tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
678 resource_cache: &mut ResourceCache,
679 ) {
680 let mut new_tile_caches = FastHashMap::default();
681 new_tile_caches.reserve(requested_tile_caches.len());
682
683 for (slice_id, params) in requested_tile_caches.drain() {
686 let tile_cache = match tile_caches.remove(&slice_id) {
687 Some(mut existing_tile_cache) => {
688 existing_tile_cache.prepare_for_new_scene(
690 params,
691 resource_cache,
692 );
693 existing_tile_cache
694 }
695 None => {
696 Box::new(TileCacheInstance::new(params))
698 }
699 };
700
701 new_tile_caches.insert(slice_id, tile_cache);
702 }
703
704 let unused_tile_caches = mem::replace(
707 tile_caches,
708 new_tile_caches,
709 );
710
711 if !unused_tile_caches.is_empty() {
712 self.dirty_rects_are_valid = false;
715
716 for (_, tile_cache) in unused_tile_caches {
718 tile_cache.destroy(resource_cache);
719 }
720 }
721 }
722
723 pub fn new_async_scene_ready(
724 &mut self,
725 mut built_scene: BuiltScene,
726 recycler: &mut Recycler,
727 tile_caches: &mut FastHashMap<SliceId, Box<TileCacheInstance>>,
728 resource_cache: &mut ResourceCache,
729 ) {
730 self.frame_is_valid = false;
731 self.hit_tester_is_valid = false;
732
733 self.update_tile_caches_for_new_scene(
734 mem::replace(&mut built_scene.tile_cache_config.tile_caches, FastHashMap::default()),
735 tile_caches,
736 resource_cache,
737 );
738
739
740 let old_scene = std::mem::replace(&mut self.scene, built_scene);
741 old_scene.recycle();
742
743 self.scratch.recycle(recycler);
744 }
745}
746
747struct DocumentOps {
748 scroll: bool,
749}
750
751impl DocumentOps {
752 fn nop() -> Self {
753 DocumentOps {
754 scroll: false,
755 }
756 }
757}
758
759static NEXT_NAMESPACE_ID: AtomicUsize = AtomicUsize::new(1);
762
763#[cfg(any(feature = "capture", feature = "replay"))]
764#[cfg_attr(feature = "capture", derive(Serialize))]
765#[cfg_attr(feature = "replay", derive(Deserialize))]
766struct PlainRenderBackend {
767 frame_config: FrameBuilderConfig,
768 documents: FastHashMap<DocumentId, DocumentView>,
769 resource_sequence_id: u32,
770}
771
772pub struct RenderBackend {
777 api_rx: Receiver<ApiMsg>,
778 result_tx: Sender<ResultMsg>,
779 scene_tx: Sender<SceneBuilderRequest>,
780
781 gpu_cache: GpuCache,
782 resource_cache: ResourceCache,
783 chunk_pool: Arc<ChunkPool>,
784
785 frame_config: FrameBuilderConfig,
786 default_compositor_kind: CompositorKind,
787 documents: FastHashMap<DocumentId, Document>,
788
789 notifier: Box<dyn RenderNotifier>,
790 sampler: Option<Box<dyn AsyncPropertySampler + Send>>,
791 size_of_ops: Option<MallocSizeOfOps>,
792 debug_flags: DebugFlags,
793 namespace_alloc_by_client: bool,
794
795 recycler: Recycler,
796
797 #[cfg(feature = "capture")]
798 capture_config: Option<CaptureConfig>,
802
803 #[cfg(feature = "replay")]
804 loaded_resource_sequence_id: u32,
805
806 tile_caches: FastHashMap<SliceId, Box<TileCacheInstance>>,
809
810 frame_publish_id: FramePublishId,
812}
813
814impl RenderBackend {
815 pub fn new(
816 api_rx: Receiver<ApiMsg>,
817 result_tx: Sender<ResultMsg>,
818 scene_tx: Sender<SceneBuilderRequest>,
819 resource_cache: ResourceCache,
820 chunk_pool: Arc<ChunkPool>,
821 notifier: Box<dyn RenderNotifier>,
822 frame_config: FrameBuilderConfig,
823 sampler: Option<Box<dyn AsyncPropertySampler + Send>>,
824 size_of_ops: Option<MallocSizeOfOps>,
825 debug_flags: DebugFlags,
826 namespace_alloc_by_client: bool,
827 ) -> RenderBackend {
828 RenderBackend {
829 api_rx,
830 result_tx,
831 scene_tx,
832 resource_cache,
833 gpu_cache: GpuCache::new(),
834 chunk_pool,
835 frame_config,
836 default_compositor_kind : frame_config.compositor_kind,
837 documents: FastHashMap::default(),
838 notifier,
839 sampler,
840 size_of_ops,
841 debug_flags,
842 namespace_alloc_by_client,
843 recycler: Recycler::new(),
844 #[cfg(feature = "capture")]
845 capture_config: None,
846 #[cfg(feature = "replay")]
847 loaded_resource_sequence_id: 0,
848 tile_caches: FastHashMap::default(),
849 frame_publish_id: FramePublishId::first(),
850 }
851 }
852
853 pub fn next_namespace_id() -> IdNamespace {
854 IdNamespace(NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed) as u32)
855 }
856
857 pub fn run(&mut self) {
858 let mut frame_counter: u32 = 0;
859 let mut status = RenderBackendStatus::Continue;
860
861 if let Some(ref sampler) = self.sampler {
862 sampler.register();
863 }
864
865 while let RenderBackendStatus::Continue = status {
866 status = match self.api_rx.recv() {
867 Ok(msg) => {
868 self.process_api_msg(msg, &mut frame_counter)
869 }
870 Err(..) => { RenderBackendStatus::ShutDown(None) }
871 };
872 }
873
874 if let RenderBackendStatus::StopRenderBackend = status {
875 while let Ok(msg) = self.api_rx.recv() {
876 match msg {
877 ApiMsg::SceneBuilderResult(SceneBuilderResult::ExternalEvent(evt)) => {
878 self.notifier.external_event(evt);
879 }
880 ApiMsg::SceneBuilderResult(SceneBuilderResult::FlushComplete(tx)) => {
881 debug_assert!(false);
885 tx.send(()).ok();
886 }
887 ApiMsg::SceneBuilderResult(SceneBuilderResult::ShutDown(sender)) => {
888 info!("Recycling stats: {:?}", self.recycler);
889 status = RenderBackendStatus::ShutDown(sender);
890 break;
891 }
892 _ => {},
893 }
894 }
895 }
896
897 while let Ok(msg) = self.api_rx.try_recv() {
900 match msg {
901 ApiMsg::SceneBuilderResult(SceneBuilderResult::FlushComplete(tx)) => {
902 debug_assert!(false);
906 tx.send(()).ok();
907 }
908 _ => {},
909 }
910 }
911
912 self.documents.clear();
913
914 self.notifier.shut_down();
915
916 if let Some(ref sampler) = self.sampler {
917 sampler.deregister();
918 }
919
920
921 if let RenderBackendStatus::ShutDown(Some(sender)) = status {
922 let _ = sender.send(());
923 }
924 }
925
926 fn process_transaction(
927 &mut self,
928 mut txns: Vec<Box<BuiltTransaction>>,
929 result_tx: Option<Sender<SceneSwapResult>>,
930 frame_counter: &mut u32,
931 ) -> bool {
932 self.prepare_for_frames();
933 self.maybe_force_nop_documents(
934 frame_counter,
935 |document_id| txns.iter().any(|txn| txn.document_id == document_id));
936
937 let mut built_frame = false;
938 for mut txn in txns.drain(..) {
939 let has_built_scene = txn.built_scene.is_some();
940
941 if let Some(doc) = self.documents.get_mut(&txn.document_id) {
942 doc.removed_pipelines.append(&mut txn.removed_pipelines);
943 doc.view.scene = txn.view;
944 doc.profile.merge(&mut txn.profile);
945
946 doc.frame_stats = if let Some(stats) = &doc.frame_stats {
947 Some(stats.merge(&txn.frame_stats))
948 } else {
949 Some(txn.frame_stats)
950 };
951
952 let last_sampled_scroll_offsets = if self.sampler.is_some() {
955 Some(doc.spatial_tree.get_last_sampled_scroll_offsets())
956 } else {
957 None
958 };
959
960 if let Some(updates) = txn.spatial_tree_updates.take() {
961 doc.spatial_tree.apply_updates(updates);
962 }
963
964 if let Some(built_scene) = txn.built_scene.take() {
965 doc.new_async_scene_ready(
966 built_scene,
967 &mut self.recycler,
968 &mut self.tile_caches,
969 &mut self.resource_cache,
970 );
971 }
972
973 if let Some(updates) = txn.interner_updates.take() {
977 doc.data_stores.apply_updates(updates, &mut doc.profile);
978 }
979
980 if let Some(last_sampled) = last_sampled_scroll_offsets {
987 doc.spatial_tree
988 .apply_last_sampled_scroll_offsets(last_sampled);
989 }
990
991 if !doc.hit_tester_is_valid {
994 doc.rebuild_hit_tester();
995 }
996
997 if let Some(ref tx) = result_tx {
998 let (resume_tx, resume_rx) = single_msg_channel();
999 tx.send(SceneSwapResult::Complete(resume_tx)).unwrap();
1000 resume_rx.recv().ok();
1005 }
1006
1007 self.resource_cache.add_rasterized_blob_images(
1008 txn.rasterized_blobs.take(),
1009 &mut doc.profile,
1010 );
1011
1012 for offscreen_scene in txn.offscreen_scenes.drain(..) {
1013 self.resource_cache.post_scene_building_update(
1014 txn.resource_updates.take(),
1015 &mut doc.profile,
1016 );
1017
1018 let rendered_document = doc.process_offscreen_scene(
1019 offscreen_scene,
1020 &mut self.resource_cache,
1021 &mut self.gpu_cache,
1022 self.chunk_pool.clone(),
1023 self.debug_flags,
1024 );
1025
1026 let msg = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
1027 self.result_tx.send(msg).unwrap();
1028
1029 let pending_update = self.resource_cache.pending_updates();
1030
1031 let msg = ResultMsg::PublishDocument(
1032 self.frame_publish_id,
1033 txn.document_id,
1034 rendered_document,
1035 pending_update,
1036 );
1037 self.result_tx.send(msg).unwrap();
1038
1039 let params = api::FrameReadyParams {
1040 present: false,
1041 render: true,
1042 scrolled: false,
1043 tracked: false,
1044 };
1045
1046 self.notifier.new_frame_ready(
1047 txn.document_id,
1048 self.frame_publish_id,
1049 ¶ms
1050 );
1051 }
1052 } else {
1053 if let Some(ref tx) = result_tx {
1057 tx.send(SceneSwapResult::Aborted).unwrap();
1058 }
1059 continue;
1060 }
1061
1062 built_frame |= self.update_document(
1063 txn.document_id,
1064 txn.resource_updates.take(),
1065 txn.frame_ops.take(),
1066 txn.notifications.take(),
1067 txn.render_frame,
1068 txn.present,
1069 txn.tracked,
1070 RenderReasons::SCENE,
1071 None,
1072 txn.invalidate_rendered_frame,
1073 frame_counter,
1074 has_built_scene,
1075 None,
1076 );
1077 }
1078
1079 built_frame
1080 }
1081
1082 fn process_api_msg(
1083 &mut self,
1084 msg: ApiMsg,
1085 frame_counter: &mut u32,
1086 ) -> RenderBackendStatus {
1087 match msg {
1088 ApiMsg::CloneApi(sender) => {
1089 assert!(!self.namespace_alloc_by_client);
1090 sender.send(Self::next_namespace_id()).unwrap();
1091 }
1092 ApiMsg::CloneApiByClient(namespace_id) => {
1093 assert!(self.namespace_alloc_by_client);
1094 debug_assert!(!self.documents.iter().any(|(did, _doc)| did.namespace_id == namespace_id));
1095 }
1096 ApiMsg::AddDocument(document_id, initial_size) => {
1097 let document = Document::new(
1098 document_id,
1099 initial_size,
1100 );
1101 let old = self.documents.insert(document_id, document);
1102 debug_assert!(old.is_none());
1103 }
1104 ApiMsg::MemoryPressure => {
1105 self.resource_cache.clear(ClearCache::all());
1114
1115 self.gpu_cache.clear();
1116
1117 for (_, doc) in &mut self.documents {
1118 doc.scratch.memory_pressure();
1119 for tile_cache in self.tile_caches.values_mut() {
1120 tile_cache.memory_pressure(&mut self.resource_cache);
1121 }
1122 }
1123
1124 let resource_updates = self.resource_cache.pending_updates();
1125 let msg = ResultMsg::UpdateResources {
1126 resource_updates,
1127 memory_pressure: true,
1128 };
1129 self.result_tx.send(msg).unwrap();
1130 self.notifier.wake_up(false);
1131
1132 self.chunk_pool.purge_all_chunks();
1133 }
1134 ApiMsg::ReportMemory(tx) => {
1135 self.report_memory(tx);
1136 }
1137 ApiMsg::DebugCommand(option) => {
1138 let msg = match option {
1139 DebugCommand::SetPictureTileSize(tile_size) => {
1140 self.frame_config.tile_size_override = tile_size;
1141 self.update_frame_builder_config();
1142
1143 return RenderBackendStatus::Continue;
1144 }
1145 DebugCommand::SetMaximumSurfaceSize(surface_size) => {
1146 self.frame_config.max_surface_override = surface_size;
1147 self.update_frame_builder_config();
1148
1149 return RenderBackendStatus::Continue;
1150 }
1151 DebugCommand::GenerateFrame => {
1152 self.prepare_for_frames();
1153
1154 let documents: Vec<DocumentId> = self.documents.keys()
1155 .cloned()
1156 .collect();
1157 for document_id in documents {
1158 self.update_document(
1159 document_id,
1160 Vec::default(),
1161 Vec::default(),
1162 Vec::default(),
1163 true,
1164 true,
1165 false,
1166 RenderReasons::empty(),
1167 None,
1168 true,
1169 frame_counter,
1170 false,
1171 None);
1172 }
1173 self.bookkeep_after_frames();
1174
1175 return RenderBackendStatus::Continue;
1176 }
1177 #[cfg(feature = "capture")]
1178 DebugCommand::SaveCapture(root, bits) => {
1179 let output = self.save_capture(root, bits);
1180 ResultMsg::DebugOutput(output)
1181 },
1182 #[cfg(feature = "capture")]
1183 DebugCommand::StartCaptureSequence(root, bits) => {
1184 self.start_capture_sequence(root, bits);
1185 return RenderBackendStatus::Continue;
1186 },
1187 #[cfg(feature = "capture")]
1188 DebugCommand::StopCaptureSequence => {
1189 self.stop_capture_sequence();
1190 return RenderBackendStatus::Continue;
1191 },
1192 #[cfg(feature = "replay")]
1193 DebugCommand::LoadCapture(path, ids, tx) => {
1194 NEXT_NAMESPACE_ID.fetch_add(1, Ordering::Relaxed);
1195 *frame_counter += 1;
1196
1197 let mut config = CaptureConfig::new(path, CaptureBits::all());
1198 if let Some((scene_id, frame_id)) = ids {
1199 config.scene_id = scene_id;
1200 config.frame_id = frame_id;
1201 }
1202
1203 self.load_capture(config);
1204
1205 for (id, doc) in &self.documents {
1206 let captured = CapturedDocument {
1207 document_id: *id,
1208 root_pipeline_id: doc.loaded_scene.root_pipeline_id,
1209 };
1210 tx.send(captured).unwrap();
1211 }
1212
1213 return RenderBackendStatus::Continue;
1216 }
1217 #[cfg(feature = "debugger")]
1218 DebugCommand::Query(ref query) => {
1219 match query.kind {
1220 DebugQueryKind::SpatialTree { .. } => {
1221 if let Some(doc) = self.documents.values().next() {
1222 let result = doc.spatial_tree.print_to_string();
1223 query.result.send(result).ok();
1224 }
1225 return RenderBackendStatus::Continue;
1226 }
1227 DebugQueryKind::CompositorView { .. } |
1228 DebugQueryKind::CompositorConfig { .. } => {
1229 ResultMsg::DebugCommand(option)
1230 }
1231 }
1232 }
1233 DebugCommand::ClearCaches(mask) => {
1234 self.resource_cache.clear(mask);
1235 return RenderBackendStatus::Continue;
1236 }
1237 DebugCommand::EnableNativeCompositor(enable) => {
1238 if let CompositorKind::Draw { .. } = self.default_compositor_kind {
1240 unreachable!();
1241 }
1242
1243 let compositor_kind = if enable {
1244 self.default_compositor_kind
1245 } else {
1246 CompositorKind::default()
1247 };
1248
1249 for (_, doc) in &mut self.documents {
1250 doc.scene.config.compositor_kind = compositor_kind;
1251 doc.frame_is_valid = false;
1252 }
1253
1254 self.frame_config.compositor_kind = compositor_kind;
1255 self.update_frame_builder_config();
1256
1257 return RenderBackendStatus::Continue;
1259 }
1260 DebugCommand::SetBatchingLookback(count) => {
1261 self.frame_config.batch_lookback_count = count as usize;
1262 self.update_frame_builder_config();
1263
1264 return RenderBackendStatus::Continue;
1265 }
1266 DebugCommand::SimulateLongSceneBuild(time_ms) => {
1267 let _ = self.scene_tx.send(SceneBuilderRequest::SimulateLongSceneBuild(time_ms));
1268 return RenderBackendStatus::Continue;
1269 }
1270 DebugCommand::SetFlags(flags) => {
1271 self.resource_cache.set_debug_flags(flags);
1272 self.gpu_cache.set_debug_flags(flags);
1273
1274 let force_invalidation = flags.contains(DebugFlags::FORCE_PICTURE_INVALIDATION);
1275 if self.frame_config.force_invalidation != force_invalidation {
1276 self.frame_config.force_invalidation = force_invalidation;
1277 self.update_frame_builder_config();
1278 }
1279
1280 let changed = self.debug_flags ^ flags;
1290 if changed.contains(DebugFlags::GPU_CACHE_DBG) {
1291 self.gpu_cache.clear();
1292 }
1293 self.debug_flags = flags;
1294
1295 ResultMsg::DebugCommand(option)
1296 }
1297 _ => ResultMsg::DebugCommand(option),
1298 };
1299 self.result_tx.send(msg).unwrap();
1300 self.notifier.wake_up(true);
1301 }
1302 ApiMsg::UpdateDocuments(transaction_msgs) => {
1303 self.prepare_transactions(
1304 transaction_msgs,
1305 frame_counter,
1306 );
1307 }
1308 ApiMsg::SceneBuilderResult(msg) => {
1309 return self.process_scene_builder_result(msg, frame_counter);
1310 }
1311 }
1312
1313 self.chunk_pool.purge_chunks(2, 3);
1318
1319 RenderBackendStatus::Continue
1320 }
1321
1322 fn process_scene_builder_result(
1323 &mut self,
1324 msg: SceneBuilderResult,
1325 frame_counter: &mut u32,
1326 ) -> RenderBackendStatus {
1327 profile_scope!("sb_msg");
1328
1329 match msg {
1330 SceneBuilderResult::Transactions(txns, result_tx) => {
1331 self.process_transaction(
1332 txns,
1333 result_tx,
1334 frame_counter,
1335 );
1336 self.bookkeep_after_frames();
1337 },
1338 #[cfg(feature = "capture")]
1339 SceneBuilderResult::CapturedTransactions(txns, capture_config, result_tx) => {
1340 if let Some(ref mut old_config) = self.capture_config {
1341 assert!(old_config.scene_id <= capture_config.scene_id);
1342 if old_config.scene_id < capture_config.scene_id {
1343 old_config.scene_id = capture_config.scene_id;
1344 old_config.frame_id = 0;
1345 }
1346 } else {
1347 self.capture_config = Some(capture_config);
1348 }
1349
1350 let built_frame = self.process_transaction(
1351 txns,
1352 result_tx,
1353 frame_counter,
1354 );
1355
1356 if built_frame {
1357 self.save_capture_sequence();
1358 }
1359
1360 self.bookkeep_after_frames();
1361 },
1362 #[cfg(feature = "capture")]
1363 SceneBuilderResult::StopCaptureSequence => {
1364 self.capture_config = None;
1365 }
1366 SceneBuilderResult::GetGlyphDimensions(request) => {
1367 let mut glyph_dimensions = Vec::with_capacity(request.glyph_indices.len());
1368 let instance_key = self.resource_cache.map_font_instance_key(request.key);
1369 if let Some(base) = self.resource_cache.get_font_instance(instance_key) {
1370 let font = FontInstance::from_base(Arc::clone(&base));
1371 for glyph_index in &request.glyph_indices {
1372 let glyph_dim = self.resource_cache.get_glyph_dimensions(&font, *glyph_index);
1373 glyph_dimensions.push(glyph_dim);
1374 }
1375 }
1376 request.sender.send(glyph_dimensions).unwrap();
1377 }
1378 SceneBuilderResult::GetGlyphIndices(request) => {
1379 let mut glyph_indices = Vec::with_capacity(request.text.len());
1380 let font_key = self.resource_cache.map_font_key(request.key);
1381 for ch in request.text.chars() {
1382 let index = self.resource_cache.get_glyph_index(font_key, ch);
1383 glyph_indices.push(index);
1384 }
1385 request.sender.send(glyph_indices).unwrap();
1386 }
1387 SceneBuilderResult::FlushComplete(tx) => {
1388 tx.send(()).ok();
1389 }
1390 SceneBuilderResult::ExternalEvent(evt) => {
1391 self.notifier.external_event(evt);
1392 }
1393 SceneBuilderResult::ClearNamespace(id) => {
1394 self.resource_cache.clear_namespace(id);
1395 self.documents.retain(|doc_id, _doc| doc_id.namespace_id != id);
1396 }
1397 SceneBuilderResult::DeleteDocument(document_id) => {
1398 self.documents.remove(&document_id);
1399 }
1400 SceneBuilderResult::SetParameter(param) => {
1401 if let Parameter::Bool(BoolParameter::Multithreading, enabled) = param {
1402 self.resource_cache.enable_multithreading(enabled);
1403 }
1404 let _ = self.result_tx.send(ResultMsg::SetParameter(param));
1405 }
1406 SceneBuilderResult::StopRenderBackend => {
1407 return RenderBackendStatus::StopRenderBackend;
1408 }
1409 SceneBuilderResult::ShutDown(sender) => {
1410 info!("Recycling stats: {:?}", self.recycler);
1411 return RenderBackendStatus::ShutDown(sender);
1412 }
1413 }
1414
1415 RenderBackendStatus::Continue
1416 }
1417
1418 fn update_frame_builder_config(&self) {
1419 self.send_backend_message(
1420 SceneBuilderRequest::SetFrameBuilderConfig(
1421 self.frame_config.clone()
1422 )
1423 );
1424 }
1425
1426 fn prepare_for_frames(&mut self) {
1427 self.gpu_cache.prepare_for_frames();
1428 }
1429
1430 fn bookkeep_after_frames(&mut self) {
1431 self.gpu_cache.bookkeep_after_frames();
1432 }
1433
1434 fn requires_frame_build(&mut self) -> bool {
1435 self.gpu_cache.requires_frame_build()
1436 }
1437
1438 fn prepare_transactions(
1439 &mut self,
1440 txns: Vec<Box<TransactionMsg>>,
1441 frame_counter: &mut u32,
1442 ) {
1443 self.prepare_for_frames();
1444 self.maybe_force_nop_documents(
1445 frame_counter,
1446 |document_id| txns.iter().any(|txn| txn.document_id == document_id));
1447
1448 let mut built_frame = false;
1449 for mut txn in txns {
1450 if txn.generate_frame.as_bool() {
1451 txn.profile.end_time(profiler::API_SEND_TIME);
1452 }
1453
1454 self.documents.get_mut(&txn.document_id).unwrap().profile.merge(&mut txn.profile);
1455
1456 built_frame |= self.update_document(
1457 txn.document_id,
1458 txn.resource_updates.take(),
1459 txn.frame_ops.take(),
1460 txn.notifications.take(),
1461 txn.generate_frame.as_bool(),
1462 txn.generate_frame.present(),
1463 txn.generate_frame.tracked(),
1464 txn.render_reasons,
1465 txn.generate_frame.id(),
1466 txn.invalidate_rendered_frame,
1467 frame_counter,
1468 false,
1469 txn.creation_time,
1470 );
1471 }
1472 if built_frame {
1473 #[cfg(feature = "capture")]
1474 self.save_capture_sequence();
1475 }
1476 self.bookkeep_after_frames();
1477 }
1478
1479 fn maybe_force_nop_documents<F>(&mut self,
1486 frame_counter: &mut u32,
1487 document_already_present: F) where
1488 F: Fn(DocumentId) -> bool {
1489 if self.requires_frame_build() {
1490 let nop_documents : Vec<DocumentId> = self.documents.keys()
1491 .cloned()
1492 .filter(|key| !document_already_present(*key))
1493 .collect();
1494 #[allow(unused_variables)]
1495 let mut built_frame = false;
1496 for &document_id in &nop_documents {
1497 built_frame |= self.update_document(
1498 document_id,
1499 Vec::default(),
1500 Vec::default(),
1501 Vec::default(),
1502 false,
1503 false,
1504 false,
1505 RenderReasons::empty(),
1506 None,
1507 false,
1508 frame_counter,
1509 false,
1510 None);
1511 }
1512 #[cfg(feature = "capture")]
1513 match built_frame {
1514 true => self.save_capture_sequence(),
1515 _ => {},
1516 }
1517 }
1518 }
1519
1520 fn update_document(
1521 &mut self,
1522 document_id: DocumentId,
1523 resource_updates: Vec<ResourceUpdate>,
1524 mut frame_ops: Vec<FrameMsg>,
1525 mut notifications: Vec<NotificationRequest>,
1526 mut render_frame: bool,
1527 mut present: bool,
1528 tracked: bool,
1529 render_reasons: RenderReasons,
1530 generated_frame_id: Option<u64>,
1531 invalidate_rendered_frame: bool,
1532 frame_counter: &mut u32,
1533 has_built_scene: bool,
1534 start_time: Option<u64>
1535 ) -> bool {
1536 let update_doc_start = zeitstempel::now();
1537
1538 let requested_frame = render_frame;
1539
1540 let requires_frame_build = self.requires_frame_build();
1541 let doc = self.documents.get_mut(&document_id).unwrap();
1542
1543 if requested_frame {
1549 if let Some(ref sampler) = self.sampler {
1550 frame_ops.append(&mut sampler.sample(document_id, generated_frame_id));
1551 }
1552 }
1553
1554 doc.has_built_scene |= has_built_scene;
1555
1556 let mut scroll = false;
1559 for frame_msg in frame_ops {
1560 let op = doc.process_frame_msg(frame_msg);
1561 scroll |= op.scroll;
1562 }
1563
1564 for update in &resource_updates {
1565 if let ResourceUpdate::UpdateImage(..) = update {
1566 doc.frame_is_valid = false;
1567 }
1568 }
1569
1570 self.resource_cache.post_scene_building_update(
1571 resource_updates,
1572 &mut doc.profile,
1573 );
1574
1575 if doc.dynamic_properties.flush_pending_updates() {
1576 doc.frame_is_valid = false;
1577 doc.hit_tester_is_valid = false;
1578 }
1579
1580 if !doc.can_render() {
1581 render_frame = false;
1585 }
1586
1587 let build_frame = (render_frame && !doc.frame_is_valid && doc.has_pixels()) ||
1593 (requires_frame_build && doc.can_render());
1594
1595 if invalidate_rendered_frame {
1599 doc.rendered_frame_is_valid = false;
1600 if doc.scene.config.compositor_kind.should_redraw_on_invalidation() {
1601 let msg = ResultMsg::ForceRedraw;
1602 self.result_tx.send(msg).unwrap();
1603 }
1604 }
1605
1606 if build_frame {
1607 if !requested_frame {
1608 present = true;
1613 }
1614
1615 if start_time.is_some() {
1616 Telemetry::record_time_to_frame_build(Duration::from_nanos(zeitstempel::now() - start_time.unwrap()));
1617 }
1618 profile_scope!("generate frame");
1619
1620 *frame_counter += 1;
1621
1622 let (pending_update, mut rendered_document) = {
1624 let timer_id = Telemetry::start_framebuild_time();
1625
1626 let frame_stats = doc.frame_stats.take();
1627
1628 let rendered_document = doc.build_frame(
1629 &mut self.resource_cache,
1630 &mut self.gpu_cache,
1631 self.debug_flags,
1632 &mut self.tile_caches,
1633 frame_stats,
1634 present,
1635 render_reasons,
1636 self.chunk_pool.clone(),
1637 );
1638
1639 debug!("generated frame for document {:?} with {} passes",
1640 document_id, rendered_document.frame.passes.len());
1641
1642 let msg = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
1643 self.result_tx.send(msg).unwrap();
1644
1645 Telemetry::stop_and_accumulate_framebuild_time(timer_id);
1646
1647 let pending_update = self.resource_cache.pending_updates();
1648 (pending_update, rendered_document)
1649 };
1650
1651 rendered_document
1653 .frame
1654 .composite_state
1655 .update_dirty_rect_validity(&doc.prev_composite_descriptor);
1656
1657 let composite_descriptor = rendered_document
1659 .frame
1660 .composite_state
1661 .descriptor
1662 .clone();
1663
1664 if !pending_update.is_nop() ||
1668 !rendered_document.frame.is_nop() ||
1669 composite_descriptor != doc.prev_composite_descriptor {
1670 doc.rendered_frame_is_valid = false;
1671 }
1672 doc.prev_composite_descriptor = composite_descriptor;
1673
1674 #[cfg(feature = "capture")]
1675 match self.capture_config {
1676 Some(ref mut config) => {
1677 config.prepare_frame();
1679
1680 if config.bits.contains(CaptureBits::FRAME) {
1681 let file_name = format!("frame-{}-{}", document_id.namespace_id.0, document_id.id);
1682 config.serialize_for_frame(&rendered_document.frame, file_name);
1683 }
1684
1685 let data_stores_name = format!("data-stores-{}-{}", document_id.namespace_id.0, document_id.id);
1686 config.serialize_for_frame(&doc.data_stores, data_stores_name);
1687
1688 let frame_spatial_tree_name = format!("frame-spatial-tree-{}-{}", document_id.namespace_id.0, document_id.id);
1689 config.serialize_for_frame::<SpatialTree, _>(&doc.spatial_tree, frame_spatial_tree_name);
1690
1691 let properties_name = format!("properties-{}-{}", document_id.namespace_id.0, document_id.id);
1692 config.serialize_for_frame(&doc.dynamic_properties, properties_name);
1693 },
1694 None => {},
1695 }
1696
1697 let update_doc_time = profiler::ns_to_ms(zeitstempel::now() - update_doc_start);
1698 rendered_document.profile.set(profiler::UPDATE_DOCUMENT_TIME, update_doc_time);
1699
1700 let msg = ResultMsg::PublishPipelineInfo(doc.updated_pipeline_info());
1701 self.result_tx.send(msg).unwrap();
1702
1703 self.frame_publish_id.advance();
1705 let msg = ResultMsg::PublishDocument(
1706 self.frame_publish_id,
1707 document_id,
1708 rendered_document,
1709 pending_update,
1710 );
1711 self.result_tx.send(msg).unwrap();
1712 } else if requested_frame {
1713 let msg = ResultMsg::PublishPipelineInfo(doc.updated_pipeline_info());
1718 self.result_tx.send(msg).unwrap();
1719 }
1720
1721 drain_filter(
1722 &mut notifications,
1723 |n| { n.when() == Checkpoint::FrameBuilt },
1724 |n| { n.notify(); },
1725 );
1726
1727 if !notifications.is_empty() {
1728 self.result_tx.send(ResultMsg::AppendNotificationRequests(notifications)).unwrap();
1729 }
1730
1731 if requested_frame {
1735 if doc.rendered_frame_is_valid {
1737 render_frame = false;
1738 } else if render_frame {
1739 doc.rendered_frame_is_valid = true;
1740 }
1741 let params = api::FrameReadyParams {
1742 present,
1743 render: render_frame,
1744 scrolled: scroll,
1745 tracked,
1746 };
1747 self.notifier.new_frame_ready(document_id, self.frame_publish_id, ¶ms);
1748 }
1749
1750 if !doc.hit_tester_is_valid {
1751 doc.rebuild_hit_tester();
1752 }
1753
1754 build_frame
1755 }
1756
1757 fn send_backend_message(&self, msg: SceneBuilderRequest) {
1758 self.scene_tx.send(msg).unwrap();
1759 }
1760
1761 fn report_memory(&mut self, tx: Sender<Box<MemoryReport>>) {
1762 let mut report = Box::new(MemoryReport::default());
1763 let ops = self.size_of_ops.as_mut().unwrap();
1764 let op = ops.size_of_op;
1765 report.gpu_cache_metadata = self.gpu_cache.size_of(ops);
1766 for doc in self.documents.values() {
1767 report.clip_stores += doc.scene.clip_store.size_of(ops);
1768 report.hit_testers += match &doc.hit_tester {
1769 Some(hit_tester) => hit_tester.size_of(ops),
1770 None => 0,
1771 };
1772
1773 doc.data_stores.report_memory(ops, &mut report)
1774 }
1775
1776 (*report) += self.resource_cache.report_memory(op);
1777 report.texture_cache_structures = self.resource_cache
1778 .texture_cache
1779 .report_memory(ops);
1780
1781 self.send_backend_message(
1785 SceneBuilderRequest::ReportMemory(report, tx)
1786 );
1787 }
1788
1789 #[cfg(feature = "capture")]
1790 fn save_capture_sequence(&mut self) {
1791 if let Some(ref mut config) = self.capture_config {
1792 let deferred = self.resource_cache.save_capture_sequence(config);
1793
1794 let backend = PlainRenderBackend {
1795 frame_config: self.frame_config.clone(),
1796 resource_sequence_id: config.resource_id,
1797 documents: self.documents
1798 .iter()
1799 .map(|(id, doc)| (*id, doc.view))
1800 .collect(),
1801 };
1802 config.serialize_for_frame(&backend, "backend");
1803
1804 if !deferred.is_empty() {
1805 let msg = ResultMsg::DebugOutput(DebugOutput::SaveCapture(config.clone(), deferred));
1806 self.result_tx.send(msg).unwrap();
1807 }
1808 }
1809 }
1810}
1811
1812impl RenderBackend {
1813 #[cfg(feature = "capture")]
1814 fn save_capture(
1816 &mut self,
1817 root: PathBuf,
1818 bits: CaptureBits,
1819 ) -> DebugOutput {
1820 use std::fs;
1821 use crate::render_task_graph::dump_render_tasks_as_svg;
1822
1823 debug!("capture: saving {:?}", root);
1824 if !root.is_dir() {
1825 if let Err(e) = fs::create_dir_all(&root) {
1826 panic!("Unable to create capture dir: {:?}", e);
1827 }
1828 }
1829 let config = CaptureConfig::new(root, bits);
1830
1831 if config.bits.contains(CaptureBits::FRAME) {
1832 self.prepare_for_frames();
1833 }
1834
1835 for (&id, doc) in &mut self.documents {
1836 debug!("\tdocument {:?}", id);
1837 if config.bits.contains(CaptureBits::FRAME) {
1838 let force_invalidation = std::mem::replace(&mut doc.scene.config.force_invalidation, true);
1840 let rendered_document = doc.build_frame(
1841 &mut self.resource_cache,
1842 &mut self.gpu_cache,
1843 self.debug_flags,
1844 &mut self.tile_caches,
1845 None,
1846 true,
1847 RenderReasons::empty(),
1848 self.chunk_pool.clone(),
1849 );
1850
1851 doc.scene.config.force_invalidation = force_invalidation;
1852
1853 let msg_update_gpu_cache = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
1857 self.result_tx.send(msg_update_gpu_cache).unwrap();
1858 let file_name = format!("frame-{}-{}", id.namespace_id.0, id.id);
1862 config.serialize_for_frame(&rendered_document.frame, file_name);
1863 let file_name = format!("spatial-{}-{}", id.namespace_id.0, id.id);
1864 config.serialize_tree_for_frame(&doc.spatial_tree, file_name);
1865 let file_name = format!("built-primitives-{}-{}", id.namespace_id.0, id.id);
1866 config.serialize_for_frame(&doc.scene.prim_store, file_name);
1867 let file_name = format!("built-clips-{}-{}", id.namespace_id.0, id.id);
1868 config.serialize_for_frame(&doc.scene.clip_store, file_name);
1869 let file_name = format!("scratch-{}-{}", id.namespace_id.0, id.id);
1870 config.serialize_for_frame(&doc.scratch.primitive, file_name);
1871 let file_name = format!("render-tasks-{}-{}.svg", id.namespace_id.0, id.id);
1872 let mut render_tasks_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1873 .expect("Failed to open the SVG file.");
1874 dump_render_tasks_as_svg(
1875 &rendered_document.frame.render_tasks,
1876 &mut render_tasks_file
1877 ).unwrap();
1878
1879 let file_name = format!("texture-cache-color-linear-{}-{}.svg", id.namespace_id.0, id.id);
1880 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1881 .expect("Failed to open the SVG file.");
1882 self.resource_cache.texture_cache.dump_color8_linear_as_svg(&mut texture_file).unwrap();
1883
1884 let file_name = format!("texture-cache-color8-glyphs-{}-{}.svg", id.namespace_id.0, id.id);
1885 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1886 .expect("Failed to open the SVG file.");
1887 self.resource_cache.texture_cache.dump_color8_glyphs_as_svg(&mut texture_file).unwrap();
1888
1889 let file_name = format!("texture-cache-alpha8-glyphs-{}-{}.svg", id.namespace_id.0, id.id);
1890 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1891 .expect("Failed to open the SVG file.");
1892 self.resource_cache.texture_cache.dump_alpha8_glyphs_as_svg(&mut texture_file).unwrap();
1893
1894 let file_name = format!("texture-cache-alpha8-linear-{}-{}.svg", id.namespace_id.0, id.id);
1895 let mut texture_file = fs::File::create(&config.file_path_for_frame(file_name, "svg"))
1896 .expect("Failed to open the SVG file.");
1897 self.resource_cache.texture_cache.dump_alpha8_linear_as_svg(&mut texture_file).unwrap();
1898 }
1899
1900 let data_stores_name = format!("data-stores-{}-{}", id.namespace_id.0, id.id);
1901 config.serialize_for_frame(&doc.data_stores, data_stores_name);
1902
1903 let frame_spatial_tree_name = format!("frame-spatial-tree-{}-{}", id.namespace_id.0, id.id);
1904 config.serialize_for_frame::<SpatialTree, _>(&doc.spatial_tree, frame_spatial_tree_name);
1905
1906 let properties_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
1907 config.serialize_for_frame(&doc.dynamic_properties, properties_name);
1908 }
1909
1910 if config.bits.contains(CaptureBits::FRAME) {
1911 assert!(!self.requires_frame_build(), "Caches were cleared during a capture.");
1915 self.bookkeep_after_frames();
1916 }
1917
1918 debug!("\tscene builder");
1919 self.send_backend_message(
1920 SceneBuilderRequest::SaveScene(config.clone())
1921 );
1922
1923 debug!("\tresource cache");
1924 let (resources, deferred) = self.resource_cache.save_capture(&config.root);
1925
1926 info!("\tbackend");
1927 let backend = PlainRenderBackend {
1928 frame_config: self.frame_config.clone(),
1929 resource_sequence_id: 0,
1930 documents: self.documents
1931 .iter()
1932 .map(|(id, doc)| (*id, doc.view))
1933 .collect(),
1934 };
1935
1936 config.serialize_for_frame(&backend, "backend");
1937 config.serialize_for_frame(&resources, "plain-resources");
1938
1939 if config.bits.contains(CaptureBits::FRAME) {
1940 let msg_update_resources = ResultMsg::UpdateResources {
1941 resource_updates: self.resource_cache.pending_updates(),
1942 memory_pressure: false,
1943 };
1944 self.result_tx.send(msg_update_resources).unwrap();
1945 info!("\tresource cache");
1947 let caches = self.resource_cache.save_caches(&config.root);
1948 config.serialize_for_resource(&caches, "resource_cache");
1949 info!("\tgpu cache");
1950 config.serialize_for_resource(&self.gpu_cache, "gpu_cache");
1951 }
1952
1953 DebugOutput::SaveCapture(config, deferred)
1954 }
1955
1956 #[cfg(feature = "capture")]
1957 fn start_capture_sequence(
1958 &mut self,
1959 root: PathBuf,
1960 bits: CaptureBits,
1961 ) {
1962 self.send_backend_message(
1963 SceneBuilderRequest::StartCaptureSequence(CaptureConfig::new(root, bits))
1964 );
1965 }
1966
1967 #[cfg(feature = "capture")]
1968 fn stop_capture_sequence(
1969 &mut self,
1970 ) {
1971 self.send_backend_message(
1972 SceneBuilderRequest::StopCaptureSequence
1973 );
1974 }
1975
1976 #[cfg(feature = "replay")]
1977 fn load_capture(
1978 &mut self,
1979 mut config: CaptureConfig,
1980 ) {
1981 debug!("capture: loading {:?}", config.frame_root());
1982 let backend = config.deserialize_for_frame::<PlainRenderBackend, _>("backend")
1983 .expect("Unable to open backend.ron");
1984
1985 let first_load = backend.resource_sequence_id == 0;
1988 if self.loaded_resource_sequence_id != backend.resource_sequence_id || first_load {
1989 self.documents.clear();
2002
2003 config.resource_id = backend.resource_sequence_id;
2004 self.loaded_resource_sequence_id = backend.resource_sequence_id;
2005
2006 let plain_resources = config.deserialize_for_resource::<PlainResources, _>("plain-resources")
2007 .expect("Unable to open plain-resources.ron");
2008 let caches_maybe = config.deserialize_for_resource::<PlainCacheOwn, _>("resource_cache");
2009
2010 let plain_externals = self.resource_cache.load_capture(
2015 plain_resources,
2016 caches_maybe,
2017 &config,
2018 );
2019
2020 let msg_load = ResultMsg::DebugOutput(
2021 DebugOutput::LoadCapture(config.clone(), plain_externals)
2022 );
2023 self.result_tx.send(msg_load).unwrap();
2024
2025 self.gpu_cache = match config.deserialize_for_resource::<GpuCache, _>("gpu_cache") {
2026 Some(gpu_cache) => gpu_cache,
2027 None => GpuCache::new(),
2028 };
2029 }
2030
2031 self.frame_config = backend.frame_config;
2032
2033 let mut scenes_to_build = Vec::new();
2034
2035 for (id, view) in backend.documents {
2036 debug!("\tdocument {:?}", id);
2037 let scene_name = format!("scene-{}-{}", id.namespace_id.0, id.id);
2038 let scene = config.deserialize_for_scene::<Scene, _>(&scene_name)
2039 .expect(&format!("Unable to open {}.ron", scene_name));
2040
2041 let scene_spatial_tree_name = format!("scene-spatial-tree-{}-{}", id.namespace_id.0, id.id);
2042 let scene_spatial_tree = config.deserialize_for_scene::<SceneSpatialTree, _>(&scene_spatial_tree_name)
2043 .expect(&format!("Unable to open {}.ron", scene_spatial_tree_name));
2044
2045 let interners_name = format!("interners-{}-{}", id.namespace_id.0, id.id);
2046 let interners = config.deserialize_for_scene::<Interners, _>(&interners_name)
2047 .expect(&format!("Unable to open {}.ron", interners_name));
2048
2049 let data_stores_name = format!("data-stores-{}-{}", id.namespace_id.0, id.id);
2050 let data_stores = config.deserialize_for_frame::<DataStores, _>(&data_stores_name)
2051 .expect(&format!("Unable to open {}.ron", data_stores_name));
2052
2053 let properties_name = format!("properties-{}-{}", id.namespace_id.0, id.id);
2054 let properties = config.deserialize_for_frame::<SceneProperties, _>(&properties_name)
2055 .expect(&format!("Unable to open {}.ron", properties_name));
2056
2057 let frame_spatial_tree_name = format!("frame-spatial-tree-{}-{}", id.namespace_id.0, id.id);
2058 let frame_spatial_tree = config.deserialize_for_frame::<SpatialTree, _>(&frame_spatial_tree_name)
2059 .expect(&format!("Unable to open {}.ron", frame_spatial_tree_name));
2060
2061 match self.documents.entry(id) {
2065 Occupied(entry) => {
2066 let doc = entry.into_mut();
2067 doc.view = view;
2068 doc.loaded_scene = scene.clone();
2069 doc.data_stores = data_stores;
2070 doc.spatial_tree = frame_spatial_tree;
2071 doc.dynamic_properties = properties;
2072 doc.frame_is_valid = false;
2073 doc.rendered_frame_is_valid = false;
2074 doc.has_built_scene = false;
2075 doc.hit_tester_is_valid = false;
2076 }
2077 Vacant(entry) => {
2078 let doc = Document {
2079 id,
2080 scene: BuiltScene::empty(),
2081 removed_pipelines: Vec::new(),
2082 view,
2083 stamp: FrameStamp::first(id),
2084 frame_builder: FrameBuilder::new(),
2085 dynamic_properties: properties,
2086 hit_tester: None,
2087 shared_hit_tester: Arc::new(SharedHitTester::new()),
2088 frame_is_valid: false,
2089 hit_tester_is_valid: false,
2090 rendered_frame_is_valid: false,
2091 has_built_scene: false,
2092 data_stores,
2093 scratch: ScratchBuffer::default(),
2094 spatial_tree: frame_spatial_tree,
2095 minimap_data: FastHashMap::default(),
2096 loaded_scene: scene.clone(),
2097 prev_composite_descriptor: CompositeDescriptor::empty(),
2098 dirty_rects_are_valid: false,
2099 profile: TransactionProfile::new(),
2100 rg_builder: RenderTaskGraphBuilder::new(),
2101 frame_stats: None,
2102 };
2103 entry.insert(doc);
2104 }
2105 };
2106
2107 let frame_name = format!("frame-{}-{}", id.namespace_id.0, id.id);
2108 let frame = config.deserialize_for_frame::<Frame, _>(frame_name);
2109 let build_frame = match frame {
2110 Some(frame) => {
2111 info!("\tloaded a built frame with {} passes", frame.passes.len());
2112
2113 let msg_update = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
2114 self.result_tx.send(msg_update).unwrap();
2115
2116 self.frame_publish_id.advance();
2117 let msg_publish = ResultMsg::PublishDocument(
2118 self.frame_publish_id,
2119 id,
2120 RenderedDocument {
2121 frame,
2122 profile: TransactionProfile::new(),
2123 render_reasons: RenderReasons::empty(),
2124 frame_stats: None,
2125 },
2126 self.resource_cache.pending_updates(),
2127 );
2128 self.result_tx.send(msg_publish).unwrap();
2129
2130 let params = api::FrameReadyParams {
2131 present: true,
2132 render: true,
2133 scrolled: false,
2134 tracked: false,
2135 };
2136 self.notifier.new_frame_ready(id, self.frame_publish_id, ¶ms);
2137
2138 false
2141 }
2142 None => true,
2143 };
2144
2145 scenes_to_build.push(LoadScene {
2146 document_id: id,
2147 scene,
2148 view: view.scene.clone(),
2149 config: self.frame_config.clone(),
2150 fonts: self.resource_cache.get_fonts(),
2151 build_frame,
2152 interners,
2153 spatial_tree: scene_spatial_tree,
2154 });
2155 }
2156
2157 if !scenes_to_build.is_empty() {
2158 self.send_backend_message(
2159 SceneBuilderRequest::LoadScenes(scenes_to_build)
2160 );
2161 }
2162 }
2163}