Skip to main content

lumen_engine/gpu/
types.rs

1use std::collections::HashMap;
2
3use crate::media::MediaFrame;
4use crate::node::{NodeId, PortRef};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum AlphaMode {
8    Premultiplied,
9    Unpremultiplied,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum ColorSpace {
14    Srgb,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct RasterMetadata {
19    pub alpha_mode: AlphaMode,
20    pub color_space: ColorSpace,
21}
22
23impl Default for RasterMetadata {
24    fn default() -> Self {
25        Self {
26            alpha_mode: AlphaMode::Premultiplied,
27            color_space: ColorSpace::Srgb,
28        }
29    }
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq)]
33pub struct RasterHandle {
34    pub texture: lumen_gpu::TextureId,
35    pub domain: lumen_gpu::TextureDomain,
36    pub metadata: RasterMetadata,
37}
38
39#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum CompiledOutput {
41    Raster(RasterHandle),
42    Empty,
43}
44
45impl CompiledOutput {
46    pub fn into_raster(self, node_id: NodeId, _port: &str) -> crate::Result<RasterHandle> {
47        match self {
48            Self::Raster(raster) => Ok(raster),
49            Self::Empty => Err(crate::error::RenderError::InvalidNodeOutputType {
50                frame: 0,
51                node_id,
52                expected: "Raster",
53                actual: "Empty",
54            }
55            .into()),
56        }
57    }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq, Hash)]
61pub struct FramePortRef {
62    pub port: PortRef,
63    pub frame: u32,
64}
65
66impl FramePortRef {
67    pub fn new(port: PortRef, frame: u32) -> Self {
68        Self { port, frame }
69    }
70}
71
72pub trait GpuCompiledNode: std::fmt::Debug + Send + Sync {
73    fn node_id(&self) -> NodeId;
74
75    fn bind(
76        &self,
77        ctx: &crate::gpu::FrameBindContext<'_>,
78        bound: &mut BoundFrame,
79    ) -> crate::Result<()>;
80}
81
82#[derive(Debug)]
83pub struct CompiledComposition {
84    pub plan: lumen_gpu::RenderPlan,
85    pub output: RasterHandle,
86    pub node_outputs: HashMap<PortRef, CompiledOutput>,
87    pub compiled_nodes: HashMap<NodeId, Box<dyn GpuCompiledNode>>,
88}
89
90#[derive(Debug, Clone, Default)]
91pub struct BoundFrame {
92    buffer_uploads: Vec<(lumen_gpu::BufferId, u64, Vec<u8>)>,
93    texture_uploads: Vec<TextureUpload>,
94    media_textures: Vec<MediaTextureUpload>,
95}
96
97#[derive(Debug, Clone)]
98enum TextureUpload {
99    Rgba8 {
100        id: lumen_gpu::TextureId,
101        data: Vec<u8>,
102        bytes_per_row: u32,
103        rows_per_image: u32,
104    },
105    Rgba8Region {
106        id: lumen_gpu::TextureId,
107        data: Vec<u8>,
108        origin: [u32; 3],
109        size: lumen_gpu::Size,
110        bytes_per_row: u32,
111        rows_per_image: u32,
112    },
113    Rgba16Float {
114        id: lumen_gpu::TextureId,
115        data: Vec<u16>,
116        bytes_per_row: u32,
117        rows_per_image: u32,
118    },
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
122pub struct MediaTextureKey {
123    pub source: String,
124    pub frame: Option<u32>,
125    pub width: u32,
126    pub height: u32,
127}
128
129#[derive(Debug, Clone)]
130pub struct MediaTextureUpload {
131    pub texture: lumen_gpu::TextureId,
132    pub key: MediaTextureKey,
133    pub frame: MediaFrame,
134    pub size: lumen_gpu::Size,
135}
136
137impl BoundFrame {
138    pub fn new() -> Self {
139        Self::default()
140    }
141
142    pub fn write_buffer(&mut self, id: lumen_gpu::BufferId, offset: u64, data: impl Into<Vec<u8>>) {
143        self.buffer_uploads.push((id, offset, data.into()));
144    }
145
146    pub fn write_texture_rgba8(
147        &mut self,
148        id: lumen_gpu::TextureId,
149        data: impl Into<Vec<u8>>,
150        bytes_per_row: u32,
151        rows_per_image: u32,
152    ) {
153        self.texture_uploads.push(TextureUpload::Rgba8 {
154            id,
155            data: data.into(),
156            bytes_per_row,
157            rows_per_image,
158        });
159    }
160
161    pub fn write_texture_rgba8_region(
162        &mut self,
163        id: lumen_gpu::TextureId,
164        data: impl Into<Vec<u8>>,
165        origin: [u32; 3],
166        size: lumen_gpu::Size,
167        bytes_per_row: u32,
168        rows_per_image: u32,
169    ) {
170        self.texture_uploads.push(TextureUpload::Rgba8Region {
171            id,
172            data: data.into(),
173            origin,
174            size,
175            bytes_per_row,
176            rows_per_image,
177        });
178    }
179
180    pub fn write_texture_rgba16_float(
181        &mut self,
182        id: lumen_gpu::TextureId,
183        data: impl Into<Vec<u16>>,
184        bytes_per_row: u32,
185        rows_per_image: u32,
186    ) {
187        self.texture_uploads.push(TextureUpload::Rgba16Float {
188            id,
189            data: data.into(),
190            bytes_per_row,
191            rows_per_image,
192        });
193    }
194
195    pub fn use_media_texture(
196        &mut self,
197        texture: lumen_gpu::TextureId,
198        key: MediaTextureKey,
199        frame: MediaFrame,
200        size: lumen_gpu::Size,
201    ) {
202        self.media_textures.push(MediaTextureUpload {
203            texture,
204            key,
205            frame,
206            size,
207        });
208    }
209
210    pub fn media_textures(&self) -> &[MediaTextureUpload] {
211        &self.media_textures
212    }
213
214    pub fn buffer_upload_count(&self) -> usize {
215        self.buffer_uploads.len()
216    }
217
218    pub fn texture_upload_count(&self) -> usize {
219        self.texture_uploads.len()
220    }
221
222    pub fn frame_update(&self) -> lumen_gpu::FrameUpdate<'_> {
223        let mut update = lumen_gpu::FrameUpdate::new();
224        for (id, offset, data) in &self.buffer_uploads {
225            update.write_buffer(*id, *offset, data);
226        }
227        for upload in &self.texture_uploads {
228            match upload {
229                TextureUpload::Rgba8 {
230                    id,
231                    data,
232                    bytes_per_row,
233                    rows_per_image,
234                } => {
235                    update.write_texture_rgba8(*id, data, *bytes_per_row, *rows_per_image);
236                }
237                TextureUpload::Rgba8Region {
238                    id,
239                    data,
240                    origin,
241                    size,
242                    bytes_per_row,
243                    rows_per_image,
244                } => {
245                    update.write_texture_rgba8_region(
246                        *id,
247                        data,
248                        *origin,
249                        *size,
250                        *bytes_per_row,
251                        *rows_per_image,
252                    );
253                }
254                TextureUpload::Rgba16Float {
255                    id,
256                    data,
257                    bytes_per_row,
258                    rows_per_image,
259                } => {
260                    update.write_texture_rgba16_float(*id, data, *bytes_per_row, *rows_per_image);
261                }
262            }
263        }
264        update
265    }
266}