lambda_platform/gfx/
assembler.rs

1//! Primitive assembly for the graphics pipeline.
2
3pub use gfx_hal::pso::Element as VertexElement;
4use gfx_hal::pso::{
5  self,
6  AttributeDesc,
7  VertexBufferDesc,
8};
9
10use super::{
11  buffer::Buffer,
12  surface::ColorFormat,
13};
14
15/// Attributes for a vertex.
16#[derive(Debug, Clone)]
17pub struct VertexAttribute {
18  pub location: u32,
19  pub offset: u32,
20  pub element: VertexElement<ColorFormat>,
21}
22
23/// PrimitiveAssemblerBuilder for preparing PrimitiveAssemblers to use in the
24/// lambda-platform Rendering pipeline.
25pub struct PrimitiveAssemblerBuilder {
26  buffer_descriptions: Vec<VertexBufferDesc>,
27  attribute_descriptions: Vec<AttributeDesc>,
28}
29
30impl PrimitiveAssemblerBuilder {
31  pub fn new() -> Self {
32    return Self {
33      buffer_descriptions: Vec::new(),
34      attribute_descriptions: Vec::new(),
35    };
36  }
37
38  /// Build a primitive assembler given the lambda-platform vertex shader
39  /// module. Buffers & attributes do not have to be tied to
40  pub fn build<'shader, RenderBackend: gfx_hal::Backend>(
41    &'shader mut self,
42    vertex_shader: &'shader super::shader::ShaderModule<RenderBackend>,
43    buffers: Option<&Vec<&Buffer<RenderBackend>>>,
44    attributes: Option<&[VertexAttribute]>,
45  ) -> PrimitiveAssembler<'shader, RenderBackend> {
46    let binding = self.buffer_descriptions.len() as u32;
47
48    match (buffers, attributes) {
49      (Some(buffers), Some(attributes)) => {
50        logging::debug!(
51          "Building primitive assembler with buffers and attributes"
52        );
53        self.buffer_descriptions = buffers
54          .iter()
55          .map(|buffer| VertexBufferDesc {
56            binding,
57            stride: buffer.stride() as u32,
58            rate: pso::VertexInputRate::Vertex,
59          })
60          .collect();
61
62        self.attribute_descriptions = attributes
63          .iter()
64          .map(|attribute| {
65            return AttributeDesc {
66              location: attribute.location,
67              binding,
68              element: attribute.element,
69            };
70          })
71          .collect();
72      }
73      _ => {}
74    }
75
76    let primitive_assembler = pso::PrimitiveAssemblerDesc::Vertex {
77      buffers: self.buffer_descriptions.as_slice(),
78      attributes: self.attribute_descriptions.as_slice(),
79      input_assembler: pso::InputAssemblerDesc::new(
80        pso::Primitive::TriangleList,
81      ),
82      vertex: pso::EntryPoint {
83        entry: vertex_shader.entry(),
84        module: super::internal::module_for(vertex_shader),
85        specialization: vertex_shader.specializations().clone(),
86      },
87      tessellation: None,
88      geometry: None,
89    };
90
91    return PrimitiveAssembler::<'shader> {
92      primitive_assembler,
93    };
94  }
95}
96
97/// PrimitiveAssembler for used for describing how Vertex Shaders should
98/// construct primitives. Each constructed Primitive Assembler should be alive
99/// for as long as the shader module that created it is.
100pub struct PrimitiveAssembler<'shader, RenderBackend: gfx_hal::Backend> {
101  primitive_assembler: pso::PrimitiveAssemblerDesc<'shader, RenderBackend>,
102}
103
104impl<'shader, RenderBackend: gfx_hal::Backend>
105  PrimitiveAssembler<'shader, RenderBackend>
106{
107  // Get the internal primitive assembler.
108  pub(super) fn internal_primitive_assembler(
109    self,
110  ) -> pso::PrimitiveAssemblerDesc<'shader, RenderBackend> {
111    return self.primitive_assembler;
112  }
113}