Skip to main content

tessera_components/
pipelines.rs

1//! Render and compute pipelines backing the basic components.
2//!
3//! ## Usage
4//!
5//! Register pipelines during renderer initialization before rendering
6//! components.
7
8pub(crate) mod blur;
9pub(crate) mod checkmark;
10pub(crate) mod contrast;
11pub(crate) mod divider;
12pub(crate) mod fluid_glass;
13pub(crate) mod image;
14pub(crate) mod image_vector;
15pub(crate) mod linear_wave;
16pub(crate) mod loading_shape;
17pub(crate) mod path_stroke;
18pub(crate) mod progress_arc;
19pub(crate) mod shape;
20pub(crate) mod simple_rect;
21pub(crate) mod text;
22
23mod compute;
24mod draw;
25mod instanced;
26
27/// Register all draw and compute pipelines required by this crate.
28pub fn register_pipelines(context: &mut tessera_ui::PipelineContext<'_>) {
29    // Independent renderer instances can reuse backend device identifiers.
30    SharedQuad::clear();
31    draw::register(context);
32    compute::register(context);
33}
34
35use std::{cell::RefCell, sync::Arc};
36
37use tessera_ui::wgpu::{self, util::DeviceExt};
38
39#[repr(C)]
40#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
41struct UnitQuadVertex {
42    position: [f32; 2],
43}
44
45/// Shared unit-quad buffers for rectangle-based drawing.
46#[derive(Clone)]
47pub(crate) struct SharedQuad {
48    vertex: Arc<wgpu::Buffer>,
49    index: Arc<wgpu::Buffer>,
50}
51
52struct SharedQuadSlot {
53    device: wgpu::Device,
54    quad: SharedQuad,
55}
56
57#[derive(Default)]
58struct SharedQuadCache(RefCell<Option<SharedQuadSlot>>);
59
60impl SharedQuad {
61    fn clear() {
62        let cache = tessera_ui::__private::local_runtime_resource::<SharedQuadCache>();
63        let removed = cache.0.replace(None);
64        drop(removed);
65    }
66
67    /// Returns the shared (0,0)-(1,1) quad buffers for `device`.
68    ///
69    /// Repeated calls on the same device and runtime session reuse the buffers.
70    pub(crate) fn get(device: &wgpu::Device) -> Self {
71        let cache = tessera_ui::__private::local_runtime_resource::<SharedQuadCache>();
72        let mut slot = cache.0.borrow_mut();
73        if let Some(slot) = slot.as_ref()
74            && slot.device == *device
75        {
76            return slot.quad.clone();
77        }
78        let quad = Self::create(device);
79        let removed = slot.replace(SharedQuadSlot {
80            device: device.clone(),
81            quad: quad.clone(),
82        });
83        drop(slot);
84        drop(removed);
85        quad
86    }
87
88    fn create(device: &wgpu::Device) -> Self {
89        let vertices = [
90            UnitQuadVertex {
91                position: [0.0, 0.0],
92            },
93            UnitQuadVertex {
94                position: [1.0, 0.0],
95            },
96            UnitQuadVertex {
97                position: [1.0, 1.0],
98            },
99            UnitQuadVertex {
100                position: [0.0, 1.0],
101            },
102        ];
103        let vertex = Arc::new(
104            device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
105                label: Some("Shared Unit Quad Vertex Buffer"),
106                contents: bytemuck::cast_slice(&vertices),
107                usage: wgpu::BufferUsages::VERTEX,
108            }),
109        );
110
111        let indices: [u16; 6] = [0, 2, 1, 0, 3, 2];
112        let index = Arc::new(
113            device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
114                label: Some("Shared Unit Quad Index Buffer"),
115                contents: bytemuck::cast_slice(&indices),
116                usage: wgpu::BufferUsages::INDEX,
117            }),
118        );
119
120        Self { vertex, index }
121    }
122
123    pub(crate) fn vertex(&self) -> &Arc<wgpu::Buffer> {
124        &self.vertex
125    }
126
127    pub(crate) fn index(&self) -> &Arc<wgpu::Buffer> {
128        &self.index
129    }
130}