Skip to main content

grafo/renderer/
construction.rs

1use super::*;
2use tracing::{info, warn};
3
4fn pick_surface_format(surface_formats: &[wgpu::TextureFormat]) -> wgpu::TextureFormat {
5    const PREFERRED_SURFACE_FORMATS: [wgpu::TextureFormat; 4] = [
6        wgpu::TextureFormat::Bgra8UnormSrgb,
7        wgpu::TextureFormat::Rgba8UnormSrgb,
8        wgpu::TextureFormat::Bgra8Unorm,
9        wgpu::TextureFormat::Rgba8Unorm,
10    ];
11
12    PREFERRED_SURFACE_FORMATS
13        .into_iter()
14        .find(|surface_format| surface_formats.contains(surface_format))
15        .unwrap_or_else(|| {
16            surface_formats
17                .first()
18                .copied()
19                .unwrap_or(wgpu::TextureFormat::Bgra8UnormSrgb)
20        })
21}
22
23fn pick_alpha_mode(alpha_modes: &[CompositeAlphaMode], transparent: bool) -> CompositeAlphaMode {
24    if transparent && alpha_modes.contains(&CompositeAlphaMode::PreMultiplied) {
25        info!("Using PreMultiplied alpha mode for transparency");
26        CompositeAlphaMode::PreMultiplied
27    } else if transparent && alpha_modes.contains(&CompositeAlphaMode::PostMultiplied) {
28        info!("Using PostMultiplied alpha mode for transparency");
29        CompositeAlphaMode::PostMultiplied
30    } else {
31        if transparent {
32            warn!(
33                "Transparency requested but no suitable alpha mode available, falling back to the surface default"
34            );
35        }
36
37        alpha_modes
38            .iter()
39            .copied()
40            .find(|alpha_mode| matches!(alpha_mode, CompositeAlphaMode::Opaque))
41            .unwrap_or_else(|| {
42                alpha_modes
43                    .first()
44                    .copied()
45                    .unwrap_or(CompositeAlphaMode::Opaque)
46            })
47    }
48}
49
50/// Errors that can occur when creating a [`Renderer`] via
51/// [`Renderer::try_new_headless`].
52#[derive(Debug, thiserror::Error)]
53pub enum RendererCreationError {
54    /// The provided `scale_factor` is not usable (must be finite and positive).
55    #[error("Invalid scale factor: {0} (must be finite and > 0.0)")]
56    InvalidScaleFactor(f64),
57    /// No suitable GPU adapter was found.
58    #[error("No suitable GPU adapter available: {0}")]
59    AdapterNotAvailable(#[from] wgpu::RequestAdapterError),
60    /// The GPU device could not be created.
61    #[error("GPU device creation failed: {0}")]
62    DeviceCreationFailed(#[from] wgpu::RequestDeviceError),
63}
64
65impl<'a> Renderer<'a> {
66    pub async fn new(
67        window: impl Into<SurfaceTarget<'static>>,
68        physical_size: (u32, u32),
69        scale_factor: f64,
70        vsync: bool,
71        transparent: bool,
72        msaa_samples: u32,
73    ) -> Self {
74        let size = physical_size;
75
76        let instance = wgpu::Instance::new(&InstanceDescriptor::default());
77        let surface = instance
78            .create_surface(window)
79            .expect("Failed to create surface");
80
81        let adapter = instance
82            .request_adapter(&wgpu::RequestAdapterOptions {
83                power_preference: wgpu::PowerPreference::HighPerformance,
84                compatible_surface: Some(&surface),
85                force_fallback_adapter: false,
86            })
87            .await
88            .unwrap();
89
90        let (device, queue) = adapter
91            .request_device(&wgpu::DeviceDescriptor {
92                label: None,
93                #[cfg(feature = "performance_measurement")]
94                required_features: wgpu::Features::TIMESTAMP_QUERY
95                    | wgpu::Features::DEPTH32FLOAT_STENCIL8,
96                #[cfg(not(feature = "performance_measurement"))]
97                required_features: wgpu::Features::empty(),
98                required_limits: wgpu::Limits::default(),
99                memory_hints: Default::default(),
100                trace: Default::default(),
101            })
102            .await
103            .unwrap();
104
105        let surface_caps = surface.get_capabilities(&adapter);
106        let swapchain_format = pick_surface_format(&surface_caps.formats);
107        let alpha_mode = pick_alpha_mode(&surface_caps.alpha_modes, transparent);
108
109        let config = wgpu::SurfaceConfiguration {
110            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
111            format: swapchain_format,
112            width: size.0,
113            height: size.1,
114            present_mode: if vsync {
115                wgpu::PresentMode::AutoVsync
116            } else {
117                wgpu::PresentMode::AutoNoVsync
118            },
119            desired_maximum_frame_latency: 2,
120            alpha_mode,
121            view_formats: vec![],
122        };
123        surface.configure(&device, &config);
124
125        let msaa_sample_count = Self::validate_sample_count_static(msaa_samples);
126
127        Self::build_from_device(
128            instance,
129            Some(surface),
130            device,
131            queue,
132            config,
133            size,
134            scale_factor,
135            msaa_sample_count,
136        )
137        .expect("Failed to build renderer from device")
138    }
139
140    /// Shared constructor: takes the wgpu primitives produced by `new()` or
141    /// `new_headless()` and builds the full `Renderer`.
142    #[allow(clippy::too_many_arguments)]
143    fn build_from_device(
144        instance: wgpu::Instance,
145        surface: Option<wgpu::Surface<'a>>,
146        device: wgpu::Device,
147        queue: wgpu::Queue,
148        config: wgpu::SurfaceConfiguration,
149        physical_size: (u32, u32),
150        scale_factor: f64,
151        msaa_sample_count: u32,
152    ) -> Result<Self, RendererCreationError> {
153        if !scale_factor.is_finite() || scale_factor <= 0.0 {
154            return Err(RendererCreationError::InvalidScaleFactor(scale_factor));
155        }
156
157        let canvas_logical_size = to_logical(physical_size, scale_factor);
158
159        let (
160            and_uniforms,
161            and_uniform_buffer,
162            and_bind_group,
163            and_texture_bgl_layer0,
164            and_texture_bgl_layer1,
165            and_pipeline,
166        ) = create_pipeline(
167            canvas_logical_size,
168            scale_factor,
169            Self::DEFAULT_FRINGE_WIDTH,
170            &device,
171            &config,
172            PipelineType::EqualIncrementStencil,
173            msaa_sample_count,
174        );
175
176        let (
177            decrementing_uniforms,
178            decrementing_uniform_buffer,
179            decrementing_bind_group,
180            _shape_texture_bind_group_layout_init0,
181            _shape_texture_bind_group_layout_init1,
182            decrementing_pipeline,
183        ) = create_pipeline(
184            canvas_logical_size,
185            scale_factor,
186            Self::DEFAULT_FRINGE_WIDTH,
187            &device,
188            &config,
189            PipelineType::EqualDecrementStencil,
190            msaa_sample_count,
191        );
192
193        let leaf_draw_pipeline = crate::pipeline::create_stencil_keep_color_pipeline(
194            &device,
195            config.format,
196            msaa_sample_count,
197            &and_pipeline.get_bind_group_layout(0),
198            &and_texture_bgl_layer0,
199            &and_texture_bgl_layer1,
200        );
201
202        let device = Arc::new(device);
203        let queue = Arc::new(queue);
204
205        let texture_manager = TextureManager::new(device.clone(), queue.clone());
206
207        let (default_shape_texture_bind_group_layer0, shape_texture_bind_group_layout_layer0) =
208            Self::create_default_shape_texture_bind_group(&device, &queue, &and_texture_bgl_layer0);
209        let (default_shape_texture_bind_group_layer1, shape_texture_bind_group_layout_layer1) =
210            Self::create_default_shape_texture_bind_group(&device, &queue, &and_texture_bgl_layer1);
211
212        let mut renderer = Self {
213            instance,
214            surface,
215            device,
216            queue,
217            config,
218            physical_size,
219            scale_factor,
220            fringe_width: Self::DEFAULT_FRINGE_WIDTH,
221            tessellator: FillTessellator::new(),
222            texture_manager,
223            buffers_pool_manager: PoolManager::new(
224                NonZeroUsize::new(MAX_CACHED_SHAPES).expect("Cache size to be greater than 0"),
225            ),
226            and_pipeline: Arc::new(and_pipeline),
227            and_uniforms,
228            and_uniform_buffer,
229            and_bind_group,
230            shape_texture_bind_group_layout_background: Arc::new(
231                shape_texture_bind_group_layout_layer0,
232            ),
233            shape_texture_bind_group_layout_foreground: Arc::new(
234                shape_texture_bind_group_layout_layer1,
235            ),
236            shape_texture_layout_epoch: 0,
237            default_shape_texture_bind_groups: [
238                Arc::new(default_shape_texture_bind_group_layer0),
239                Arc::new(default_shape_texture_bind_group_layer1),
240            ],
241            decrementing_pipeline: Arc::new(decrementing_pipeline),
242            decrementing_uniforms,
243            decrementing_uniform_buffer,
244            decrementing_bind_group,
245            draw_tree: easy_tree::Tree::new(),
246            metadata_to_clips: HashMap::new(),
247            temp_vertices: Vec::new(),
248            temp_indices: Vec::new(),
249            geometry_dedup_map: HashMap::new(),
250            temp_instance_transforms: Vec::new(),
251            temp_instance_colors: Vec::new(),
252            temp_instance_metadata: Vec::new(),
253            aggregated_vertex_buffer: None,
254            aggregated_index_buffer: None,
255            aggregated_instance_transform_buffer: None,
256            aggregated_instance_color_buffer: None,
257            aggregated_instance_metadata_buffer: None,
258            identity_instance_transform_buffer: None,
259            identity_instance_color_buffer: None,
260            identity_instance_metadata_buffer: None,
261            shape_cache: HashMap::new(),
262            argb_cs_bgl: None,
263            argb_cs_pipeline: None,
264            argb_swizzle_bind_group: None,
265            argb_params_buffer: None,
266            argb_input_buffer: None,
267            argb_output_storage_buffer: None,
268            argb_readback_buffer: None,
269            argb_input_buffer_size: 0,
270            argb_output_buffer_size: 0,
271            argb_cached_width: 0,
272            argb_cached_height: 0,
273            argb_offscreen_texture: None,
274            rtb_offscreen_texture: None,
275            rtb_readback_buffer: None,
276            rtb_cached_width: 0,
277            rtb_cached_height: 0,
278            msaa_sample_count,
279            msaa_color_texture: None,
280            msaa_color_texture_view: None,
281            depth_stencil_texture: None,
282            depth_stencil_view: None,
283            loaded_effects: HashMap::new(),
284            group_effects: HashMap::new(),
285            backdrop_effects: HashMap::new(),
286            offscreen_texture_pool: OffscreenTexturePool::new(),
287            composite_pipeline: None,
288            composite_bgl: None,
289            effect_sampler: None,
290            backdrop_snapshot_texture: None,
291            backdrop_snapshot_view: None,
292            stencil_only_pipeline: None,
293            backdrop_color_pipeline: None,
294            leaf_draw_pipeline: Arc::new(leaf_draw_pipeline),
295            #[cfg(feature = "render_metrics")]
296            render_loop_metrics_tracker: RenderLoopMetricsTracker::default(),
297            #[cfg(feature = "render_metrics")]
298            last_phase_timings: Default::default(),
299            #[cfg(feature = "render_metrics")]
300            last_pipeline_switch_counts: Default::default(),
301            scratch: RendererScratch::new(),
302        };
303
304        renderer.recreate_msaa_texture();
305        renderer.recreate_depth_stencil_texture();
306        Ok(renderer)
307    }
308
309    pub fn print_memory_usage_info(&self) {
310        println!("=== Memory Usage Info ===");
311
312        println!("Cached shapes: {}", self.shape_cache.len());
313        println!("Draw tree size: {}", self.draw_tree.len());
314        println!(
315            "Metadata to clips mappings: {}",
316            self.metadata_to_clips.len()
317        );
318
319        println!("\n--- Temporary Vectors ---");
320        println!(
321            "Temp vertices: {} items, {} capacity, ~{} bytes",
322            self.temp_vertices.len(),
323            self.temp_vertices.capacity(),
324            self.temp_vertices.capacity() * std::mem::size_of::<crate::vertex::CustomVertex>()
325        );
326        println!(
327            "Temp indices: {} items, {} capacity, ~{} bytes",
328            self.temp_indices.len(),
329            self.temp_indices.capacity(),
330            self.temp_indices.capacity() * std::mem::size_of::<u16>()
331        );
332        println!(
333            "Temp instance transforms: {} items, {} capacity, ~{} bytes",
334            self.temp_instance_transforms.len(),
335            self.temp_instance_transforms.capacity(),
336            self.temp_instance_transforms.capacity() * std::mem::size_of::<InstanceTransform>()
337        );
338        println!(
339            "Temp instance colors: {} items, {} capacity, ~{} bytes",
340            self.temp_instance_colors.len(),
341            self.temp_instance_colors.capacity(),
342            self.temp_instance_colors.capacity() * std::mem::size_of::<InstanceColor>()
343        );
344        println!(
345            "Temp instance metadata: {} items, {} capacity, ~{} bytes",
346            self.temp_instance_metadata.len(),
347            self.temp_instance_metadata.capacity(),
348            self.temp_instance_metadata.capacity() * std::mem::size_of::<InstanceMetadata>()
349        );
350
351        println!("\n--- GPU Buffers ---");
352        if let Some(buf) = &self.aggregated_vertex_buffer {
353            println!("Aggregated vertex buffer: {} bytes", buf.size());
354        }
355        if let Some(buf) = &self.aggregated_index_buffer {
356            println!("Aggregated index buffer: {} bytes", buf.size());
357        }
358        if let Some(buf) = &self.aggregated_instance_transform_buffer {
359            println!("Aggregated instance transform buffer: {} bytes", buf.size());
360        }
361        if let Some(buf) = &self.aggregated_instance_color_buffer {
362            println!("Aggregated instance color buffer: {} bytes", buf.size());
363        }
364        if let Some(buf) = &self.aggregated_instance_metadata_buffer {
365            println!("Aggregated instance metadata buffer: {} bytes", buf.size());
366        }
367        if let Some(buf) = &self.identity_instance_transform_buffer {
368            println!("Identity instance transform buffer: {} bytes", buf.size());
369        }
370        if let Some(buf) = &self.identity_instance_color_buffer {
371            println!("Identity instance color buffer: {} bytes", buf.size());
372        }
373        if let Some(buf) = &self.identity_instance_metadata_buffer {
374            println!("Identity instance metadata buffer: {} bytes", buf.size());
375        }
376
377        println!("\n--- ARGB Compute Buffers ---");
378        if let Some(buf) = &self.argb_input_buffer {
379            println!(
380                "ARGB input buffer: {} bytes (cached size: {})",
381                buf.size(),
382                self.argb_input_buffer_size
383            );
384        }
385        if let Some(buf) = &self.argb_output_storage_buffer {
386            println!(
387                "ARGB output storage buffer: {} bytes (cached size: {})",
388                buf.size(),
389                self.argb_output_buffer_size
390            );
391        }
392        if let Some(buf) = &self.argb_readback_buffer {
393            println!("ARGB readback buffer: {} bytes", buf.size());
394        }
395        if let Some(buf) = &self.argb_params_buffer {
396            println!("ARGB params buffer: {} bytes", buf.size());
397        }
398        if let Some(tex) = &self.argb_offscreen_texture {
399            let size = tex.size();
400            println!(
401                "ARGB offscreen texture: {}x{} (cached: {}x{})",
402                size.width, size.height, self.argb_cached_width, self.argb_cached_height
403            );
404        }
405
406        println!("\n--- Render-to-Buffer Caches ---");
407        if let Some(tex) = &self.rtb_offscreen_texture {
408            let size = tex.size();
409            println!(
410                "RTB offscreen texture: {}x{} (cached: {}x{})",
411                size.width, size.height, self.rtb_cached_width, self.rtb_cached_height
412            );
413        }
414        if let Some(buf) = &self.rtb_readback_buffer {
415            println!("RTB readback buffer: {} bytes", buf.size());
416        }
417
418        println!("\n--- Uniform Buffers ---");
419        println!(
420            "AND uniform buffer: {} bytes",
421            self.and_uniform_buffer.size()
422        );
423        println!(
424            "Decrementing uniform buffer: {} bytes",
425            self.decrementing_uniform_buffer.size()
426        );
427
428        println!("\n--- Texture Manager ---");
429        println!("{:?}", self.texture_manager.size());
430
431        println!("\n--- Buffer Pool Manager ---");
432        self.buffers_pool_manager.print_sizes();
433
434        println!("=========================");
435    }
436
437    fn create_default_shape_texture_bind_group(
438        device: &Arc<wgpu::Device>,
439        queue: &Arc<wgpu::Queue>,
440        shape_texture_bind_group_layout: &wgpu::BindGroupLayout,
441    ) -> (wgpu::BindGroup, wgpu::BindGroupLayout) {
442        let texture = device.create_texture(&wgpu::TextureDescriptor {
443            label: Some("default_transparent_texture"),
444            size: wgpu::Extent3d {
445                width: 1,
446                height: 1,
447                depth_or_array_layers: 1,
448            },
449            mip_level_count: 1,
450            sample_count: 1,
451            dimension: wgpu::TextureDimension::D2,
452            format: wgpu::TextureFormat::Rgba8UnormSrgb,
453            usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
454            view_formats: &[],
455        });
456        let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
457        let transparent: [u8; 4] = [0, 0, 0, 0];
458        queue.write_texture(
459            wgpu::TexelCopyTextureInfo {
460                texture: &texture,
461                mip_level: 0,
462                origin: wgpu::Origin3d::ZERO,
463                aspect: wgpu::TextureAspect::All,
464            },
465            &transparent,
466            wgpu::TexelCopyBufferLayout {
467                offset: 0,
468                bytes_per_row: Some(4),
469                rows_per_image: Some(1),
470            },
471            wgpu::Extent3d {
472                width: 1,
473                height: 1,
474                depth_or_array_layers: 1,
475            },
476        );
477
478        let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
479            address_mode_u: wgpu::AddressMode::ClampToEdge,
480            address_mode_v: wgpu::AddressMode::ClampToEdge,
481            address_mode_w: wgpu::AddressMode::ClampToEdge,
482            mag_filter: wgpu::FilterMode::Linear,
483            min_filter: wgpu::FilterMode::Linear,
484            mipmap_filter: wgpu::FilterMode::Linear,
485            ..Default::default()
486        });
487
488        let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
489            layout: shape_texture_bind_group_layout,
490            entries: &[
491                wgpu::BindGroupEntry {
492                    binding: 0,
493                    resource: wgpu::BindingResource::TextureView(&view),
494                },
495                wgpu::BindGroupEntry {
496                    binding: 1,
497                    resource: wgpu::BindingResource::Sampler(&sampler),
498                },
499            ],
500            label: Some("default_shape_texture_bind_group_transparent"),
501        });
502
503        (bind_group, shape_texture_bind_group_layout.clone())
504    }
505
506    pub async fn new_transparent(
507        window: impl Into<SurfaceTarget<'static>>,
508        physical_size: (u32, u32),
509        scale_factor: f64,
510        vsync: bool,
511        msaa_samples: u32,
512    ) -> Self {
513        Self::new(
514            window,
515            physical_size,
516            scale_factor,
517            vsync,
518            true,
519            msaa_samples,
520        )
521        .await
522    }
523
524    /// Creates a headless renderer without a window surface.
525    ///
526    /// Use `render_to_buffer()` or `render_to_argb32()` to read back rendered
527    /// pixels. Calling `render()` on a headless renderer will panic.
528    ///
529    /// Returns an error if no suitable GPU adapter is available, the device
530    /// cannot be created, or the `scale_factor` is invalid.
531    pub async fn try_new_headless(
532        physical_size: (u32, u32),
533        scale_factor: f64,
534    ) -> Result<Self, RendererCreationError> {
535        let size = physical_size;
536
537        let instance = wgpu::Instance::new(&InstanceDescriptor::default());
538
539        let adapter = instance
540            .request_adapter(&wgpu::RequestAdapterOptions {
541                power_preference: wgpu::PowerPreference::HighPerformance,
542                compatible_surface: None,
543                force_fallback_adapter: false,
544            })
545            .await?;
546
547        let (device, queue) = adapter
548            .request_device(&wgpu::DeviceDescriptor {
549                label: None,
550                #[cfg(feature = "performance_measurement")]
551                required_features: wgpu::Features::TIMESTAMP_QUERY
552                    | wgpu::Features::DEPTH32FLOAT_STENCIL8,
553                #[cfg(not(feature = "performance_measurement"))]
554                required_features: wgpu::Features::empty(),
555                required_limits: wgpu::Limits::default(),
556                memory_hints: Default::default(),
557                trace: Default::default(),
558            })
559            .await?;
560
561        let swapchain_format = wgpu::TextureFormat::Bgra8UnormSrgb;
562
563        let config = wgpu::SurfaceConfiguration {
564            usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC,
565            format: swapchain_format,
566            width: size.0,
567            height: size.1,
568            present_mode: wgpu::PresentMode::AutoVsync,
569            desired_maximum_frame_latency: 2,
570            alpha_mode: CompositeAlphaMode::Opaque,
571            view_formats: vec![],
572        };
573
574        let msaa_sample_count = 1;
575
576        Self::build_from_device(
577            instance,
578            None,
579            device,
580            queue,
581            config,
582            size,
583            scale_factor,
584            msaa_sample_count,
585        )
586    }
587
588    /// Creates a headless renderer without a window surface, panicking on
589    /// any error from [`Self::try_new_headless`] (e.g. no suitable GPU adapter,
590    /// invalid scale factor, device/queue creation failure).
591    ///
592    /// Use `render_to_buffer()` or `render_to_argb32()` to read back rendered
593    /// pixels. Calling `render()` on a headless renderer will panic.
594    ///
595    /// For a non-panicking alternative (e.g. in tests), use
596    /// [`Self::try_new_headless`] instead.
597    pub async fn new_headless(physical_size: (u32, u32), scale_factor: f64) -> Self {
598        Self::try_new_headless(physical_size, scale_factor)
599            .await
600            .expect("Failed to create headless renderer")
601    }
602
603    pub(super) fn recreate_pipelines(&mut self) {
604        let canvas_logical_size = to_logical(self.physical_size, self.scale_factor);
605
606        let (
607            and_uniforms,
608            and_uniform_buffer,
609            and_bind_group,
610            and_texture_bgl_layer0,
611            and_texture_bgl_layer1,
612            and_pipeline,
613        ) = create_pipeline(
614            canvas_logical_size,
615            self.scale_factor,
616            self.fringe_width,
617            &self.device,
618            &self.config,
619            PipelineType::EqualIncrementStencil,
620            self.msaa_sample_count,
621        );
622
623        let (
624            decrementing_uniforms,
625            decrementing_uniform_buffer,
626            decrementing_bind_group,
627            _,
628            _,
629            decrementing_pipeline,
630        ) = create_pipeline(
631            canvas_logical_size,
632            self.scale_factor,
633            self.fringe_width,
634            &self.device,
635            &self.config,
636            PipelineType::EqualDecrementStencil,
637            self.msaa_sample_count,
638        );
639
640        self.and_pipeline = Arc::new(and_pipeline);
641        self.and_uniforms = and_uniforms;
642        self.and_uniform_buffer = and_uniform_buffer;
643        self.and_bind_group = and_bind_group;
644
645        self.decrementing_pipeline = Arc::new(decrementing_pipeline);
646        self.decrementing_uniforms = decrementing_uniforms;
647        self.decrementing_uniform_buffer = decrementing_uniform_buffer;
648        self.decrementing_bind_group = decrementing_bind_group;
649
650        self.shape_texture_bind_group_layout_background = Arc::new(and_texture_bgl_layer0);
651        self.shape_texture_bind_group_layout_foreground = Arc::new(and_texture_bgl_layer1);
652        self.shape_texture_layout_epoch += 1;
653
654        let (default_shape_texture_bind_group_background, _) =
655            Self::create_default_shape_texture_bind_group(
656                &self.device,
657                &self.queue,
658                &self.shape_texture_bind_group_layout_background,
659            );
660        let (default_shape_texture_bind_group_foreground, _) =
661            Self::create_default_shape_texture_bind_group(
662                &self.device,
663                &self.queue,
664                &self.shape_texture_bind_group_layout_foreground,
665            );
666        self.default_shape_texture_bind_groups = [
667            Arc::new(default_shape_texture_bind_group_background),
668            Arc::new(default_shape_texture_bind_group_foreground),
669        ];
670
671        self.composite_pipeline = None;
672        self.composite_bgl = None;
673
674        self.leaf_draw_pipeline = Arc::new(crate::pipeline::create_stencil_keep_color_pipeline(
675            &self.device,
676            self.config.format,
677            self.msaa_sample_count,
678            &self.and_pipeline.get_bind_group_layout(0),
679            &self.shape_texture_bind_group_layout_background,
680            &self.shape_texture_bind_group_layout_foreground,
681        ));
682    }
683}