Skip to content

Commit 8c20517

Browse files
committed
[update] the render context to take in the pipeline & renderers in exchange for a resource ID to simplify render commands.
1 parent abb0af4 commit 8c20517

5 files changed

Lines changed: 104 additions & 89 deletions

File tree

lambda/src/core/render/command.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,25 @@ pub enum RenderCommand {
2424
viewports: Vec<super::viewport::Viewport>,
2525
},
2626
SetPipeline {
27-
pipeline: Rc<super::pipeline::RenderPipeline>,
27+
pipeline: super::ResourceId,
2828
},
2929
/// Begins the render pass.
3030
BeginRenderPass {
31-
render_pass: Rc<super::render_pass::RenderPass>,
31+
render_pass: super::ResourceId,
3232
viewport: super::viewport::Viewport,
3333
},
3434
/// Ends the render pass.
3535
EndRenderPass,
3636
PushConstants {
37-
pipeline: Rc<super::pipeline::RenderPipeline>,
37+
pipeline: super::ResourceId,
3838
stage: super::pipeline::PipelineStage,
3939
offset: u32,
4040
bytes: Vec<u32>,
4141
},
4242
/// Draws a graphical primitive.
43-
Draw { vertices: Range<u32> },
43+
Draw {
44+
vertices: Range<u32>,
45+
},
4446
}
4547

4648
impl RenderCommand {
@@ -76,12 +78,17 @@ impl RenderCommand {
7678
viewport,
7779
} => {
7880
let surface = surface_from_context(render_context);
79-
let render_pass = render_pass.into_gfx_render_pass();
80-
let frame_buffer =
81-
render_context.allocate_and_get_frame_buffer(render_pass.as_ref());
81+
let frame_buffer = render_context.allocate_and_get_frame_buffer(
82+
render_context
83+
.get_render_pass(render_pass)
84+
.into_gfx_render_pass()
85+
.as_ref(),
86+
);
8287

8388
PlatformRenderCommand::BeginRenderPass {
84-
render_pass: render_pass.clone(),
89+
render_pass: render_context
90+
.get_render_pass(render_pass)
91+
.into_gfx_render_pass(),
8592
surface: surface.clone(),
8693
frame_buffer: frame_buffer.clone(),
8794
viewport: viewport.into_gfx_viewport(),
@@ -90,7 +97,11 @@ impl RenderCommand {
9097
RenderCommand::EndRenderPass => PlatformRenderCommand::EndRenderPass,
9198
RenderCommand::SetPipeline { pipeline } => {
9299
PlatformRenderCommand::AttachGraphicsPipeline {
93-
pipeline: pipeline.into_platform_render_pipeline(),
100+
pipeline: render_context
101+
.render_pipelines
102+
.get(pipeline)
103+
.unwrap()
104+
.into_platform_render_pipeline(),
94105
}
95106
}
96107
RenderCommand::PushConstants {
@@ -99,7 +110,11 @@ impl RenderCommand {
99110
offset,
100111
bytes,
101112
} => PlatformRenderCommand::PushConstants {
102-
pipeline: pipeline.into_platform_render_pipeline(),
113+
pipeline: render_context
114+
.render_pipelines
115+
.get(pipeline)
116+
.unwrap()
117+
.into_platform_render_pipeline(),
103118
stage,
104119
offset,
105120
bytes,

lambda/src/core/render/mod.rs

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ use lambda_platform::gfx::{
2222
},
2323
framebuffer::FramebufferBuilder,
2424
surface::SwapchainBuilder,
25-
viewport::ViewPort,
2625
};
2726

2827
use self::{
@@ -104,7 +103,6 @@ impl RenderContextBuilder {
104103
submission_fence: Some(submission_fence),
105104
render_semaphore: Some(render_semaphore),
106105
command_pool: Some(command_pool),
107-
viewports: vec![],
108106
render_passes: vec![],
109107
render_pipelines: vec![],
110108
};
@@ -123,12 +121,29 @@ pub struct RenderContext {
123121
Option<internal::RenderSubmissionFence<internal::RenderBackend>>,
124122
render_semaphore: Option<internal::RenderSemaphore<internal::RenderBackend>>,
125123
command_pool: Option<internal::CommandPool<internal::RenderBackend>>,
126-
render_passes: Vec<Option<RenderPass>>,
127-
render_pipelines: Vec<Option<RenderPipeline>>,
128-
viewports: Vec<ViewPort>,
124+
render_passes: Vec<RenderPass>,
125+
render_pipelines: Vec<RenderPipeline>,
129126
}
130127

128+
pub type ResourceId = usize;
129+
131130
impl RenderContext {
131+
/// Permanently transfer a render pipeline to the render context in exchange
132+
/// for a resource ID that you can use in render commands.
133+
pub fn attach_pipeline(&mut self, pipeline: RenderPipeline) -> ResourceId {
134+
let index = self.render_pipelines.len();
135+
self.render_pipelines.push(pipeline);
136+
return index;
137+
}
138+
139+
/// Permanently transfer a render pipeline to the render context in exchange
140+
/// for a resource ID that you can use in render commands.
141+
pub fn attach_render_pass(&mut self, render_pass: RenderPass) -> ResourceId {
142+
let index = self.render_passes.len();
143+
self.render_passes.push(render_pass);
144+
return index;
145+
}
146+
132147
/// destroys the RenderContext and all associated resources.
133148
pub fn destroy(mut self) {
134149
println!("{} will now start destroying resources.", self.name);
@@ -147,30 +162,32 @@ impl RenderContext {
147162
.expect("Couldn't take the rendering semaphore from the context and destroy it.")
148163
.destroy(&self.gpu);
149164

165+
self
166+
.command_pool
167+
.as_mut()
168+
.unwrap()
169+
.deallocate_command_buffer("primary");
170+
171+
self
172+
.command_pool
173+
.take()
174+
.expect("Couldn't take the command pool from the context and destroy it.")
175+
.destroy(&self.gpu);
176+
150177
// Destroy render passes.
151178
let mut render_passes = vec![];
152179
swap(&mut self.render_passes, &mut render_passes);
153180

154-
for render_pass in &mut render_passes {
155-
render_pass
156-
.take()
157-
.expect(
158-
"Couldn't take the render pass from the context and destroy it.",
159-
)
160-
.destroy(&self);
181+
for render_pass in render_passes {
182+
render_pass.destroy(&self);
161183
}
162184

163185
// Destroy render pipelines.
164186
let mut render_pipelines = vec![];
165187
swap(&mut self.render_pipelines, &mut render_pipelines);
166188

167-
for render_pipeline in &mut render_pipelines {
168-
render_pipeline
169-
.take()
170-
.expect(
171-
"Couldn't take the render pipeline from the context and destroy it.",
172-
)
173-
.destroy(&self);
189+
for render_pipeline in render_pipelines {
190+
render_pipeline.destroy(&self);
174191
}
175192

176193
// Takes the inner surface and destroys it.
@@ -232,7 +249,6 @@ impl RenderContext {
232249
command_buffer.issue_commands(platform_command_list);
233250
command_buffer.issue_command(PlatformRenderCommand::EndRecording);
234251

235-
println!("[INFO] {} will now submit commands to the GPU.", self.name);
236252
self.gpu.submit_command_buffer(
237253
&mut command_buffer,
238254
vec![self.render_semaphore.as_ref().unwrap()],
@@ -242,7 +258,6 @@ impl RenderContext {
242258
.expect("Failed to get mutable reference to submission fence."),
243259
);
244260

245-
println!("[INFO] {} will now render to the surface.", self.name);
246261
self
247262
.gpu
248263
.render_to_surface(
@@ -252,15 +267,10 @@ impl RenderContext {
252267
)
253268
.expect("Failed to render to the surface");
254269

255-
println!(
256-
"[INFO] {} will now wait for the GPU to finish rendering.",
257-
self.name
258-
);
259270
match self.frame_buffer {
260271
Some(_) => {
261272
Rc::try_unwrap(self.frame_buffer.take().unwrap())
262-
.ok()
263-
.unwrap()
273+
.expect("Failed to unwrap the frame buffer.")
264274
.destroy(&self.gpu);
265275
}
266276
None => {}
@@ -276,6 +286,14 @@ impl RenderContext {
276286
.apply_swapchain(&self.gpu, swapchain, 1_000_000_000)
277287
.expect("Failed to apply the swapchain to the surface while attempting to resize.");
278288
}
289+
290+
pub fn get_render_pass(&self, id: ResourceId) -> &RenderPass {
291+
return &self.render_passes[id];
292+
}
293+
294+
pub fn get_render_pipeline(&mut self, id: ResourceId) -> &RenderPipeline {
295+
return &self.render_pipelines[id];
296+
}
279297
}
280298

281299
type PlatformRenderCommand = Command<internal::RenderBackend>;

lambda/src/runtimes/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ impl Runtime for GenericRuntime {
156156
event: RuntimeEvent::Shutdown,
157157
issued_at: Instant::now(),
158158
});
159+
160+
*control_flow = ControlFlow::Exit;
159161
}
160162
WinitWindowEvent::Resized(dims) => {
161163
active_render_context
@@ -292,7 +294,6 @@ impl Runtime for GenericRuntime {
292294
component
293295
.on_renderer_detached(active_render_context.as_mut().unwrap());
294296
}
295-
*control_flow = ControlFlow::Exit;
296297
}
297298
},
298299
_ => {

tools/lambda_rs_demo/src/main.rs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,8 @@ use lambda::{
1515
},
1616
render::{
1717
command::RenderCommand,
18-
pipeline::{
19-
self,
20-
RenderPipeline,
21-
},
22-
render_pass::{
23-
self,
24-
RenderPass,
25-
},
18+
pipeline,
19+
render_pass,
2620
shader::{
2721
Shader,
2822
ShaderBuilder,
@@ -39,8 +33,8 @@ use lambda::{
3933
pub struct DemoComponent {
4034
triangle_vertex: Shader,
4135
vertex_shader: Shader,
42-
render_pass: Option<Rc<RenderPass>>,
43-
render_pipeline: Option<Rc<RenderPipeline>>,
36+
render_pass_id: Option<lambda::core::render::ResourceId>,
37+
render_pipeline_id: Option<lambda::core::render::ResourceId>,
4438
width: u32,
4539
height: u32,
4640
}
@@ -119,18 +113,18 @@ impl RenderableComponent<Events> for DemoComponent {
119113
) {
120114
println!("Attached the demo component to the renderer");
121115
let render_pass =
122-
Rc::new(render_pass::RenderPassBuilder::new().build(&render_context));
123-
124-
self.render_pass = Some(render_pass.clone());
116+
render_pass::RenderPassBuilder::new().build(&render_context);
125117

126-
let pipeline = Rc::new(pipeline::RenderPipelineBuilder::new().build(
118+
let pipeline = pipeline::RenderPipelineBuilder::new().build(
127119
render_context,
128-
&self.render_pass.as_ref().unwrap(),
120+
&render_pass,
129121
&self.vertex_shader,
130122
&self.triangle_vertex,
131-
));
123+
);
132124

133-
self.render_pipeline = Some(pipeline.clone());
125+
// Attach the render pass and pipeline to the render context
126+
self.render_pass_id = Some(render_context.attach_render_pass(render_pass));
127+
self.render_pipeline_id = Some(render_context.attach_pipeline(pipeline));
134128
}
135129

136130
fn on_render(
@@ -152,19 +146,13 @@ impl RenderableComponent<Events> for DemoComponent {
152146
},
153147
RenderCommand::SetPipeline {
154148
pipeline: self
155-
.render_pipeline
156-
.as_ref()
157-
.expect(
158-
"No render pipeline set while trying to issue a render command.",
159-
)
160-
.clone(),
149+
.render_pipeline_id
150+
.expect("No pipeline attached to the component"),
161151
},
162152
RenderCommand::BeginRenderPass {
163153
render_pass: self
164-
.render_pass
165-
.as_ref()
166-
.expect("Cannot begin the render pass when it doesn't exist.")
167-
.clone(),
154+
.render_pass_id
155+
.expect("No render pass attached to the component"),
168156
viewport: viewport.clone(),
169157
},
170158
RenderCommand::Draw { vertices: 0..3 },
@@ -208,8 +196,8 @@ impl Default for DemoComponent {
208196
return DemoComponent {
209197
vertex_shader: vs,
210198
triangle_vertex: fs,
211-
render_pass: None,
212-
render_pipeline: None,
199+
render_pass_id: None,
200+
render_pipeline_id: None,
213201
width: 800,
214202
height: 600,
215203
};

0 commit comments

Comments
 (0)