blob: 0e4feda9a7cfe8a2ccc8ed8261d4f2c54409b96f [file] [log] [blame]
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// 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<PrimitiveTopology, PrimitiveTopologyClass>,
/// 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<bool>,
}
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,
}
}
}