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
//! Shading gates.
//!
//! A shading gate is a _pipeline node_ that allows to share shader [`Program`] for deeper nodes.
//!
//! [`Program`]: crate::shader::Program

use crate::{
  backend::shading_gate::ShadingGate as ShadingGateBackend,
  render_gate::RenderGate,
  shader::{Program, ProgramInterface, UniformInterface},
  vertex::Semantics,
};

/// A shading gate.
///
/// This is obtained after entering a [`PipelineGate`].
///
/// # Parametricity
///
/// - `B` is the backend type.
///
/// [`PipelineGate`]: crate::pipeline::PipelineGate
pub struct ShadingGate<'a, B> {
  pub(crate) backend: &'a mut B,
}

impl<'a, B> ShadingGate<'a, B>
where
  B: ShadingGateBackend,
{
  /// Enter a [`ShadingGate`] by using a shader [`Program`].
  ///
  /// The argument closure is given two arguments:
  ///
  /// - A [`ProgramInterface`], that allows to pass values (via [`ProgramInterface::set`]) to the
  ///   in-use shader [`Program`] and/or perform dynamic lookup of uniforms.
  /// - A [`RenderGate`], allowing to create deeper nodes in the graphics pipeline.
  pub fn shade<E, Sem, Out, Uni, F>(
    &mut self,
    program: &mut Program<B, Sem, Out, Uni>,
    f: F,
  ) -> Result<(), E>
  where
    Sem: Semantics,
    Uni: UniformInterface<B>,
    F: for<'b> FnOnce(ProgramInterface<'b, B>, &'b Uni, RenderGate<'b, B>) -> Result<(), E>,
  {
    unsafe {
      self.backend.apply_shader_program(&mut program.repr);
    }

    let render_gate = RenderGate {
      backend: self.backend,
    };
    let program_interface = ProgramInterface {
      program: &mut program.repr,
    };

    f(program_interface, &program.uni, render_gate)
  }
}