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 input vertices are assembled into primitives. 11 12 use crate::{ 13 buffer::BufferContents, 14 macros::vulkan_enum, 15 pipeline::{PartialStateMode, StateMode}, 16 DeviceSize, 17 }; 18 19 /// The state in a graphics pipeline describing how the input assembly stage should behave. 20 #[derive(Clone, Copy, Debug)] 21 pub struct InputAssemblyState { 22 /// The type of primitives. 23 /// 24 /// Note that some topologies require a feature to be enabled on the device. 25 /// 26 /// If set to `Dynamic`, the device API version must be at least 1.3, or the 27 /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be 28 /// enabled on the device. 29 pub topology: PartialStateMode<PrimitiveTopology, PrimitiveTopologyClass>, 30 31 /// If true, then when drawing with an index buffer, the special index value consisting of the 32 /// maximum unsigned value (`0xff`, `0xffff` or `0xffffffff`) will tell the GPU that it is the 33 /// end of the current primitive. A new primitive will restart at the next index. 34 /// 35 /// Primitive restart is mostly useful in combination with "strip" and "fan" topologies. "List" 36 /// topologies require a feature to be enabled on the device when combined with primitive 37 /// restart. 38 /// 39 /// If set to `Dynamic`, the device API version must be at least 1.3, or the 40 /// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature must 41 /// be enabled on the device. 42 pub primitive_restart_enable: StateMode<bool>, 43 } 44 45 impl InputAssemblyState { 46 /// Creates an `InputAssemblyState` with the `TriangleList` topology and primitive restart 47 /// disabled. 48 #[inline] new() -> Self49 pub fn new() -> Self { 50 Self { 51 topology: PartialStateMode::Fixed(PrimitiveTopology::TriangleList), 52 primitive_restart_enable: StateMode::Fixed(false), 53 } 54 } 55 56 /// Sets the primitive topology. 57 #[inline] topology(mut self, topology: PrimitiveTopology) -> Self58 pub fn topology(mut self, topology: PrimitiveTopology) -> Self { 59 self.topology = PartialStateMode::Fixed(topology); 60 self 61 } 62 63 /// Sets the primitive topology to dynamic. 64 #[inline] topology_dynamic(mut self, topology_class: PrimitiveTopologyClass) -> Self65 pub fn topology_dynamic(mut self, topology_class: PrimitiveTopologyClass) -> Self { 66 self.topology = PartialStateMode::Dynamic(topology_class); 67 self 68 } 69 70 /// Enables primitive restart. 71 #[inline] primitive_restart_enable(mut self) -> Self72 pub fn primitive_restart_enable(mut self) -> Self { 73 self.primitive_restart_enable = StateMode::Fixed(true); 74 self 75 } 76 77 /// Sets primitive restart enable to dynmamic. 78 #[inline] primitive_restart_enable_dynamic(mut self) -> Self79 pub fn primitive_restart_enable_dynamic(mut self) -> Self { 80 self.primitive_restart_enable = StateMode::Dynamic; 81 self 82 } 83 } 84 85 impl Default for InputAssemblyState { 86 /// Returns [`InputAssemblyState::new()`]. 87 #[inline] default() -> Self88 fn default() -> Self { 89 Self::new() 90 } 91 } 92 93 vulkan_enum! { 94 #[non_exhaustive] 95 96 /// Describes how vertices must be grouped together to form primitives. 97 /// 98 /// When enabling primitive restart, "list" topologies require a feature to be enabled on the 99 /// device: 100 /// - The `PatchList` topology requires the 101 /// [`primitive_topology_patch_list_restart`](crate::device::Features::primitive_topology_patch_list_restart) 102 /// feature. 103 /// - All other "list" topologies require the 104 /// [`primitive_topology_list_restart`](crate::device::Features::primitive_topology_list_restart) 105 /// feature. 106 PrimitiveTopology impl { 107 /// Returns the topology class of this topology. 108 #[inline] 109 pub fn class(self) -> PrimitiveTopologyClass { 110 match self { 111 Self::PointList => PrimitiveTopologyClass::Point, 112 Self::LineList 113 | Self::LineStrip 114 | Self::LineListWithAdjacency 115 | Self::LineStripWithAdjacency => PrimitiveTopologyClass::Line, 116 Self::TriangleList 117 | Self::TriangleStrip 118 | Self::TriangleFan 119 | Self::TriangleListWithAdjacency 120 | Self::TriangleStripWithAdjacency => PrimitiveTopologyClass::Triangle, 121 Self::PatchList => PrimitiveTopologyClass::Patch, 122 } 123 } 124 } 125 = PrimitiveTopology(i32); 126 127 /// A series of separate point primitives. 128 PointList = POINT_LIST, 129 130 /// A series of separate line primitives. 131 LineList = LINE_LIST, 132 133 /// A series of consecutive line primitives, with consecutive lines sharing a vertex. 134 LineStrip = LINE_STRIP, 135 136 /// A series of separate triangle primitives. 137 TriangleList = TRIANGLE_LIST, 138 139 /// A series of consecutive triangle primitives, with consecutive triangles sharing an edge (two vertices). 140 TriangleStrip = TRIANGLE_STRIP, 141 142 /// A series of consecutive triangle primitives, with all triangles sharing a common vertex (the first). 143 /// 144 /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag) 145 /// devices, the [`triangle_fans`](crate::device::Features::triangle_fans) 146 /// feature must be enabled on the device. 147 TriangleFan = TRIANGLE_FAN, 148 149 /// As `LineList, but with adjacency, used in combination with geometry shaders. Requires the 150 /// [`geometry_shader`](crate::device::Features::geometry_shader) feature. 151 LineListWithAdjacency = LINE_LIST_WITH_ADJACENCY, 152 153 /// As `LineStrip`, but with adjacency, used in combination with geometry shaders. Requires the 154 /// [`geometry_shader`](crate::device::Features::geometry_shader) feature. 155 LineStripWithAdjacency = LINE_STRIP_WITH_ADJACENCY, 156 157 /// As `TriangleList`, but with adjacency, used in combination with geometry shaders. Requires 158 /// the [`geometry_shader`](crate::device::Features::geometry_shader) feature. 159 TriangleListWithAdjacency = TRIANGLE_LIST_WITH_ADJACENCY, 160 161 /// As `TriangleStrip`, but with adjacency, used in combination with geometry shaders. Requires 162 /// the [`geometry_shader`](crate::device::Features::geometry_shader) feature. 163 TriangleStripWithAdjacency = TRIANGLE_STRIP_WITH_ADJACENCY, 164 165 /// Separate patch primitives, used in combination with tessellation shaders. Requires the 166 /// [`tessellation_shader`](crate::device::Features::tessellation_shader) feature. 167 PatchList = PATCH_LIST, 168 169 } 170 171 // TODO: use the #[default] attribute once it's stable. 172 // See: https://github.com/rust-lang/rust/issues/87517 173 impl Default for PrimitiveTopology { 174 #[inline] default() -> Self175 fn default() -> Self { 176 PrimitiveTopology::TriangleList 177 } 178 } 179 180 /// Describes the shape of a primitive topology. 181 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 182 pub enum PrimitiveTopologyClass { 183 Point, 184 Line, 185 Triangle, 186 Patch, 187 } 188 189 impl PrimitiveTopologyClass { 190 /// Returns a representative example of this topology class. example(self) -> PrimitiveTopology191 pub(crate) fn example(self) -> PrimitiveTopology { 192 match self { 193 Self::Point => PrimitiveTopology::PointList, 194 Self::Line => PrimitiveTopology::LineList, 195 Self::Triangle => PrimitiveTopology::TriangleList, 196 Self::Patch => PrimitiveTopology::PatchList, 197 } 198 } 199 } 200 201 /// Trait for types that can be used as indices by the GPU. 202 pub unsafe trait Index: BufferContents + Sized { 203 /// Returns the type of data. ty() -> IndexType204 fn ty() -> IndexType; 205 } 206 207 unsafe impl Index for u8 { 208 #[inline(always)] ty() -> IndexType209 fn ty() -> IndexType { 210 IndexType::U8 211 } 212 } 213 214 unsafe impl Index for u16 { 215 #[inline(always)] ty() -> IndexType216 fn ty() -> IndexType { 217 IndexType::U16 218 } 219 } 220 221 unsafe impl Index for u32 { 222 #[inline(always)] ty() -> IndexType223 fn ty() -> IndexType { 224 IndexType::U32 225 } 226 } 227 228 vulkan_enum! { 229 #[non_exhaustive] 230 231 /// An enumeration of all valid index types. 232 IndexType = IndexType(i32); 233 234 // TODO: document 235 U8 = UINT8_EXT { 236 device_extensions: [ext_index_type_uint8], 237 }, 238 239 // TODO: document 240 U16 = UINT16, 241 242 // TODO: document 243 U32 = UINT32, 244 245 /* TODO: enable 246 // TODO: document 247 None = NONE_KHR { 248 device_extensions: [khr_acceleration_structure, nv_ray_tracing], 249 },*/ 250 } 251 252 impl IndexType { 253 /// Returns the size in bytes of indices of this type. 254 #[inline] size(self) -> DeviceSize255 pub fn size(self) -> DeviceSize { 256 match self { 257 IndexType::U8 => 1, 258 IndexType::U16 => 2, 259 IndexType::U32 => 4, 260 } 261 } 262 } 263