glium::implement_uniform_block! [] [src]

macro_rules! implement_uniform_block {
    (__as_item $i:item) => {$i};

    (__impl $struct_name:ident [$($gs:tt)*], $($field_name:ident),+) => (
        implement_uniform_block! { __as_item
            impl<$($gs)*> $crate::uniforms::UniformBlock for $struct_name<$($gs)*> {
                fn matches(layout: &$crate::program::BlockLayout, base_offset: usize)
                           -> ::std::result::Result<(), $crate::uniforms::LayoutMismatchError>
                {
                    use std::mem;
                    use $crate::program::BlockLayout;
                    use $crate::uniforms::LayoutMismatchError;

                    if let &BlockLayout::Struct { ref members } = layout {
                        // checking that each member exists in the input struct
                        for &(ref name, _) in members {
                            if $(name != stringify!($field_name) &&)+ true {
                                return Err(LayoutMismatchError::MissingField {
                                    name: name.clone(),
                                });
                            }
                        }

                        fn matches_from_ty<T: $crate::uniforms::UniformBlock + ?Sized>(_: &T,
                            layout: &$crate::program::BlockLayout, base_offset: usize)
                            -> ::std::result::Result<(), $crate::uniforms::LayoutMismatchError>
                        {
                            <T as $crate::uniforms::UniformBlock>::matches(layout, base_offset)
                        }

                        // checking that each field of the input struct is correct in the reflection
                        $(
                            let reflected_ty = members.iter().find(|&&(ref name, _)| {
                                                                        name == stringify!($field_name)
                                                                   });
                            let reflected_ty = match reflected_ty {
                                Some(t) => &t.1,
                                None => return Err(LayoutMismatchError::MissingField {
                                    name: stringify!($field_name).to_owned(),
                                })
                            };

                            let input_offset = {
                                let dummy: &$struct_name = unsafe { mem::zeroed() };
                                let dummy_field: *const _ = &dummy.$field_name;
                                dummy_field as *const () as usize
                            };

                            let dummy: &$struct_name = unsafe { mem::uninitialized() };
                            
                            match matches_from_ty(&dummy.$field_name, reflected_ty, input_offset) {
                                Ok(_) => (),
                                Err(e) => return Err(LayoutMismatchError::MemberMismatch {
                                    member: stringify!($field_name).to_owned(),
                                    err: Box::new(e),
                                })
                            };
                        )+

                        Ok(())

                    } else {
                        Err(LayoutMismatchError::LayoutMismatch {
                            expected: layout.clone(),
                            obtained: <Self as $crate::uniforms::UniformBlock>::build_layout(base_offset),
                        })
                    }
                }

                fn build_layout(base_offset: usize) -> $crate::program::BlockLayout {
                    use std::mem;
                    use $crate::program::BlockLayout;

                    fn layout_from_ty<T: $crate::uniforms::UniformBlock + ?Sized>(_: &T, base_offset: usize)
                                                                         -> BlockLayout
                    {
                        <T as $crate::uniforms::UniformBlock>::build_layout(base_offset)
                    }

                    let dummy: &$struct_name = unsafe { mem::zeroed() };

                    BlockLayout::Struct {
                        members: vec![
                            $(
                                (
                                    stringify!($field_name).to_owned(),
                                    {
                                        let offset = {
                                            let dummy_field: *const _ = &dummy.$field_name;
                                            dummy_field as *const () as usize
                                        };
                                        layout_from_ty(&dummy.$field_name, offset + base_offset)
                                    }
                                ),
                            )+
                        ],
                    }
                }
            }
        }
    );

    ($struct_name:ident, $($field_name:ident),+,) => (
        implement_uniform_block!($struct_name, $($field_name),+);
    );

    ($struct_name:ident, $($field_name:ident),+) => (
        implement_uniform_block!(__impl $struct_name [], $($field_name),+);
    );

    ($struct_name:ident<$l:tt>, $($field_name:ident),+) => (
        implement_uniform_block!(__impl $struct_name [$l], $($field_name),+);
    );
}

Implements the glium::uniforms::UniformBlock trait for the given type.

The parameters must be the name of the struct and the names of its fields.

Example

#[derive(Copy, Clone)]
struct Vertex {
    value1: [f32; 3],
    value2: [f32; 2],
}

implement_uniform_block!(Vertex, value1, value2);