// Copyright (c) 2016 The vulkano developers // Licensed under the Apache License, Version 2.0 // or the MIT // license , // at your option. All files in the project carrying such // notice may not be copied, modified, or distributed except // according to those terms. //! Configures how input vertices are assembled into primitives. use crate::{ buffer::BufferContents, macros::vulkan_enum, pipeline::{PartialStateMode, StateMode}, DeviceSize, }; /// The state in a graphics pipeline describing how the input assembly stage should behave. #[derive(Clone, Copy, Debug)] pub struct InputAssemblyState { /// The type of primitives. /// /// Note that some topologies require a feature to be enabled on the device. /// /// If set to `Dynamic`, the device API version must be at least 1.3, or the /// [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature must be /// enabled on the device. pub topology: PartialStateMode, /// If true, then when drawing with an index buffer, the special index value consisting of the /// maximum unsigned value (`0xff`, `0xffff` or `0xffffffff`) will tell the GPU that it is the /// end of the current primitive. A new primitive will restart at the next index. /// /// Primitive restart is mostly useful in combination with "strip" and "fan" topologies. "List" /// topologies require a feature to be enabled on the device when combined with primitive /// restart. /// /// If set to `Dynamic`, the device API version must be at least 1.3, or the /// [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature must /// be enabled on the device. pub primitive_restart_enable: StateMode, } impl InputAssemblyState { /// Creates an `InputAssemblyState` with the `TriangleList` topology and primitive restart /// disabled. #[inline] pub fn new() -> Self { Self { topology: PartialStateMode::Fixed(PrimitiveTopology::TriangleList), primitive_restart_enable: StateMode::Fixed(false), } } /// Sets the primitive topology. #[inline] pub fn topology(mut self, topology: PrimitiveTopology) -> Self { self.topology = PartialStateMode::Fixed(topology); self } /// Sets the primitive topology to dynamic. #[inline] pub fn topology_dynamic(mut self, topology_class: PrimitiveTopologyClass) -> Self { self.topology = PartialStateMode::Dynamic(topology_class); self } /// Enables primitive restart. #[inline] pub fn primitive_restart_enable(mut self) -> Self { self.primitive_restart_enable = StateMode::Fixed(true); self } /// Sets primitive restart enable to dynmamic. #[inline] pub fn primitive_restart_enable_dynamic(mut self) -> Self { self.primitive_restart_enable = StateMode::Dynamic; self } } impl Default for InputAssemblyState { /// Returns [`InputAssemblyState::new()`]. #[inline] fn default() -> Self { Self::new() } } vulkan_enum! { #[non_exhaustive] /// Describes how vertices must be grouped together to form primitives. /// /// When enabling primitive restart, "list" topologies require a feature to be enabled on the /// device: /// - The `PatchList` topology requires the /// [`primitive_topology_patch_list_restart`](crate::device::Features::primitive_topology_patch_list_restart) /// feature. /// - All other "list" topologies require the /// [`primitive_topology_list_restart`](crate::device::Features::primitive_topology_list_restart) /// feature. PrimitiveTopology impl { /// Returns the topology class of this topology. #[inline] pub fn class(self) -> PrimitiveTopologyClass { match self { Self::PointList => PrimitiveTopologyClass::Point, Self::LineList | Self::LineStrip | Self::LineListWithAdjacency | Self::LineStripWithAdjacency => PrimitiveTopologyClass::Line, Self::TriangleList | Self::TriangleStrip | Self::TriangleFan | Self::TriangleListWithAdjacency | Self::TriangleStripWithAdjacency => PrimitiveTopologyClass::Triangle, Self::PatchList => PrimitiveTopologyClass::Patch, } } } = PrimitiveTopology(i32); /// A series of separate point primitives. PointList = POINT_LIST, /// A series of separate line primitives. LineList = LINE_LIST, /// A series of consecutive line primitives, with consecutive lines sharing a vertex. LineStrip = LINE_STRIP, /// A series of separate triangle primitives. TriangleList = TRIANGLE_LIST, /// A series of consecutive triangle primitives, with consecutive triangles sharing an edge (two vertices). TriangleStrip = TRIANGLE_STRIP, /// A series of consecutive triangle primitives, with all triangles sharing a common vertex (the first). /// /// On [portability subset](crate::instance#portability-subset-devices-and-the-enumerate_portability-flag) /// devices, the [`triangle_fans`](crate::device::Features::triangle_fans) /// feature must be enabled on the device. TriangleFan = TRIANGLE_FAN, /// As `LineList, but with adjacency, used in combination with geometry shaders. Requires the /// [`geometry_shader`](crate::device::Features::geometry_shader) feature. LineListWithAdjacency = LINE_LIST_WITH_ADJACENCY, /// As `LineStrip`, but with adjacency, used in combination with geometry shaders. Requires the /// [`geometry_shader`](crate::device::Features::geometry_shader) feature. LineStripWithAdjacency = LINE_STRIP_WITH_ADJACENCY, /// As `TriangleList`, but with adjacency, used in combination with geometry shaders. Requires /// the [`geometry_shader`](crate::device::Features::geometry_shader) feature. TriangleListWithAdjacency = TRIANGLE_LIST_WITH_ADJACENCY, /// As `TriangleStrip`, but with adjacency, used in combination with geometry shaders. Requires /// the [`geometry_shader`](crate::device::Features::geometry_shader) feature. TriangleStripWithAdjacency = TRIANGLE_STRIP_WITH_ADJACENCY, /// Separate patch primitives, used in combination with tessellation shaders. Requires the /// [`tessellation_shader`](crate::device::Features::tessellation_shader) feature. PatchList = PATCH_LIST, } // TODO: use the #[default] attribute once it's stable. // See: https://github.com/rust-lang/rust/issues/87517 impl Default for PrimitiveTopology { #[inline] fn default() -> Self { PrimitiveTopology::TriangleList } } /// Describes the shape of a primitive topology. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum PrimitiveTopologyClass { Point, Line, Triangle, Patch, } impl PrimitiveTopologyClass { /// Returns a representative example of this topology class. pub(crate) fn example(self) -> PrimitiveTopology { match self { Self::Point => PrimitiveTopology::PointList, Self::Line => PrimitiveTopology::LineList, Self::Triangle => PrimitiveTopology::TriangleList, Self::Patch => PrimitiveTopology::PatchList, } } } /// Trait for types that can be used as indices by the GPU. pub unsafe trait Index: BufferContents + Sized { /// Returns the type of data. fn ty() -> IndexType; } unsafe impl Index for u8 { #[inline(always)] fn ty() -> IndexType { IndexType::U8 } } unsafe impl Index for u16 { #[inline(always)] fn ty() -> IndexType { IndexType::U16 } } unsafe impl Index for u32 { #[inline(always)] fn ty() -> IndexType { IndexType::U32 } } vulkan_enum! { #[non_exhaustive] /// An enumeration of all valid index types. IndexType = IndexType(i32); // TODO: document U8 = UINT8_EXT { device_extensions: [ext_index_type_uint8], }, // TODO: document U16 = UINT16, // TODO: document U32 = UINT32, /* TODO: enable // TODO: document None = NONE_KHR { device_extensions: [khr_acceleration_structure, nv_ray_tracing], },*/ } impl IndexType { /// Returns the size in bytes of indices of this type. #[inline] pub fn size(self) -> DeviceSize { match self { IndexType::U8 => 1, IndexType::U16 => 2, IndexType::U32 => 4, } } }