• 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 use super::VertexMemberInfo;
11 use crate::buffer::BufferAccess;
12 use crate::pipeline::shader::ShaderInterface;
13 use crate::pipeline::vertex::IncompatibleVertexDefinitionError;
14 use crate::pipeline::vertex::Vertex;
15 use crate::pipeline::vertex::VertexDefinition;
16 use crate::pipeline::vertex::VertexInput;
17 use crate::pipeline::vertex::VertexInputAttribute;
18 use crate::pipeline::vertex::VertexInputBinding;
19 use crate::pipeline::vertex::VertexInputRate;
20 use crate::pipeline::vertex::VertexSource;
21 use crate::DeviceSize;
22 use std::mem;
23 use std::sync::Arc;
24 
25 /// A vertex definition for any number of vertex and instance buffers.
26 #[derive(Clone, Default)]
27 pub struct BuffersDefinition(Vec<VertexBuffer>);
28 
29 #[derive(Clone, Copy)]
30 struct VertexBuffer {
31     info_fn: fn(&str) -> Option<VertexMemberInfo>,
32     stride: u32,
33     input_rate: VertexInputRate,
34 }
35 
36 impl From<VertexBuffer> for VertexInputBinding {
37     #[inline]
from(val: VertexBuffer) -> Self38     fn from(val: VertexBuffer) -> Self {
39         Self {
40             stride: val.stride,
41             input_rate: val.input_rate,
42         }
43     }
44 }
45 
46 impl BuffersDefinition {
47     /// Constructs a new definition.
new() -> Self48     pub fn new() -> Self {
49         BuffersDefinition(Vec::new())
50     }
51 
52     /// Adds a new vertex buffer containing elements of type `V` to the definition.
vertex<V: Vertex>(mut self) -> Self53     pub fn vertex<V: Vertex>(mut self) -> Self {
54         self.0.push(VertexBuffer {
55             info_fn: V::member,
56             stride: mem::size_of::<V>() as u32,
57             input_rate: VertexInputRate::Vertex,
58         });
59         self
60     }
61 
62     /// Adds a new instance buffer containing elements of type `V` to the definition.
instance<V: Vertex>(mut self) -> Self63     pub fn instance<V: Vertex>(mut self) -> Self {
64         self.0.push(VertexBuffer {
65             info_fn: V::member,
66             stride: mem::size_of::<V>() as u32,
67             input_rate: VertexInputRate::Instance { divisor: 1 },
68         });
69         self
70     }
71 
72     /// Adds a new instance buffer containing elements of type `V` to the definition, with the
73     /// specified input rate divisor.
74     ///
75     /// This requires the
76     /// [`vertex_attribute_instance_rate_divisor`](crate::device::Features::vertex_attribute_instance_rate_divisor)
77     /// feature has been enabled on the device, unless `divisor` is 1.
78     ///
79     /// `divisor` can be 0 if the
80     /// [`vertex_attribute_instance_rate_zero_divisor`](crate::device::Features::vertex_attribute_instance_rate_zero_divisor)
81     /// feature is also enabled. This means that every vertex will use the same vertex and instance
82     /// data.
instance_with_divisor<V: Vertex>(mut self, divisor: u32) -> Self83     pub fn instance_with_divisor<V: Vertex>(mut self, divisor: u32) -> Self {
84         self.0.push(VertexBuffer {
85             info_fn: V::member,
86             stride: mem::size_of::<V>() as u32,
87             input_rate: VertexInputRate::Instance { divisor },
88         });
89         self
90     }
91 }
92 
93 unsafe impl VertexDefinition for BuffersDefinition {
definition( &self, interface: &ShaderInterface, ) -> Result<VertexInput, IncompatibleVertexDefinitionError>94     fn definition(
95         &self,
96         interface: &ShaderInterface,
97     ) -> Result<VertexInput, IncompatibleVertexDefinitionError> {
98         let bindings = self
99             .0
100             .iter()
101             .enumerate()
102             .map(|(binding, &buffer)| (binding as u32, buffer.into()));
103         let mut attributes: Vec<(u32, VertexInputAttribute)> = Vec::new();
104 
105         for element in interface.elements() {
106             let name = element.name.as_ref().unwrap();
107 
108             let (infos, binding) = self
109                 .0
110                 .iter()
111                 .enumerate()
112                 .find_map(|(binding, buffer)| {
113                     (buffer.info_fn)(name).map(|infos| (infos, binding as u32))
114                 })
115                 .ok_or_else(||
116                     // TODO: move this check to GraphicsPipelineBuilder
117                     IncompatibleVertexDefinitionError::MissingAttribute {
118                         attribute: name.clone().into_owned(),
119                     })?;
120 
121             if !infos.ty.matches(
122                 infos.array_size,
123                 element.format,
124                 element.location.end - element.location.start,
125             ) {
126                 // TODO: move this check to GraphicsPipelineBuilder
127                 return Err(IncompatibleVertexDefinitionError::FormatMismatch {
128                     attribute: name.clone().into_owned(),
129                     shader: (
130                         element.format,
131                         (element.location.end - element.location.start) as usize,
132                     ),
133                     definition: (infos.ty, infos.array_size),
134                 });
135             }
136 
137             let mut offset = infos.offset as DeviceSize;
138             for location in element.location.clone() {
139                 attributes.push((
140                     location,
141                     VertexInputAttribute {
142                         binding,
143                         format: element.format,
144                         offset: offset as u32,
145                     },
146                 ));
147                 offset += element.format.size().unwrap();
148             }
149         }
150 
151         Ok(VertexInput::new(bindings, attributes))
152     }
153 }
154 
155 unsafe impl VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>> for BuffersDefinition {
156     #[inline]
decode( &self, source: Vec<Arc<dyn BufferAccess + Send + Sync>>, ) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize)157     fn decode(
158         &self,
159         source: Vec<Arc<dyn BufferAccess + Send + Sync>>,
160     ) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize) {
161         let result = source
162             .into_iter()
163             .map(|source| Box::new(source) as Box<_>)
164             .collect::<Vec<_>>();
165         let (vertices, instances) = self.vertices_instances(&result);
166         (result, vertices, instances)
167     }
168 }
169 
170 unsafe impl<B> VertexSource<B> for BuffersDefinition
171 where
172     B: BufferAccess + Send + Sync + 'static,
173 {
174     #[inline]
decode(&self, source: B) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize)175     fn decode(&self, source: B) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize) {
176         let result = vec![Box::new(source) as Box<_>];
177         let (vertices, instances) = self.vertices_instances(&result);
178         (result, vertices, instances)
179     }
180 }
181 
182 unsafe impl<B1, B2> VertexSource<(B1, B2)> for BuffersDefinition
183 where
184     B1: BufferAccess + Send + Sync + 'static,
185     B2: BufferAccess + Send + Sync + 'static,
186 {
187     #[inline]
decode(&self, source: (B1, B2)) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize)188     fn decode(&self, source: (B1, B2)) -> (Vec<Box<dyn BufferAccess + Send + Sync>>, usize, usize) {
189         let result = vec![Box::new(source.0) as Box<_>, Box::new(source.1) as Box<_>];
190         let (vertices, instances) = self.vertices_instances(&result);
191         (result, vertices, instances)
192     }
193 }
194 
195 impl BuffersDefinition {
vertices_instances(&self, source: &[Box<dyn BufferAccess + Send + Sync>]) -> (usize, usize)196     fn vertices_instances(&self, source: &[Box<dyn BufferAccess + Send + Sync>]) -> (usize, usize) {
197         assert_eq!(source.len(), self.0.len());
198         let mut vertices = None;
199         let mut instances = None;
200 
201         for (buffer, source) in self.0.iter().zip(source) {
202             let items = (source.size() / buffer.stride as DeviceSize) as usize;
203             let (items, count) = match buffer.input_rate {
204                 VertexInputRate::Vertex => (items, &mut vertices),
205                 VertexInputRate::Instance { divisor } => (
206                     if divisor == 0 {
207                         // A divisor of 0 means the same instance data is used for all instances,
208                         // so we can draw any number of instances from a single element.
209                         // The buffer must contain at least one element though.
210                         if items == 0 {
211                             0
212                         } else {
213                             usize::MAX
214                         }
215                     } else {
216                         // If divisor is 2, we use only half the amount of data from the source buffer,
217                         // so the number of instances that can be drawn is twice as large.
218                         items * divisor as usize
219                     },
220                     &mut instances,
221                 ),
222             };
223 
224             if let Some(count) = count {
225                 *count = std::cmp::min(*count, items);
226             } else {
227                 *count = Some(items);
228             }
229         }
230 
231         // TODO: find some way to let the user specify these when drawing
232         (vertices.unwrap_or(1), instances.unwrap_or(1))
233     }
234 }
235