• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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