use bytemuck::{Pod, Zeroable};
use crate::Transform2D;
pub(crate) const MAX_SCENE_LIGHTS: usize = 8;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub struct GpuGlobals {
pub resolution: [f32; 2],
pub dpr: [f32; 2],
pub origin: [f32; 2],
pub _padding: [f32; 2],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuPrimitive {
pub fill_id: u16,
pub fill_type_flag: u16,
pub z_index: i32,
pub material_id: u32,
pub transform_id: u32,
pub draw_range: [f32; 4],
pub light_mask: u32,
pub paint_count: u32,
pub _padding: [u32; 2],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuColor {
pub color: [f32; 4],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuMaterial {
pub coefficients: [f32; 4],
pub emissive: [f32; 4],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuSceneLight {
pub position: [f32; 4],
pub direction: [f32; 4],
pub color: [f32; 4],
pub params: [f32; 4],
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuSceneLighting {
pub ambient: [f32; 4],
pub meta: [u32; 4],
pub lights: [GpuSceneLight; MAX_SCENE_LIGHTS],
}
const MAX_GRADIENT_STOPS: usize = 8;
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuGradient {
pub colors: [[f32; 4]; MAX_GRADIENT_STOPS],
pub stops: [f32; MAX_GRADIENT_STOPS],
pub position: [f32; 2],
pub main_axis: [f32; 2],
pub off_axis: [f32; 2],
pub stop_count: u32,
pub type_id: u32,
pub weight: f32,
pub _padding_0: u32,
pub focal_point: [f32; 2],
pub _padding: [u32; 12],
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuTransform {
pub transform: [[f32; 2]; 3],
pub opacity: f32,
pub _pad: f32,
}
impl Default for GpuTransform {
fn default() -> Self {
Self {
transform: Transform2D::identity().to_arrays(),
opacity: 1.0,
_pad: 0.0,
}
}
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, Pod, Zeroable)]
pub(crate) struct GpuVertex {
pub position: [f32; 2],
pub normal: [f32; 2],
pub prim_id: u32,
pub path_progress: f32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gpu_primitive_matches_wgsl_storage_stride() {
assert_eq!(std::mem::size_of::<GpuPrimitive>(), 48);
assert_eq!(std::mem::align_of::<GpuPrimitive>(), 4);
assert_eq!(std::mem::size_of::<GpuGradient>(), 256);
}
}
impl GpuVertex {
pub(crate) fn desc() -> wgpu::VertexBufferLayout<'static> {
const ATTRIBS: [wgpu::VertexAttribute; 4] =
wgpu::vertex_attr_array![0 => Float32x2, 1 => Float32x2, 2 => Uint32, 3 => Float32];
wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<GpuVertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &ATTRIBS,
}
}
}