diff --git a/src/render/draw_data.rs b/src/render/draw_data.rs index 2823a71..8150ef9 100644 --- a/src/render/draw_data.rs +++ b/src/render/draw_data.rs @@ -224,49 +224,49 @@ use glium::implement_vertex; implement_vertex!(DrawVert, pos, uv, col); #[cfg(feature = "gfx")] -unsafe impl gfx::traits::Pod for DrawVert {} -#[cfg(feature = "gfx")] -impl gfx::pso::buffer::Structure for DrawVert { - fn query(name: &str) -> Option> { - // array query hack from gfx_impl_struct_meta macro - use gfx::format::Formatted; - use gfx::pso::buffer::{ElemOffset, Element}; - use std::mem::{size_of, transmute}; - // using "1" here as a simple non-zero pointer addres - let tmp: &DrawVert = unsafe { transmute(1usize) }; - let base = tmp as *const _ as usize; - //HACK: special treatment of array queries - let (sub_name, big_offset) = { - let mut split = name.split(|c| c == '[' || c == ']'); - let _ = split.next().unwrap(); - match split.next() { - Some(s) => { - let array_id: ElemOffset = s.parse().unwrap(); - let sub_name = match split.next() { - Some(s) if s.starts_with('.') => &s[1..], - _ => name, - }; - (sub_name, array_id * (size_of::() as ElemOffset)) - } - None => (name, 0), - } - }; - match sub_name { - "pos" => Some(Element { - format: <[f32; 2] as Formatted>::get_format(), - offset: ((&tmp.pos as *const _ as usize) - base) as ElemOffset + big_offset, - }), - "uv" => Some(Element { - format: <[f32; 2] as Formatted>::get_format(), - offset: ((&tmp.uv as *const _ as usize) - base) as ElemOffset + big_offset, - }), - "col" => Some(Element { - format: <[gfx::format::U8Norm; 4] as Formatted>::get_format(), - offset: ((&tmp.col as *const _ as usize) - base) as ElemOffset + big_offset, - }), - _ => None, +mod gfx_support { + use gfx::*; + use super::DrawVert; + + // gfx doesn't provide a macro to implement vertex structure for an existing struct, so we + // create a dummy vertex with the same memory layout using gfx macros, and delegate query(name) + // calls later to the automatically derived implementation + gfx_vertex_struct! { + Dummy { + pos: [f32; 2] = "pos", + uv: [f32; 2] = "uv", + col: [format::U8Norm; 4] = "col", } } + unsafe impl gfx::traits::Pod for DrawVert {} + impl gfx::pso::buffer::Structure for DrawVert { + fn query(name: &str) -> Option> { + // Dummy has the same memory layout, so this should be ok + Dummy::query(name) + } + } + + #[test] + fn test_dummy_memory_layout() { + use std::mem; + assert_eq!( + mem::size_of::(), + mem::size_of::() + ); + assert_eq!( + mem::align_of::(), + mem::align_of::() + ); + use memoffset::offset_of; + macro_rules! assert_field_offset { + ($l:ident, $r:ident) => { + assert_eq!(offset_of!(DrawVert, $l), offset_of!(Dummy, $r)); + }; + }; + assert_field_offset!(pos, pos); + assert_field_offset!(uv, uv); + assert_field_offset!(col, col); + } } #[test]