1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//! Input Assembler (IA) stage description.
//! The input assembler collects raw vertex and index data.

use crate::{format, IndexType};

/// Shader binding location.
pub type Location = u32;
/// Index of a vertex buffer.
pub type BufferIndex = u32;
/// Offset of an attribute from the start of the buffer, in bytes
pub type ElemOffset = u32;
/// Offset between attribute values, in bytes
pub type ElemStride = u32;
/// Number of instances between each advancement of the vertex buffer.
pub type InstanceRate = u8;
/// Number of vertices in a patch
pub type PatchSize = u8;

/// The rate at which to advance input data to shaders for the given buffer
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum VertexInputRate {
    /// Advance the buffer after every vertex
    Vertex,
    /// Advance the buffer after every instance
    Instance(InstanceRate),
}

impl VertexInputRate {
    /// Get the numeric representation of the rate
    pub fn as_uint(&self) -> u8 {
        match *self {
            VertexInputRate::Vertex => 0,
            VertexInputRate::Instance(divisor) => divisor,
        }
    }
}

/// A struct element descriptor.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Element<F> {
    /// Element format
    pub format: F,
    /// Offset from the beginning of the container, in bytes
    pub offset: ElemOffset,
}

/// Vertex buffer description. Notably, completely separate from resource `Descriptor`s
/// used in `DescriptorSet`s.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct VertexBufferDesc {
    /// Binding number of this vertex buffer. This binding number is
    /// used only for vertex buffers, and is completely separate from
    /// `Descriptor` and `DescriptorSet` bind points.
    pub binding: BufferIndex,
    /// Total container size, in bytes.
    /// Specifies the byte distance between two consecutive elements.
    pub stride: ElemStride,
    /// The rate at which to advance data for the given buffer
    ///
    /// i.e. the rate at which data passed to shaders will get advanced by
    /// `stride` bytes
    pub rate: VertexInputRate,
}

/// Vertex attribute description. Notably, completely separate from resource `Descriptor`s
/// used in `DescriptorSet`s.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct AttributeDesc {
    /// Attribute binding location in the shader. Attribute locations are
    /// shared between all vertex buffers in a pipeline, meaning that even if the
    /// data for this attribute comes from a different vertex buffer, it still cannot
    /// share the same location with another attribute.
    pub location: Location,
    /// Binding number of the associated vertex buffer.
    pub binding: BufferIndex,
    /// Attribute element description.
    pub element: Element<format::Format>,
}

/// Describes the type of geometric primitives,
/// created from vertex data.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(u8)]
pub enum Primitive {
    /// Each vertex represents a single point.
    PointList,
    /// Each pair of vertices represent a single line segment. For example, with `[a, b, c, d,
    /// e]`, `a` and `b` form a line, `c` and `d` form a line, and `e` is discarded.
    LineList,
    /// Every two consecutive vertices represent a single line segment. Visually forms a "path" of
    /// lines, as they are all connected. For example, with `[a, b, c]`, `a` and `b` form a line
    /// line, and `b` and `c` form a line.
    LineStrip,
    /// Each triplet of vertices represent a single triangle. For example, with `[a, b, c, d, e]`,
    /// `a`, `b`, and `c` form a triangle, `d` and `e` are discarded.
    TriangleList,
    /// Every three consecutive vertices represent a single triangle. For example, with `[a, b, c,
    /// d]`, `a`, `b`, and `c` form a triangle, and `b`, `c`, and `d` form a triangle.
    TriangleStrip,
    /// Patch list,
    /// used with shaders capable of producing primitives on their own (tessellation)
    PatchList(PatchSize),
}

/// All the information needed to create an input assembler.
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct InputAssemblerDesc {
    /// Type of the primitive
    pub primitive: Primitive,
    /// When adjacency information is enabled, every even-numbered vertex
    /// (every other starting from the first) represents an additional
    /// vertex for the primitive, while odd-numbered vertices (every other starting from the
    /// second) represent adjacent vertices.
    ///
    /// For example, with `[a, b, c, d, e, f, g, h]`, `[a, c,
    /// e, g]` form a triangle strip, and `[b, d, f, h]` are the adjacent vertices, where `b`, `d`,
    /// and `f` are adjacent to the first triangle in the strip, and `d`, `f`, and `h` are adjacent
    /// to the second.
    pub with_adjacency: bool,
    /// Describes whether or not primitive restart is supported for
    /// an input assembler. Primitive restart is a feature that
    /// allows a mark to be placed in an index buffer where it is
    /// is "broken" into multiple pieces of geometry.
    ///
    /// See <https://www.khronos.org/opengl/wiki/Vertex_Rendering#Primitive_Restart>
    /// for more detail.
    pub restart_index: Option<IndexType>,
}

impl InputAssemblerDesc {
    /// Create a new IA descriptor without primitive restart or adjucency.
    pub fn new(primitive: Primitive) -> Self {
        InputAssemblerDesc {
            primitive,
            with_adjacency: false,
            restart_index: None,
        }
    }
}