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