lambda/render/
buffer.rs

1//! Buffers for allocating memory on the GPU.
2
3mod internal {
4  // Placed these in an internal module to avoid a name collision with the
5  // high level Buffer & BufferBuilder types in the parent module.
6  pub use lambda_platform::gfx::buffer::{
7    Buffer,
8    BufferBuilder,
9  };
10}
11
12use std::rc::Rc;
13
14// publicly use Properties and Usage from buffer.rs
15pub use lambda_platform::gfx::buffer::{
16  BufferType,
17  Properties,
18  Usage,
19};
20use logging;
21
22use super::{
23  mesh::Mesh,
24  vertex::Vertex,
25  RenderContext,
26};
27
28/// Buffer for storing vertex data on the GPU.
29#[derive(Debug)]
30pub struct Buffer {
31  buffer: Rc<internal::Buffer<super::internal::RenderBackend>>,
32  buffer_type: BufferType,
33}
34
35/// Public interface for a buffer.
36impl Buffer {
37  /// Destroy the buffer and all it's resources with the render context that
38  /// created it.
39  pub fn destroy(self, render_context: &RenderContext) {
40    Rc::try_unwrap(self.buffer)
41      .expect("Failed to get inside buffer")
42      .destroy(render_context.internal_gpu());
43  }
44}
45
46/// Internal interface for working with buffers.
47impl Buffer {
48  /// Retrieve a reference to the internal buffer.
49  pub(super) fn internal_buffer_rc(
50    &self,
51  ) -> Rc<internal::Buffer<super::internal::RenderBackend>> {
52    return self.buffer.clone();
53  }
54
55  pub(super) fn internal_buffer(
56    &self,
57  ) -> &internal::Buffer<super::internal::RenderBackend> {
58    return &self.buffer;
59  }
60}
61
62/// A buffer is a block of memory that can be used to store data that can be
63/// accessed by the GPU. The buffer is created with a length, usage, and
64/// properties that determine how the buffer can be used.
65pub struct BufferBuilder {
66  buffer_builder: internal::BufferBuilder,
67  buffer_type: BufferType,
68}
69
70impl BufferBuilder {
71  /// Creates a new buffer builder of type vertex.
72  pub fn new() -> Self {
73    return Self {
74      buffer_builder: internal::BufferBuilder::new(),
75      buffer_type: BufferType::Vertex,
76    };
77  }
78
79  /// Builds a buffer from a given mesh and allocates it's memory on to the GPU.
80  pub fn build_from_mesh(
81    mesh: &Mesh,
82    render_context: &mut RenderContext,
83  ) -> Result<Buffer, &'static str> {
84    let mut buffer_builder = Self::new();
85
86    // Allocate a buffer with the size of the mesh's vertices.
87    let internal_buffer = buffer_builder
88      .buffer_builder
89      .with_length(mesh.vertices().len() * std::mem::size_of::<Vertex>())
90      .with_usage(Usage::VERTEX)
91      .with_properties(Properties::CPU_VISIBLE)
92      .build(
93        render_context.internal_mutable_gpu(),
94        mesh.vertices().to_vec(),
95      );
96
97    match internal_buffer {
98      Ok(internal_buffer) => {
99        return Ok(Buffer {
100          buffer: Rc::new(internal_buffer),
101          buffer_type: BufferType::Vertex,
102        });
103      }
104      Err(_) => {
105        return Err("Failed to create buffer from mesh.");
106      }
107    }
108  }
109
110  /// Sets the length of the buffer (In bytes).
111  pub fn with_length(&mut self, size: usize) -> &mut Self {
112    self.buffer_builder.with_length(size);
113    return self;
114  }
115
116  /// Sets the type of buffer to create.
117  pub fn with_buffer_type(&mut self, buffer_type: BufferType) -> &mut Self {
118    self.buffer_type = buffer_type;
119    self.buffer_builder.with_buffer_type(buffer_type);
120    return self;
121  }
122
123  /// Sets the usage of the buffer.
124  pub fn with_usage(&mut self, usage: Usage) -> &mut Self {
125    self.buffer_builder.with_usage(usage);
126    return self;
127  }
128
129  /// Sets the properties of the buffer.
130  pub fn with_properties(&mut self, properties: Properties) -> &mut Self {
131    self.buffer_builder.with_properties(properties);
132    return self;
133  }
134
135  /// Build a buffer utilizing the current render context
136  pub fn build<Data: Sized>(
137    &self,
138    render_context: &mut RenderContext,
139    data: Vec<Data>,
140  ) -> Result<Buffer, &'static str> {
141    let buffer_allocation = self
142      .buffer_builder
143      .build(render_context.internal_mutable_gpu(), data);
144
145    match buffer_allocation {
146      Ok(buffer) => {
147        logging::debug!(
148          "Buffer allocation for {:?} succeeded.",
149          self.buffer_type
150        );
151        return Ok(Buffer {
152          buffer: Rc::new(buffer),
153          buffer_type: self.buffer_type,
154        });
155      }
156      Err(error) => {
157        logging::error!(
158          "Buffer allocation for {:?} failed with error: {:?}",
159          self.buffer_type,
160          error
161        );
162        return Err(error);
163      }
164    }
165  }
166}