use noesis_runtime::render_device::types::{
ATTRIBUTES_FOR_FORMAT, SIZE_FOR_FORMAT, SIZE_FOR_TYPE, TYPE_FOR_ATTR, VERTEX_ATTR_COUNT,
};
#[must_use]
pub fn attributes_for_format(format_idx: u8) -> Vec<wgpu::VertexAttribute> {
let mask = ATTRIBUTES_FOR_FORMAT[format_idx as usize];
let mut attrs = Vec::new();
let mut offset: u64 = 0;
for attr_bit in 0..VERTEX_ATTR_COUNT as u8 {
if (mask & (1 << attr_bit)) == 0 {
continue;
}
let type_idx = TYPE_FOR_ATTR[attr_bit as usize];
attrs.push(wgpu::VertexAttribute {
offset,
shader_location: u32::from(attr_bit),
format: wgpu_format_for_type(type_idx),
});
offset += u64::from(SIZE_FOR_TYPE[type_idx as usize]);
}
debug_assert_eq!(
offset,
u64::from(SIZE_FOR_FORMAT[format_idx as usize]),
"vertex layout stride mismatch for format {format_idx}"
);
attrs
}
#[must_use]
pub fn stride_for_format(format_idx: u8) -> u64 {
u64::from(SIZE_FOR_FORMAT[format_idx as usize])
}
fn wgpu_format_for_type(type_idx: u8) -> wgpu::VertexFormat {
match type_idx {
0 => wgpu::VertexFormat::Float32, 1 => wgpu::VertexFormat::Float32x2, 2 => wgpu::VertexFormat::Float32x4, 3 => wgpu::VertexFormat::Unorm8x4, 4 => wgpu::VertexFormat::Unorm16x4, other => panic!("unknown VertexAttrType: {other}"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn pos_color_layout() {
let attrs = attributes_for_format(1);
assert_eq!(attrs.len(), 2);
assert_eq!(attrs[0].shader_location, 0);
assert_eq!(attrs[0].offset, 0);
assert_eq!(attrs[0].format, wgpu::VertexFormat::Float32x2);
assert_eq!(attrs[1].shader_location, 1);
assert_eq!(attrs[1].offset, 8);
assert_eq!(attrs[1].format, wgpu::VertexFormat::Unorm8x4);
assert_eq!(stride_for_format(1), 12);
}
#[test]
fn pos_tex0_rect_tile_layout() {
let attrs = attributes_for_format(4);
assert_eq!(attrs.len(), 4);
assert_eq!(attrs[0].shader_location, 0);
assert_eq!(attrs[1].shader_location, 2);
assert_eq!(attrs[2].shader_location, 5);
assert_eq!(attrs[3].shader_location, 6);
assert_eq!(stride_for_format(4), 40);
}
}