1 // Copyright (c) 2017 The vulkano developers 2 // Licensed under the Apache License, Version 2.0 3 // <LICENSE-APACHE or 4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT 5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, 6 // at your option. All files in the project carrying such 7 // notice may not be copied, modified, or distributed except 8 // according to those terms. 9 10 use crate::format::Format; 11 12 /// Implements the `Vertex` trait on a struct. 13 /// 14 /// # Examples 15 /// 16 /// ``` 17 /// # use vulkano::buffer::BufferContents; 18 /// #[derive(BufferContents, Default)] 19 /// #[repr(C)] 20 /// struct Vertex { 21 /// position: [f32; 3], 22 /// color: [f32; 4], 23 /// } 24 /// 25 /// vulkano::impl_vertex!(Vertex, position, color); 26 /// ``` 27 #[deprecated( 28 since = "0.33.0", 29 note = "derive `Vertex` instead and use field-level attributes to specify format" 30 )] 31 #[macro_export] 32 macro_rules! impl_vertex { 33 ($out:ty $(, $member:ident)*) => ( 34 #[allow(unsafe_code)] 35 unsafe impl $crate::pipeline::graphics::vertex_input::Vertex for $out { 36 #[inline(always)] 37 #[allow(deprecated)] 38 fn per_vertex() -> $crate::pipeline::graphics::vertex_input::VertexBufferDescription { 39 #[allow(unused_imports)] 40 use std::collections::HashMap; 41 use $crate::format::Format; 42 use $crate::pipeline::graphics::vertex_input::VertexMember; 43 use $crate::pipeline::graphics::vertex_input::{VertexInputRate, VertexMemberInfo}; 44 45 let mut members = HashMap::default(); 46 $( 47 { 48 let dummy = <$out>::default(); 49 #[inline] fn f<T: VertexMember>(_: &T) -> Format { T::format() } 50 let format = f(&dummy.$member); 51 let field_size = { 52 let p = unsafe { 53 core::ptr::addr_of!((*(&dummy as *const _ as *const $out)).$member) 54 }; 55 const fn size_of_raw<T>(_: *const T) -> usize { 56 core::mem::size_of::<T>() 57 } 58 size_of_raw(p) 59 } as u32; 60 let format_size = format.block_size().expect("no block size for format") as u32; 61 let num_elements = field_size / format_size; 62 let remainder = field_size % format_size; 63 assert!(remainder == 0, "struct field `{}` size does not fit multiple of format size", stringify!($member)); 64 65 let dummy_ptr = (&dummy) as *const _; 66 let member_ptr = (&dummy.$member) as *const _; 67 68 members.insert(stringify!($member).to_string(), VertexMemberInfo { 69 offset: member_ptr as usize - dummy_ptr as usize, 70 format, 71 num_elements, 72 }); 73 } 74 )* 75 76 $crate::pipeline::graphics::vertex_input::VertexBufferDescription { 77 members, 78 stride: std::mem::size_of::<$out>() as u32, 79 input_rate: VertexInputRate::Vertex, 80 } 81 } 82 #[inline(always)] 83 #[allow(deprecated)] 84 fn per_instance() -> $crate::pipeline::graphics::vertex_input::VertexBufferDescription { 85 <$out as $crate::pipeline::graphics::vertex_input::Vertex>::per_vertex().per_instance() 86 } 87 #[inline(always)] 88 #[allow(deprecated)] 89 fn per_instance_with_divisor(divisor: u32) -> $crate::pipeline::graphics::vertex_input::VertexBufferDescription { 90 <$out as $crate::pipeline::graphics::vertex_input::Vertex>::per_vertex().per_instance_with_divisor(divisor) 91 } 92 93 } 94 ) 95 } 96 97 /// Trait for data types that can be used as vertex members. Used by the `impl_vertex!` macro. 98 #[deprecated( 99 since = "0.33.0", 100 note = "Derive `Vertex` instead and use field-level attributes to specify format" 101 )] 102 pub unsafe trait VertexMember { 103 /// Returns the format and array size of the member. format() -> Format104 fn format() -> Format; 105 } 106 107 #[macro_export] 108 macro_rules! impl_vertex_member { 109 ($out:ty, $format:ident) => { 110 #[allow(deprecated)] 111 unsafe impl VertexMember for $out { 112 #[inline] 113 fn format() -> Format { 114 Format::$format 115 } 116 } 117 }; 118 } 119 120 impl_vertex_member!(i8, R8_SINT); 121 impl_vertex_member!(u8, R8_UINT); 122 impl_vertex_member!(i16, R16_SINT); 123 impl_vertex_member!(u16, R16_UINT); 124 impl_vertex_member!(i32, R32_SINT); 125 impl_vertex_member!(u32, R32_UINT); 126 impl_vertex_member!(f32, R32_SFLOAT); 127 impl_vertex_member!(f64, R64_SFLOAT); 128 impl_vertex_member!([i8; 2], R8G8_SINT); 129 impl_vertex_member!([u8; 2], R8G8_UINT); 130 impl_vertex_member!([i16; 2], R16G16_SINT); 131 impl_vertex_member!([u16; 2], R16G16_UINT); 132 impl_vertex_member!([i32; 2], R32G32_SINT); 133 impl_vertex_member!([u32; 2], R32G32_UINT); 134 impl_vertex_member!([f32; 2], R32G32_SFLOAT); 135 impl_vertex_member!([f64; 2], R64G64_SFLOAT); 136 impl_vertex_member!([i8; 3], R8G8B8_SINT); 137 impl_vertex_member!([u8; 3], R8G8B8_UINT); 138 impl_vertex_member!([i16; 3], R16G16B16_SINT); 139 impl_vertex_member!([u16; 3], R16G16B16_UINT); 140 impl_vertex_member!([i32; 3], R32G32B32_SINT); 141 impl_vertex_member!([u32; 3], R32G32B32_UINT); 142 impl_vertex_member!([f32; 3], R32G32B32_SFLOAT); 143 impl_vertex_member!([f64; 3], R64G64B64_SFLOAT); 144 impl_vertex_member!([i8; 4], R8G8B8A8_SINT); 145 impl_vertex_member!([u8; 4], R8G8B8A8_UINT); 146 impl_vertex_member!([i16; 4], R16G16B16A16_SINT); 147 impl_vertex_member!([u16; 4], R16G16B16A16_UINT); 148 impl_vertex_member!([i32; 4], R32G32B32A32_SINT); 149 impl_vertex_member!([u32; 4], R32G32B32A32_UINT); 150 impl_vertex_member!([f32; 4], R32G32B32A32_SFLOAT); 151 impl_vertex_member!([f64; 4], R64G64B64A64_SFLOAT); 152 impl_vertex_member!([f32; 9], R32G32B32_SFLOAT); 153 impl_vertex_member!([f32; 16], R32G32B32A32_SFLOAT); 154 155 #[allow(deprecated)] 156 unsafe impl<T> VertexMember for [T; 1] 157 where 158 T: VertexMember, 159 { format() -> Format160 fn format() -> Format { 161 <T as VertexMember>::format() 162 } 163 } 164 165 #[cfg(test)] 166 mod tests { 167 use crate::format::Format; 168 #[allow(deprecated)] 169 use crate::pipeline::graphics::vertex_input::Vertex; 170 171 use bytemuck::{Pod, Zeroable}; 172 173 #[test] 174 #[allow(deprecated)] impl_vertex()175 fn impl_vertex() { 176 #[repr(C)] 177 #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] 178 struct TestVertex { 179 matrix: [f32; 16], 180 vector: [f32; 4], 181 scalar: u16, 182 _padding: u16, 183 } 184 impl_vertex!(TestVertex, scalar, vector, matrix); 185 186 let info = TestVertex::per_vertex(); 187 let matrix = info.members.get("matrix").unwrap(); 188 let vector = info.members.get("vector").unwrap(); 189 let scalar = info.members.get("scalar").unwrap(); 190 assert_eq!(matrix.format, Format::R32G32B32A32_SFLOAT); 191 assert_eq!(matrix.offset, 0); 192 assert_eq!(matrix.num_elements, 4); 193 assert_eq!(vector.format, Format::R32G32B32A32_SFLOAT); 194 assert_eq!(vector.offset, 16 * 4); 195 assert_eq!(vector.num_elements, 1); 196 assert_eq!(scalar.format, Format::R16_UINT); 197 assert_eq!(scalar.offset, 16 * 5); 198 assert_eq!(scalar.num_elements, 1); 199 } 200 } 201