• 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 super::VertexInputRate;
11 use crate::{buffer::BufferContents, format::Format};
12 use std::collections::HashMap;
13 #[cfg(feature = "macros")]
14 pub use vulkano_macros::Vertex;
15 
16 /// Describes an individual `Vertex`. In other words a collection of attributes that can be read
17 /// from a vertex shader.
18 ///
19 /// At this stage, the vertex is in a "raw" format. For example a `[f32; 4]` can match both a
20 /// `vec4` or a `float[4]`. The way the things are bound depends on the shader.
21 ///
22 /// The vertex trait can be derived and the format has to be specified using the `format`
23 /// field-level attribute:
24 ///
25 /// ```
26 /// use vulkano::{buffer::BufferContents, pipeline::graphics::vertex_input::Vertex};
27 ///
28 /// #[derive(BufferContents, Vertex)]
29 /// #[repr(C)]
30 /// struct MyVertex {
31 ///     // Every field needs to explicitly state the desired shader input format
32 ///     #[format(R32G32B32_SFLOAT)]
33 ///     pos: [f32; 3],
34 ///     // The `name` attribute can be used to specify shader input names to match.
35 ///     // By default the field-name is used.
36 ///     #[name("in_proj", "cam_proj")]
37 ///     #[format(R32G32B32_SFLOAT)]
38 ///     proj: [f32; 16],
39 /// }
40 /// ```
41 pub unsafe trait Vertex: BufferContents + Sized {
42     /// Returns the information about this Vertex type.
per_vertex() -> VertexBufferDescription43     fn per_vertex() -> VertexBufferDescription;
44 
per_instance() -> VertexBufferDescription45     fn per_instance() -> VertexBufferDescription;
46 
per_instance_with_divisor(divisor: u32) -> VertexBufferDescription47     fn per_instance_with_divisor(divisor: u32) -> VertexBufferDescription;
48 }
49 
50 /// Describes the contents of a VertexBuffer.
51 #[derive(Clone, Debug)]
52 pub struct VertexBufferDescription {
53     /// List of member names with their detailed information.
54     pub members: HashMap<String, VertexMemberInfo>,
55     /// Stride of the vertex type in a buffer.
56     pub stride: u32,
57     /// How the vertex buffer is unrolled in the shader.
58     pub input_rate: VertexInputRate,
59 }
60 
61 impl VertexBufferDescription {
62     #[inline]
per_vertex(self) -> VertexBufferDescription63     pub fn per_vertex(self) -> VertexBufferDescription {
64         let VertexBufferDescription {
65             members, stride, ..
66         } = self;
67         VertexBufferDescription {
68             members,
69             stride,
70             input_rate: VertexInputRate::Vertex,
71         }
72     }
73 
74     #[inline]
per_instance(self) -> VertexBufferDescription75     pub fn per_instance(self) -> VertexBufferDescription {
76         self.per_instance_with_divisor(1)
77     }
78 
79     #[inline]
per_instance_with_divisor(self, divisor: u32) -> VertexBufferDescription80     pub fn per_instance_with_divisor(self, divisor: u32) -> VertexBufferDescription {
81         let VertexBufferDescription {
82             members, stride, ..
83         } = self;
84         VertexBufferDescription {
85             members,
86             stride,
87             input_rate: VertexInputRate::Instance { divisor },
88         }
89     }
90 }
91 
92 /// Information about a member of a vertex struct.
93 #[derive(Clone, Debug, PartialEq, Eq)]
94 pub struct VertexMemberInfo {
95     /// Offset of the member in bytes from the start of the struct.
96     pub offset: usize,
97     /// Attribute format of the member. Implicitly provides number of components.
98     pub format: Format,
99     /// Number of consecutive array elements or matrix columns using format. The corresponding
100     /// number of locations might defer depending on the size of the format.
101     pub num_elements: u32,
102 }
103 
104 impl VertexMemberInfo {
105     #[inline]
num_components(&self) -> u32106     pub fn num_components(&self) -> u32 {
107         self.format
108             .components()
109             .iter()
110             .filter(|&bits| *bits > 0)
111             .count() as u32
112     }
113 }
114 
115 #[cfg(test)]
116 mod tests {
117     use crate::format::Format;
118     use crate::pipeline::graphics::vertex_input::Vertex;
119 
120     use bytemuck::{Pod, Zeroable};
121 
122     #[test]
derive_vertex_multiple_names()123     fn derive_vertex_multiple_names() {
124         #[repr(C)]
125         #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
126         struct TestVertex {
127             #[name("b", "c")]
128             #[format(R32G32B32A32_SFLOAT)]
129             a: [f32; 16],
130         }
131 
132         let info = TestVertex::per_vertex();
133         let b = info.members.get("b").unwrap();
134         let c = info.members.get("c").unwrap();
135         assert_eq!(b.format, Format::R32G32B32A32_SFLOAT);
136         assert_eq!(c.format, Format::R32G32B32A32_SFLOAT);
137         assert_eq!(b.num_elements, 4);
138         assert_eq!(c.num_elements, 4);
139     }
140 
141     #[test]
derive_vertex_format()142     fn derive_vertex_format() {
143         #[repr(C)]
144         #[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
145         struct TestVertex {
146             #[format(R8_UNORM)]
147             unorm: u8,
148         }
149 
150         let info = TestVertex::per_instance();
151         let unorm = info.members.get("unorm").unwrap();
152         assert_eq!(unorm.format, Format::R8_UNORM);
153         assert_eq!(unorm.num_elements, 1);
154     }
155 }
156