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