• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016 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 //! Configures how data from vertex buffers is read into vertex shader input locations.
11 //!
12 //! The vertex input stage is the stage where data is read from a buffer and fed into the vertex
13 //! shader. After each invocation of the vertex shader, the pipeline then proceeds to the input
14 //! assembly stage.
15 //!
16 //! # Input locations and components
17 //!
18 //! Input data is assigned per shader input location. Locations are set by adding the `location`
19 //! layout qualifier to an input variable in GLSL. A single location contains four data elements,
20 //! named "components", which are each 32 bits in size. These correspond to the `x`, `y`, `z` and
21 //! `w` (or equivalently `r`, `g`, `b`, `a`) components of a `vec4` inside the shader.
22 //! A component can contain at most one value, and data types that are smaller than 32 bits will
23 //! still take up a whole component, so a single `i8vec4` variable will still take up all four
24 //! components in a location, even if not all bits are actually used.
25 //!
26 //! A variable may take up fewer than four components. For example, a single `float` takes up only
27 //! one component, a `vec2` takes up two, and so on. Using the `component` layout qualifier in GLSL,
28 //! it is possible to fit multiple variables into a single four-component location slot, as long
29 //! as the components of each variable don't overlap.
30 //!
31 //! If the input variable is an array, then it takes up a series of consecutive locations. Each
32 //! element of the array always starts at a new location, regardless of whether there is still room
33 //! in the previous one. So, for example, an array of three `vec2` takes three locations, since
34 //! `vec2` alone needs one location. An array can be decorated with the `component` qualifier as
35 //! well; this is equivalent to applying the qualifier to every element of the array. If elements do
36 //! not use all components in their locations, those free components can be filled with additional
37 //! variables, just like for non-array types.
38 //!
39 //! Matrices are laid out as if they were an array of column vectors. Thus, a `mat4x3` is laid out
40 //! as an array of four `vec3`s, `mat2x4` as two `vec4`s. As with individual vectors, each column of
41 //! the matrix uses up as many components of its location as there are rows in the matrix, and the
42 //! remaining components are available for additional variables as described above. However, it is
43 //! not possible to use the `component` qualifier on a matrix.
44 //!
45 //! If a 64-bit value is to be passed to a shader, it will take up two adjacent components. Vectors
46 //! of 64-bit values are correspondingly twice as large: `dvec2` takes up all four components of a
47 //! location, `dvec4` takes two full locations, while `dvec3` takes one full location and the first
48 //! two components of the next. An array or matrix of a 64-bit type is made up of multiple adjacent
49 //! 64-bit elements, just like for smaller types: each new element starts at a fresh location.
50 //!
51 //! # Input attributes
52 //!
53 //! An input attribute is a mapping between data in a vertex buffer and the locations and components
54 //! of the vertex shader.
55 //!
56 //! Input attributes are assigned on a per-location basis; it is not possible to assign attributes
57 //! to individual components. Instead, each attribute specifies up to four values to be read from
58 //! the vertex buffer at once, which are then mapped to the four components of the given location.
59 //! Like the texels in an image, each attribute's data format in a vertex buffer is described by a
60 //! [`Format`]. The input data doesn't have to be an actual color, the format simply describes the
61 //! type, size and layout of the data for the four input components. For example,
62 //! `Format::R32G32B32A32_SFLOAT` will read four `f32` values from the vertex buffer and assigns
63 //! them to the four components of the attribute's location.
64 //!
65 //! It is possible to specify a `Format` that contains less than four components. In this case, the
66 //! missing components are given default values: the first three components default to 0, while the
67 //! fourth defaults to 1. This means that you can, for example, store only the `x`, `y` and `z`
68 //! components of a vertex position in a vertex buffer, and have the vertex input state
69 //! automatically set the `w` value to 1 for you. An exception to this are 64-bit values: these do
70 //! *not* receive default values, meaning that components that are missing from the format are
71 //! assigned no value and must not be used in the shader at all.
72 //!
73 //! When matching attribute formats to shader input types, the following rules apply:
74 //! - Signed integers in the shader must have an attribute format with a `SINT` type.
75 //! - Unsigned integers in the shader must have an attribute format with a `UINT` type.
76 //! - Floating point values in the shader must have an attribute format with a type other than
77 //!   `SINT` or `UINT`. This includes `SFLOAT`, `UFLOAT` and `SRGB`, but also `SNORM`, `UNORM`,
78 //!   `SSCALED` and `USCALED`.
79 //! - 64-bit values in the shader must have a 64-bit attribute format.
80 //! - 32-bit and smaller values in the shader must have a 32-bit or smaller attribute format, but
81 //!   the exact number of bits doesn't matter. For example, `Format::R8G8B8A8_UNORM` can be used
82 //!   with a `vec4` in the shader.
83 //!
84 //! # Input bindings
85 //!
86 //! An input binding is a definition of a Vulkan buffer that contains the actual data from which
87 //! each input attribute is to be read. The buffer itself is referred to as a "vertex buffer", and
88 //! is set during drawing with the
89 //! [`bind_vertex_buffers`](crate::command_buffer::AutoCommandBufferBuilder::bind_vertex_buffers)
90 //! command.
91 //!
92 //! The data in a vertex buffer is typically arranged into an array, where each array element
93 //! contains the data for a single vertex shader invocation. When deciding which element read from
94 //! the vertex buffer for a given vertex and instance number, each binding has an "input rate".
95 //! If the input rate is `Vertex`, then the vertex input state advances to the next element of that
96 //! buffer each time a new vertex number is processed. Likewise, if the input rate is `Instance`,
97 //! it advances to the next element for each new instance number. Different bindings can have
98 //! different input rates, and it's also possible to have multiple bindings with the same input
99 //! rate.
100 
101 #[allow(deprecated)]
102 pub use self::{
103     buffers::BuffersDefinition,
104     collection::VertexBuffersCollection,
105     definition::{IncompatibleVertexDefinitionError, VertexDefinition},
106     impl_vertex::VertexMember,
107     vertex::{Vertex, VertexBufferDescription, VertexMemberInfo},
108 };
109 use crate::format::Format;
110 use ahash::HashMap;
111 
112 mod buffers;
113 mod collection;
114 mod definition;
115 mod impl_vertex;
116 mod vertex;
117 
118 /// The state in a graphics pipeline describing how the vertex input stage should behave.
119 #[derive(Clone, Debug, Default)]
120 pub struct VertexInputState {
121     /// A description of the vertex buffers that the vertex input stage will read from.
122     pub bindings: HashMap<u32, VertexInputBindingDescription>,
123 
124     /// Describes, for each shader input location, the mapping between elements in a vertex buffer
125     /// and the components of that location in the shader.
126     pub attributes: HashMap<u32, VertexInputAttributeDescription>,
127 }
128 
129 impl VertexInputState {
130     /// Constructs a new `VertexInputState` with no bindings or attributes.
131     #[inline]
new() -> VertexInputState132     pub fn new() -> VertexInputState {
133         VertexInputState {
134             bindings: Default::default(),
135             attributes: Default::default(),
136         }
137     }
138 
139     /// Adds a single binding.
140     #[inline]
binding(mut self, binding: u32, description: VertexInputBindingDescription) -> Self141     pub fn binding(mut self, binding: u32, description: VertexInputBindingDescription) -> Self {
142         self.bindings.insert(binding, description);
143         self
144     }
145 
146     /// Sets all bindings.
bindings( mut self, bindings: impl IntoIterator<Item = (u32, VertexInputBindingDescription)>, ) -> Self147     pub fn bindings(
148         mut self,
149         bindings: impl IntoIterator<Item = (u32, VertexInputBindingDescription)>,
150     ) -> Self {
151         self.bindings = bindings.into_iter().collect();
152         self
153     }
154 
155     /// Adds a single attribute.
156     #[inline]
attribute( mut self, location: u32, description: VertexInputAttributeDescription, ) -> Self157     pub fn attribute(
158         mut self,
159         location: u32,
160         description: VertexInputAttributeDescription,
161     ) -> Self {
162         self.attributes.insert(location, description);
163         self
164     }
165 
166     /// Sets all attributes.
attributes( mut self, attributes: impl IntoIterator<Item = (u32, VertexInputAttributeDescription)>, ) -> Self167     pub fn attributes(
168         mut self,
169         attributes: impl IntoIterator<Item = (u32, VertexInputAttributeDescription)>,
170     ) -> Self {
171         self.attributes = attributes.into_iter().collect();
172         self
173     }
174 }
175 
176 /// Describes a single vertex buffer binding.
177 #[derive(Clone, Debug)]
178 pub struct VertexInputBindingDescription {
179     /// The number of bytes from the start of one element in the vertex buffer to the start of the
180     /// next element. This can be simply the size of the data in each element, but larger strides
181     /// are possible.
182     pub stride: u32,
183 
184     /// How often the vertex input should advance to the next element.
185     pub input_rate: VertexInputRate,
186 }
187 
188 /// Describes a single vertex buffer attribute mapping.
189 #[derive(Clone, Copy, Debug)]
190 pub struct VertexInputAttributeDescription {
191     /// The vertex buffer binding number that this attribute should take its data from.
192     pub binding: u32,
193 
194     /// The size and type of the vertex data.
195     pub format: Format,
196 
197     /// Number of bytes between the start of a vertex buffer element and the location of attribute.
198     ///
199     /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag)
200     /// devices, if the sum of `offset + format.block_size()` is greater than the `stride` of
201     /// `binding`, the
202     /// [`vertex_attribute_access_beyond_stride`](crate::device::Features::vertex_attribute_access_beyond_stride)
203     /// feature must be enabled on the device.
204     pub offset: u32,
205 }
206 
207 /// How the vertex source should be unrolled.
208 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
209 pub enum VertexInputRate {
210     /// Each element of the source corresponds to a vertex.
211     Vertex,
212 
213     /// Each element of the source corresponds to an instance.
214     ///
215     /// `divisor` indicates how many consecutive instances will use the same instance buffer data.
216     /// This value must be 1, unless the [`vertex_attribute_instance_rate_divisor`] feature has
217     /// been enabled on the device.
218     ///
219     /// `divisor` can be 0 if the [`vertex_attribute_instance_rate_zero_divisor`] feature is also
220     /// enabled. This means that every vertex will use the same vertex and instance data.
221     ///
222     /// [`vertex_attribute_instance_rate_divisor`]: crate::device::Features::vertex_attribute_instance_rate_divisor
223     /// [`vertex_attribute_instance_rate_zero_divisor`]: crate::device::Features::vertex_attribute_instance_rate_zero_divisor
224     Instance { divisor: u32 },
225 }
226 
227 impl From<VertexInputRate> for ash::vk::VertexInputRate {
228     #[inline]
from(val: VertexInputRate) -> Self229     fn from(val: VertexInputRate) -> Self {
230         match val {
231             VertexInputRate::Vertex => ash::vk::VertexInputRate::VERTEX,
232             VertexInputRate::Instance { .. } => ash::vk::VertexInputRate::INSTANCE,
233         }
234     }
235 }
236