1use bytemuck::{Pod, Zeroable};
2
3use crate::Transform2D;
4
5pub(crate) const MAX_SCENE_LIGHTS: usize = 8;
6
7#[repr(C)]
8#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
9pub struct GpuGlobals {
10 pub resolution: [f32; 2],
11 pub dpr: [f32; 2],
12 pub origin: [f32; 2],
13 pub _padding: [f32; 2],
14}
15
16#[repr(C)]
17#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
18pub(crate) struct GpuPrimitive {
19 pub fill_id: u16,
20 pub fill_type_flag: u16,
21 pub z_index: i32,
22 pub material_id: u32,
23 pub transform_id: u32,
24 pub draw_range: [f32; 4],
25 pub light_mask: u32,
26 pub paint_count: u32,
27 pub _padding: [u32; 2],
28}
29
30#[repr(C)]
31#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
32pub(crate) struct GpuColor {
33 pub color: [f32; 4],
34}
35
36#[repr(C)]
37#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
38pub(crate) struct GpuMaterial {
39 pub coefficients: [f32; 4],
40 pub emissive: [f32; 4],
41}
42
43#[repr(C)]
44#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
45pub(crate) struct GpuSceneLight {
46 pub position: [f32; 4],
47 pub direction: [f32; 4],
48 pub color: [f32; 4],
49 pub params: [f32; 4],
50}
51
52#[repr(C)]
53#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
54pub(crate) struct GpuSceneLighting {
55 pub ambient: [f32; 4],
56 pub meta: [u32; 4],
57 pub lights: [GpuSceneLight; MAX_SCENE_LIGHTS],
58}
59
60const MAX_GRADIENT_STOPS: usize = 8;
63
64#[repr(C)]
65#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
66pub(crate) struct GpuGradient {
67 pub colors: [[f32; 4]; MAX_GRADIENT_STOPS],
68 pub stops: [f32; MAX_GRADIENT_STOPS],
69 pub position: [f32; 2],
70 pub main_axis: [f32; 2],
71 pub off_axis: [f32; 2],
72 pub stop_count: u32,
73 pub type_id: u32,
74 pub weight: f32,
75 pub _padding_0: u32,
76 pub focal_point: [f32; 2],
77 pub _padding: [u32; 12],
78}
79
80#[repr(C)]
81#[derive(Debug, Copy, Clone, Pod, Zeroable)]
82pub(crate) struct GpuTransform {
83 pub transform: [[f32; 2]; 3],
84 pub opacity: f32,
85 pub _pad: f32,
86}
87
88impl Default for GpuTransform {
89 fn default() -> Self {
90 Self {
91 transform: Transform2D::identity().to_arrays(),
92 opacity: 1.0,
93 _pad: 0.0,
94 }
95 }
96}
97
98#[repr(C)]
99#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
100pub(crate) struct GpuVertex {
101 pub position: [f32; 2],
102 pub normal: [f32; 2],
103 pub prim_id: u32,
104 pub path_progress: f32,
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn gpu_primitive_matches_wgsl_storage_stride() {
113 assert_eq!(std::mem::size_of::<GpuPrimitive>(), 48);
114 assert_eq!(std::mem::align_of::<GpuPrimitive>(), 4);
115 assert_eq!(std::mem::size_of::<GpuGradient>(), 256);
116 }
117}
118
119impl GpuVertex {
120 pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
121 const ATTRIBS: [wgpu::VertexAttribute; 4] =
122 wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2, 2 => Uint32, 3 => Float32];
123 wgpu::VertexBufferLayout {
124 array_stride: std::mem::size_of::<GpuVertex>() as wgpu::BufferAddress,
125 step_mode: wgpu::VertexStepMode::Vertex,
126 attributes: &ATTRIBS,
127 }
128 }
129}