lambda/render/
pipeline.rs1use std::rc::Rc;
4
5use lambda_platform::gfx::shader::{
6 ShaderModuleBuilder,
7 ShaderModuleType,
8};
9
10use super::{
11 buffer::Buffer,
12 internal::RenderBackend,
13 shader::Shader,
14 RenderContext,
15};
16
17#[derive(Debug)]
18pub struct RenderPipeline {
19 pipeline: Rc<
20 lambda_platform::gfx::pipeline::RenderPipeline<
21 super::internal::RenderBackend,
22 >,
23 >,
24 buffers: Vec<Rc<Buffer>>,
25}
26
27impl RenderPipeline {
28 pub fn destroy(self, render_context: &RenderContext) {
30 logging::trace!("Destroying render pipeline");
31 Rc::try_unwrap(self.pipeline)
32 .expect("Failed to destroy render pipeline")
33 .destroy(render_context.internal_gpu());
34
35 logging::trace!("Destroying buffers");
36 for buffer in self.buffers {
37 Rc::try_unwrap(buffer)
38 .expect("Failed to get high level buffer.")
39 .destroy(render_context);
40 }
41
42 logging::info!("Render pipeline & all attached buffers destroyed");
43 }
44}
45
46impl RenderPipeline {
47 pub(super) fn buffers(&self) -> &Vec<Rc<Buffer>> {
48 return &self.buffers;
49 }
50
51 pub(super) fn into_platform_render_pipeline(
52 &self,
53 ) -> Rc<lambda_platform::gfx::pipeline::RenderPipeline<RenderBackend>> {
54 return self.pipeline.clone();
55 }
56}
57
58use lambda_platform::gfx::pipeline::PushConstantUpload;
59pub use lambda_platform::gfx::{
60 assembler::VertexAttribute,
61 pipeline::PipelineStage,
62};
63
64pub struct RenderPipelineBuilder {
65 push_constants: Vec<PushConstantUpload>,
66 buffers: Vec<Rc<Buffer>>,
67 attributes: Vec<VertexAttribute>,
68}
69
70impl RenderPipelineBuilder {
71 pub fn new() -> Self {
73 return Self {
74 push_constants: Vec::new(),
75 buffers: Vec::new(),
76 attributes: Vec::new(),
77 };
78 }
79
80 pub fn with_buffer(
82 mut self,
83 buffer: Buffer,
84 attributes: Vec<VertexAttribute>,
85 ) -> Self {
86 self.buffers.push(Rc::new(buffer));
87 self.attributes.extend(attributes);
88 return self;
89 }
90
91 pub fn with_push_constant(
94 mut self,
95 stage: PipelineStage,
96 bytes: u32,
97 ) -> Self {
98 self.push_constants.push((stage, 0..bytes));
99 return self;
100 }
101
102 pub fn build(
104 self,
105 render_context: &mut RenderContext,
106 render_pass: &super::render_pass::RenderPass,
107 vertex_shader: &Shader,
108 fragment_shader: Option<&Shader>,
109 ) -> RenderPipeline {
110 logging::debug!("Building render pipeline");
111
112 logging::debug!("Building vertex shader... ");
113 let vertex_shader_module = ShaderModuleBuilder::new().build(
114 render_context.internal_mutable_gpu(),
115 &vertex_shader.as_binary(),
116 ShaderModuleType::Vertex,
117 );
118
119 logging::debug!(
120 "\tDone. (Vertex shader: {} bytes)",
121 vertex_shader.as_binary().len()
122 );
123
124 logging::debug!("Building fragment shader... ");
125 let fragment_shader_module = match fragment_shader {
126 Some(shader) => Some(ShaderModuleBuilder::new().build(
127 render_context.internal_mutable_gpu(),
128 &shader.as_binary(),
129 ShaderModuleType::Fragment,
130 )),
131 None => None,
132 };
133
134 logging::debug!(
135 "\tDone. (Fragment shader: {} bytes)",
136 fragment_shader.map(|s| s.as_binary().len()).unwrap_or(0)
137 );
138
139 let builder = lambda_platform::gfx::pipeline::RenderPipelineBuilder::new();
140
141 let buffers = self.buffers;
142 let internal_buffers = buffers
143 .iter()
144 .map(|b| b.internal_buffer())
145 .collect::<Vec<_>>();
146
147 let render_pipeline = builder
148 .with_push_constants(self.push_constants.clone())
149 .build(
150 render_context.internal_gpu(),
151 render_pass.internal_render_pass(),
152 &vertex_shader_module,
153 fragment_shader_module.as_ref(),
154 &internal_buffers,
155 self.attributes.as_slice(),
156 );
157
158 vertex_shader_module.destroy(render_context.internal_mutable_gpu());
160 if let Some(fragment_shader_module) = fragment_shader_module {
161 fragment_shader_module.destroy(render_context.internal_mutable_gpu());
162 }
163
164 return RenderPipeline {
165 pipeline: Rc::new(render_pipeline),
166 buffers,
167 };
168 }
169}