lambda_platform/gfx/
buffer.rs1use gfx_hal::{
2 memory::{
3 Segment,
4 SparseFlags,
5 },
6 prelude::Device,
7 Backend,
8};
9
10use super::gpu::Gpu;
11
12pub type Usage = gfx_hal::buffer::Usage;
14pub type Properties = gfx_hal::memory::Properties;
15
16#[derive(Debug, Clone, Copy)]
18pub enum BufferType {
19 Vertex,
20 Index,
21 Uniform,
22 Storage,
23}
24
25#[derive(Debug, Clone, Copy)]
28pub struct Buffer<RenderBackend: Backend> {
29 buffer: RenderBackend::Buffer,
30 memory: RenderBackend::Memory,
31 stride: usize,
32 buffer_type: BufferType,
33}
34
35impl<RenderBackend: Backend> Buffer<RenderBackend> {
36 pub fn destroy(self, gpu: &Gpu<RenderBackend>) {
39 unsafe {
40 gpu.internal_logical_device().free_memory(self.memory);
41 gpu.internal_logical_device().destroy_buffer(self.buffer);
42 }
43 }
44
45 pub fn stride(&self) -> usize {
47 return self.stride;
48 }
49}
50
51impl<RenderBackend: Backend> Buffer<RenderBackend> {
52 pub(super) fn internal_buffer(&self) -> &RenderBackend::Buffer {
54 return &self.buffer;
55 }
56}
57
58pub struct BufferBuilder {
59 buffer_length: usize,
60 usage: Usage,
61 properties: Properties,
62 buffer_type: BufferType,
63}
64
65impl BufferBuilder {
66 pub fn new() -> Self {
67 return Self {
68 buffer_length: 0,
69 usage: Usage::empty(),
70 properties: Properties::empty(),
71 buffer_type: BufferType::Vertex,
72 };
73 }
74
75 pub fn with_length(&mut self, length: usize) -> &mut Self {
76 self.buffer_length = length;
77 return self;
78 }
79
80 pub fn with_usage(&mut self, usage: Usage) -> &mut Self {
81 self.usage = usage;
82 return self;
83 }
84
85 pub fn with_properties(&mut self, properties: Properties) -> &mut Self {
86 self.properties = properties;
87 return self;
88 }
89
90 pub fn with_buffer_type(&mut self, buffer_type: BufferType) -> &mut Self {
91 self.buffer_type = buffer_type;
92 return self;
93 }
94
95 pub fn build<RenderBackend: Backend, Data: Sized>(
100 &self,
101 gpu: &mut Gpu<RenderBackend>,
102 data: Vec<Data>,
103 ) -> Result<Buffer<RenderBackend>, &'static str> {
104 use gfx_hal::{
105 adapter::PhysicalDevice,
106 MemoryTypeId,
107 };
108 let logical_device = gpu.internal_logical_device();
109 let physical_device = gpu.internal_physical_device();
110
111 logging::debug!(
114 "[DEBUG] Creating buffer of length: {}",
115 self.buffer_length
116 );
117 let buffer_result = unsafe {
118 logical_device.create_buffer(
119 self.buffer_length as u64,
120 self.usage,
121 SparseFlags::empty(),
122 )
123 };
124
125 if buffer_result.is_err() {
126 logging::error!("Failed to create buffer for allocating memory.");
127 return Err("Failed to create buffer for allocating memory.");
128 }
129
130 let mut buffer = buffer_result.unwrap();
131
132 let requirements =
133 unsafe { logical_device.get_buffer_requirements(&buffer) };
134 let memory_types = physical_device.memory_properties().memory_types;
135
136 logging::debug!("Buffer requirements: {:?}", requirements);
137 let memory_type = memory_types
139 .iter()
140 .enumerate()
141 .find(|(id, memory_type)| {
142 let type_supported = requirements.type_mask & (1 << id) != 0;
143 type_supported && memory_type.properties.contains(self.properties)
144 })
145 .map(|(id, _)| MemoryTypeId(id))
146 .unwrap();
147
148 logging::debug!("Allocating memory for buffer.");
149 let buffer_memory_allocation =
151 unsafe { logical_device.allocate_memory(memory_type, requirements.size) };
152
153 if buffer_memory_allocation.is_err() {
154 logging::error!("Failed to allocate memory for buffer.");
155 return Err("Failed to allocate memory for buffer.");
156 }
157
158 let mut buffer_memory = buffer_memory_allocation.unwrap();
159
160 let buffer_binding = unsafe {
162 logical_device.bind_buffer_memory(&buffer_memory, 0, &mut buffer)
163 };
164
165 if buffer_binding.is_err() {
167 unsafe { logical_device.destroy_buffer(buffer) };
168 logging::error!("Failed to bind buffer memory.");
169 return Err("Failed to bind buffer memory.");
170 }
171
172 let get_mapping_to_memory =
174 unsafe { logical_device.map_memory(&mut buffer_memory, Segment::ALL) };
175
176 if get_mapping_to_memory.is_err() {
177 unsafe { logical_device.destroy_buffer(buffer) };
178 logging::error!("Failed to map memory.");
179 return Err("Failed to map memory.");
180 }
181 let mapped_memory = get_mapping_to_memory.unwrap();
182
183 unsafe {
185 std::ptr::copy_nonoverlapping(
186 data.as_ptr() as *const u8,
187 mapped_memory,
188 self.buffer_length,
189 );
190 };
191
192 let memory_flush = unsafe {
194 logical_device
195 .flush_mapped_memory_ranges(std::iter::once((
196 &buffer_memory,
197 Segment::ALL,
198 )))
199 .map_err(|_| "Failed to flush memory.")
200 };
201
202 if memory_flush.is_err() {
203 unsafe { logical_device.destroy_buffer(buffer) };
204 logging::error!("Failed to flush memory.");
205 return Err("No memory available on the GPU.");
206 }
207
208 unsafe { logical_device.unmap_memory(&mut buffer_memory) };
210
211 return Ok(Buffer {
212 buffer,
213 memory: buffer_memory,
214 stride: std::mem::size_of::<Data>(),
215 buffer_type: self.buffer_type,
216 });
217 }
218}