Skip to content

Commit 9e5fdf9

Browse files
committed
[update] Buffer & Mesh API, refactor internal api calls, implement vertex attributes & mesh into demo.
1 parent d1ef60b commit 9e5fdf9

11 files changed

Lines changed: 173 additions & 88 deletions

File tree

crates/lambda-platform/src/gfx/assembler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Primitive assembly for the graphics pipeline.
22
3+
pub use gfx_hal::pso::Element as VertexElement;
34
use gfx_hal::pso::{
45
self,
56
AttributeDesc,
6-
Element,
77
VertexBufferDesc,
88
};
99

@@ -17,7 +17,7 @@ use super::{
1717
pub struct VertexAttribute {
1818
pub location: u32,
1919
pub offset: u32,
20-
pub element: Element<ColorFormat>,
20+
pub element: VertexElement<ColorFormat>,
2121
}
2222

2323
/// PrimitiveAssemblerBuilder for preparing PrimitiveAssemblers to use in the

crates/lambda-platform/src/gfx/buffer.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
use gfx_hal::memory::{
2-
Segment,
3-
SparseFlags,
1+
use gfx_hal::{
2+
memory::{
3+
Segment,
4+
SparseFlags,
5+
},
6+
prelude::Device,
47
};
58

69
use super::gpu::Gpu;
@@ -29,6 +32,14 @@ pub struct Buffer<RenderBackend: super::internal::Backend> {
2932
}
3033

3134
impl<RenderBackend: super::internal::Backend> Buffer<RenderBackend> {
35+
/// Destroy the buffer and all it's resources with the GPU that
36+
/// created it.
37+
pub fn destroy(self, gpu: &Gpu<RenderBackend>) {
38+
unsafe {
39+
gpu.internal_logical_device().destroy_buffer(self.buffer);
40+
gpu.internal_logical_device().free_memory(self.memory);
41+
}
42+
}
3243
pub fn stride(&self) -> usize {
3344
return self.stride;
3445
}
@@ -82,10 +93,9 @@ impl BufferBuilder {
8293
) -> Result<Buffer<RenderBackend>, &'static str> {
8394
use gfx_hal::{
8495
adapter::PhysicalDevice,
85-
device::Device,
8696
MemoryTypeId,
8797
};
88-
let logical_device = super::internal::logical_device_for(gpu);
98+
let logical_device = gpu.internal_logical_device();
8999
let physical_device = super::internal::physical_device_for(gpu);
90100

91101
// TODO(vmarcella): Add the ability for the user to specify the memory

crates/lambda-platform/src/gfx/gpu.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl<RenderBackend: gfx_hal::Backend> Gpu<RenderBackend> {
183183
return Ok(());
184184
}
185185

186-
pub(super) fn logical_device(&self) -> &RenderBackend::Device {
186+
pub(super) fn internal_logical_device(&self) -> &RenderBackend::Device {
187187
return &self.gpu.device;
188188
}
189189
}

crates/lambda-platform/src/gfx/pipeline.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl<RenderBackend: internal::Backend> RenderPipelineBuilder<RenderBackend> {
158158

159159
let pipeline = unsafe {
160160
gpu
161-
.logical_device()
161+
.internal_logical_device()
162162
.create_graphics_pipeline(&pipeline_desc, None)
163163
.expect("Failed to create graphics pipeline")
164164
};
@@ -184,11 +184,11 @@ impl<RenderBackend: internal::Backend> RenderPipeline<RenderBackend> {
184184
pub fn destroy(self, gpu: &super::gpu::Gpu<RenderBackend>) {
185185
unsafe {
186186
gpu
187-
.logical_device()
187+
.internal_logical_device()
188188
.destroy_pipeline_layout(self.pipeline_layout);
189189

190190
gpu
191-
.logical_device()
191+
.internal_logical_device()
192192
.destroy_graphics_pipeline(self.pipeline);
193193
}
194194
}

crates/lambda-platform/src/gfx/surface.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl<RenderBackend: gfx_hal::Backend> Surface<RenderBackend> {
8585
swapchain: Swapchain,
8686
timeout_in_nanoseconds: u64,
8787
) -> Result<(), &'surface str> {
88-
let device = super::gpu::internal::logical_device_for(gpu);
88+
let device = gpu.internal_logical_device();
8989
self.extent = Some(swapchain.config.extent);
9090

9191
unsafe {

lambda/examples/push_constants.rs

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use lambda::{
22
core::{
33
component::Component,
44
render::{
5+
buffer::BufferBuilder,
56
command::RenderCommand,
67
mesh::MeshBuilder,
78
pipeline::RenderPipelineBuilder,
@@ -10,7 +11,11 @@ use lambda::{
1011
Shader,
1112
ShaderBuilder,
1213
},
13-
vertex::VertexBuilder,
14+
vertex::{
15+
VertexAttribute,
16+
VertexBuilder,
17+
VertexElement,
18+
},
1419
viewport,
1520
ResourceId,
1621
},
@@ -24,7 +29,10 @@ use lambda::{
2429
runtimes::GenericRuntimeBuilder,
2530
};
2631
use lambda_platform::{
27-
gfx::pipeline::PipelineStage,
32+
gfx::{
33+
pipeline::PipelineStage,
34+
surface::ColorFormat,
35+
},
2836
shaderc::{
2937
ShaderKind,
3038
VirtualShader,
@@ -82,14 +90,8 @@ impl Component for PushConstantsExample {
8290
&mut self,
8391
render_context: &mut lambda::core::render::RenderContext,
8492
) {
85-
let render_pass = RenderPassBuilder::new().build(&render_context);
93+
let render_pass = RenderPassBuilder::new().build(render_context);
8694
let push_constant_size = std::mem::size_of::<PushConstant>() as u32;
87-
let pipeline = RenderPipelineBuilder::new()
88-
.with_push_constant(PipelineStage::VERTEX, push_constant_size)
89-
.build(render_context, &render_pass, &self.shader, None);
90-
91-
self.render_pass = Some(render_context.attach_render_pass(render_pass));
92-
self.render_pipeline = Some(render_context.attach_pipeline(pipeline));
9395

9496
// Create triangle mesh.
9597
let vertices = [
@@ -114,6 +116,39 @@ impl Component for PushConstantsExample {
114116
vertices.iter().for_each(|vertex| {
115117
mesh_builder.with_vertex(vertex.clone());
116118
});
119+
120+
let mesh = mesh_builder
121+
.with_attributes(vec![
122+
VertexAttribute {
123+
location: 0,
124+
offset: 0,
125+
element: VertexElement {
126+
format: ColorFormat::Rgb32Sfloat,
127+
offset: 0,
128+
},
129+
},
130+
VertexAttribute {
131+
location: 1,
132+
offset: 0,
133+
element: VertexElement {
134+
format: ColorFormat::Rgb32Sfloat,
135+
offset: 12,
136+
},
137+
},
138+
])
139+
.build();
140+
141+
let pipeline = RenderPipelineBuilder::new()
142+
.with_push_constant(PipelineStage::VERTEX, push_constant_size)
143+
.with_buffer(
144+
BufferBuilder::build_from_mesh(&mesh, render_context)
145+
.expect("Failed to create buffer"),
146+
mesh.attributes().to_vec(),
147+
)
148+
.build(render_context, &render_pass, &self.shader, None);
149+
150+
self.render_pass = Some(render_context.attach_render_pass(render_pass));
151+
self.render_pipeline = Some(render_context.attach_pipeline(pipeline));
117152
}
118153

119154
fn on_detach(

lambda/src/core/render/buffer.rs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use lambda_platform::gfx::buffer::{
1515
};
1616

1717
use super::{
18-
internal::mut_gpu_from_context,
18+
mesh::Mesh,
1919
RenderContext,
2020
};
2121

@@ -25,6 +25,16 @@ pub struct Buffer {
2525
buffer_type: BufferType,
2626
}
2727

28+
/// Public interface for a buffer.
29+
impl Buffer {
30+
/// Destroy the buffer and all it's resources with the render context that
31+
/// created it.
32+
pub fn destroy(self, render_context: &RenderContext) {
33+
self.buffer.destroy(render_context.internal_gpu());
34+
}
35+
}
36+
37+
/// Internal interface for working with buffers.
2838
impl Buffer {
2939
/// Retrieve a reference to the internal buffer.
3040
pub(super) fn internal_buffer(
@@ -50,6 +60,34 @@ impl BufferBuilder {
5060
};
5161
}
5262

63+
pub fn build_from_mesh(
64+
mesh: &Mesh,
65+
render_context: &mut RenderContext,
66+
) -> Result<Buffer, &'static str> {
67+
let mut buffer_builder = Self::new();
68+
let internal_buffer = buffer_builder
69+
.buffer_builder
70+
.with_length(mesh.vertices().len())
71+
.with_usage(Usage::VERTEX)
72+
.with_properties(Properties::CPU_VISIBLE | Properties::COHERENT)
73+
.build(
74+
render_context.internal_mutable_gpu(),
75+
mesh.vertices().to_vec(),
76+
);
77+
78+
match internal_buffer {
79+
Ok(internal_buffer) => {
80+
return Ok(Buffer {
81+
buffer: internal_buffer,
82+
buffer_type: BufferType::Vertex,
83+
});
84+
}
85+
Err(_) => {
86+
return Err("Failed to create buffer from mesh.");
87+
}
88+
}
89+
}
90+
5391
/// Sets the length of the buffer (In bytes).
5492
pub fn with_length(&mut self, size: usize) -> &mut Self {
5593
self.buffer_builder.with_length(size);
@@ -83,7 +121,7 @@ impl BufferBuilder {
83121
) -> Result<Buffer, &'static str> {
84122
let buffer_allocation = self
85123
.buffer_builder
86-
.build(&mut mut_gpu_from_context(render_context), data);
124+
.build(render_context.internal_mutable_gpu(), data);
87125

88126
match buffer_allocation {
89127
Ok(buffer) => {

lambda/src/core/render/mesh.rs

Lines changed: 26 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
use super::{
2-
buffer::{
3-
Buffer,
4-
BufferBuilder,
5-
Properties,
6-
Usage,
2+
vertex::{
3+
Vertex,
4+
VertexAttribute,
75
},
8-
vertex::Vertex,
96
RenderContext,
107
};
118

@@ -15,12 +12,16 @@ use super::{
1512
#[derive(Debug)]
1613
pub struct Mesh {
1714
vertices: Vec<Vertex>,
18-
buffer: Buffer,
15+
attributes: Vec<VertexAttribute>,
1916
}
2017

2118
impl Mesh {
22-
pub(super) fn buffer(&self) -> &Buffer {
23-
return &self.buffer;
19+
pub fn vertices(&self) -> &[Vertex] {
20+
&self.vertices
21+
}
22+
23+
pub fn attributes(&self) -> &[VertexAttribute] {
24+
&self.attributes
2425
}
2526
}
2627

@@ -31,13 +32,15 @@ impl Mesh {
3132
pub struct MeshBuilder {
3233
capacity: usize,
3334
vertices: Vec<Vertex>,
35+
attributes: Vec<VertexAttribute>,
3436
}
3537

3638
impl MeshBuilder {
3739
pub fn new() -> Self {
3840
return Self {
3941
capacity: 0,
40-
vertices: vec![],
42+
vertices: Vec::new(),
43+
attributes: Vec::new(),
4144
};
4245
}
4346

@@ -51,37 +54,21 @@ impl MeshBuilder {
5154
return self;
5255
}
5356

57+
pub fn with_attributes(
58+
&mut self,
59+
attributes: Vec<VertexAttribute>,
60+
) -> &mut Self {
61+
self.attributes = attributes;
62+
return self;
63+
}
64+
5465
/// Builds a mesh from the vertices and indices that have been added to the
5566
/// builder and allocates the memory for the mesh on the GPU.
56-
pub fn build(
57-
&self,
58-
render_context: &mut RenderContext,
59-
) -> Result<Mesh, &'static str> {
60-
let gpu_memory_required =
61-
self.vertices.len() * std::mem::size_of::<Vertex>();
62-
println!(
63-
"Allocating {} bytes of GPU memory for mesh.",
64-
gpu_memory_required
65-
);
66-
67-
// Allocate memory for the mesh on the GPU.
68-
let buffer_allocation = BufferBuilder::new()
69-
.with_length(gpu_memory_required)
70-
.with_usage(Usage::VERTEX)
71-
.with_properties(Properties::CPU_VISIBLE | Properties::COHERENT)
72-
.build(render_context, self.vertices.clone());
73-
74-
match buffer_allocation {
75-
Ok(buffer) => {
76-
return Ok(Mesh {
77-
vertices: self.vertices.clone(),
78-
buffer,
79-
});
80-
}
81-
Err(error) => {
82-
return Err(error);
83-
}
84-
}
67+
pub fn build(&self) -> Mesh {
68+
return Mesh {
69+
vertices: self.vertices.clone(),
70+
attributes: self.attributes.clone(),
71+
};
8572
}
8673
}
8774

@@ -93,8 +80,4 @@ mod tests {
9380

9481
assert_eq!(mesh.vertices.len(), 0);
9582
}
96-
97-
// TODO(vmarcella): Add more tests for mesh building once the render context
98-
// is mockable. As of right now, testing would require the creation of a real
99-
// render context to perform the GPU memory allocation & binding for the mesh.
10083
}

0 commit comments

Comments
 (0)