use crate::ffi::*;
#[derive(Debug, Clone, Copy)]
#[repr(usize)]
pub enum VertexFormat {
Float = MTLVertexFormatFloat,
Float2 = MTLVertexFormatFloat2,
Float3 = MTLVertexFormatFloat3,
Float4 = MTLVertexFormatFloat4,
Half2 = MTLVertexFormatHalf2,
Half4 = MTLVertexFormatHalf4,
UChar4Normalized = MTLVertexFormatUChar4Normalized,
UInt = MTLVertexFormatUInt,
Int = MTLVertexFormatInt,
}
#[derive(Debug, Clone, Copy)]
#[repr(usize)]
pub enum VertexStep {
Constant = MTLVertexStepFunctionConstant,
PerVertex = MTLVertexStepFunctionPerVertex,
PerInstance = MTLVertexStepFunctionPerInstance,
}
#[derive(Debug, Clone, Copy)]
pub struct VertexAttribute {
pub shader_location: u32,
pub format: VertexFormat,
pub offset: u32,
pub buffer_index: u32,
}
#[derive(Debug, Clone, Copy)]
pub struct VertexBufferLayout {
pub buffer_index: u32,
pub stride: u32,
pub step: VertexStep,
pub step_rate: u32,
}
#[derive(Debug, Clone, Default)]
pub struct VertexDescriptor {
pub attributes: Vec<VertexAttribute>,
pub layouts: Vec<VertexBufferLayout>,
}
impl VertexDescriptor {
pub fn new() -> Self {
Self::default()
}
pub fn with_attribute(mut self, a: VertexAttribute) -> Self {
self.attributes.push(a);
self
}
pub fn with_layout(mut self, l: VertexBufferLayout) -> Self {
self.layouts.push(l);
self
}
pub(crate) unsafe fn build_objc(&self) -> ObjcId {
let cls = objc_getClass(c"MTLVertexDescriptor".as_ptr()) as ObjcId;
let new_sel = sel_registerName(c"new".as_ptr());
let desc = msg0(cls, new_sel);
let attrs_array = msg0(desc, SEL_attributes());
for a in &self.attributes {
let slot = msg1_uint_id(
attrs_array,
SEL_objectAtIndexedSubscript(),
a.shader_location as NSUInteger,
);
msg1_uint_void(slot, SEL_setFormat(), a.format as NSUInteger);
msg1_uint_void(slot, SEL_setOffset(), a.offset as NSUInteger);
msg1_uint_void(slot, SEL_setBufferIndex(), a.buffer_index as NSUInteger);
}
let layouts_array = msg0(desc, SEL_layouts());
for l in &self.layouts {
let slot = msg1_uint_id(
layouts_array,
SEL_objectAtIndexedSubscript(),
l.buffer_index as NSUInteger,
);
msg1_uint_void(slot, SEL_setStride(), l.stride as NSUInteger);
msg1_uint_void(slot, SEL_setStepFunction(), l.step as NSUInteger);
msg1_uint_void(slot, SEL_setStepRate(), l.step_rate as NSUInteger);
}
desc
}
}