Skip to main content

ursus_materials/
field.rs

1use crate::value::MaterialValue;
2
3/// The scalar/vector type of a single field.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum FieldType {
6    Float,
7    UInt,
8    Vec2,
9    Vec3,
10    Vec4,
11    UVec4,
12}
13
14impl FieldType {
15    /// Size in bytes of one value of this type.
16    pub const fn size(self) -> usize {
17        match self {
18            Self::Float | Self::UInt => 4,
19            Self::Vec2 => 8,
20            Self::Vec3 => 12,
21            Self::Vec4 | Self::UVec4 => 16,
22        }
23    }
24
25    /// std430 alignment rules (GLSL storage buffer layout): vec3 aligns as
26    /// vec4, everything else aligns to its own size.
27    pub const fn std430_align(self) -> usize {
28        match self {
29            Self::Float | Self::UInt => 4,
30            Self::Vec2 => 8,
31            Self::Vec3 | Self::Vec4 | Self::UVec4 => 16,
32        }
33    }
34}
35
36/// Describes one named field a strategy exposes: its name and value type.
37/// Says nothing about memory layout - offsets, strides, and buffer
38/// placement are computed by whichever packing module consumes this
39/// (see `pack::aos`).
40#[derive(Debug, Clone, Copy)]
41pub struct FieldDesc {
42    pub name: &'static str,
43    pub ty: FieldType,
44}
45
46impl FieldDesc {
47    pub const fn new(name: &'static str, ty: FieldType) -> Self {
48        Self { name, ty }
49    }
50}
51
52/// Writes `value` into `dst` as raw little-endian bytes matching `ty`.
53/// `dst` must be at least `ty.size()` bytes long.
54pub fn write_field_bytes(ty: FieldType, value: &MaterialValue, dst: &mut [u8]) -> Option<()> {
55    match ty {
56        FieldType::Float => {
57            let v = value.as_float()?;
58            dst[..4].copy_from_slice(&v.to_le_bytes());
59        }
60        FieldType::UInt => {
61            let v = match value {
62                MaterialValue::Texture(t) => t.0,
63                MaterialValue::Int(i) => *i as u32,
64                _ => return None,
65            };
66            dst[..4].copy_from_slice(&v.to_le_bytes());
67        }
68        FieldType::Vec2 => {
69            let v = value.as_vec4()?;
70            dst[0..4].copy_from_slice(&v.x.to_le_bytes());
71            dst[4..8].copy_from_slice(&v.y.to_le_bytes());
72        }
73        FieldType::Vec3 => {
74            let v = value.as_vec3()?;
75            dst[0..4].copy_from_slice(&v.x.to_le_bytes());
76            dst[4..8].copy_from_slice(&v.y.to_le_bytes());
77            dst[8..12].copy_from_slice(&v.z.to_le_bytes());
78        }
79        FieldType::Vec4 => {
80            let v = value.as_vec4()?;
81            dst[0..4].copy_from_slice(&v.x.to_le_bytes());
82            dst[4..8].copy_from_slice(&v.y.to_le_bytes());
83            dst[8..12].copy_from_slice(&v.z.to_le_bytes());
84            dst[12..16].copy_from_slice(&v.w.to_le_bytes());
85        }
86        FieldType::UVec4 => {
87            let v = value.as_uvec4()?;
88            dst[0..4].copy_from_slice(&v[0].to_le_bytes());
89            dst[4..8].copy_from_slice(&v[1].to_le_bytes());
90            dst[8..12].copy_from_slice(&v[2].to_le_bytes());
91            dst[12..16].copy_from_slice(&v[3].to_le_bytes());
92        }
93    }
94    Some(())
95}