vkobject_rs/
mesh.rs

1
2use crate::prelude::*;
3use std::{
4	any::{Any, TypeId, type_name},
5	ffi::c_void,
6	fmt::Debug,
7	marker::PhantomData,
8	mem::{size_of, size_of_val},
9	sync::Arc,
10	vec::IntoIter,
11};
12use struct_iterable::Iterable;
13
14/// The type that could be the item of the `BufferVec`
15pub trait BufferVecStructItem: Copy + Clone + Sized + Default + Debug + Iterable {}
16impl<T> BufferVecStructItem for T where T: Copy + Clone + Sized + Default + Debug + Iterable {}
17
18/// A wrapper for `Buffer`
19#[derive(Debug, Clone)]
20pub struct BufferWithType<T>
21where
22	T: BufferVecItem {
23	/// The buffer
24	buffer: Buffer,
25
26	/// The phantom data to hold the type
27	_phantom: PhantomData<T>,
28}
29
30impl<T> BufferWithType<T>
31where
32	T: BufferVecItem {
33	/// Create the `BufferWithType<T>`
34	pub fn new(device: Arc<VulkanDevice>, data: &[T], cmdbuf: VkCommandBuffer, usage: VkBufferUsageFlags) -> Result<Self, VulkanError> {
35		let ret = Self {
36			buffer: Buffer::new(device, size_of_val(data) as VkDeviceSize, Some(data.as_ptr() as *const c_void), usage)?,
37			_phantom: PhantomData,
38		};
39		ret.upload_staging_buffer(cmdbuf)?;
40		Ok(ret)
41	}
42
43	/// Create the `BufferWithType<T>`
44	pub fn new_empty(device: Arc<VulkanDevice>, size: usize, usage: VkBufferUsageFlags) -> Result<Self, VulkanError> {
45		Ok(Self {
46			buffer: Buffer::new(device, (size * size_of::<T>()) as VkDeviceSize, None, usage)?,
47			_phantom: PhantomData,
48		})
49	}
50
51	/// Create the `BufferWithType<T>`
52	pub fn new_from_buffer(buffer: Buffer) -> Self {
53		Self {
54			buffer,
55			_phantom: PhantomData,
56		}
57	}
58
59	/// Create staging buffer for the `BufferWithType<T>`
60	pub fn ensure_staging_buffer(&mut self) -> Result<(), VulkanError> {
61		self.buffer.ensure_staging_buffer()
62	}
63
64	/// Discard the staging buffer to save memory
65	pub fn discard_staging_buffer(&mut self) {
66		self.buffer.discard_staging_buffer();
67	}
68
69	/// Get data by an index
70	pub fn get_data(&mut self, index: usize) -> Option<T> {
71		if let Some(ref mut staging_buffer) = self.buffer.staging_buffer {
72			let mut ret = T::default();
73			staging_buffer.get_data(&mut ret as *mut T as *mut c_void, (index * size_of::<T>()) as VkDeviceSize, size_of::<T>()).ok()?;
74			Some(ret)
75		} else {
76			None
77		}
78	}
79
80	/// Set data
81	pub fn set_data(&mut self, index: usize, data: T) -> Result<(), VulkanError> {
82		unsafe {self.buffer.set_staging_data(&data as *const T as *const c_void, (index * size_of::<T>()) as VkDeviceSize, size_of::<T>())}
83	}
84
85	/// Upload staging buffer data to buffer
86	pub fn upload_staging_buffer(&self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
87		self.buffer.upload_staging_buffer(cmdbuf, 0, self.buffer.get_size())
88	}
89
90	/// Get the count of the data
91	pub fn len(&self) -> usize {
92		self.buffer.get_size() as usize / size_of::<T>()
93	}
94
95	/// Get if the buffer is empty
96	pub fn is_empty(&self) -> bool {
97		self.buffer.get_size() == 0
98	}
99
100	/// Get the inner buffer
101	pub fn into_inner(self) -> Buffer {
102		self.buffer
103	}
104}
105
106/// The trait for the mesh to hold buffers
107pub trait BufferForDraw<T>: Debug + Clone
108where
109	T: BufferVecItem {
110	/// Must be able to get the `VkBuffer` handle
111	fn get_vk_buffer(&self) -> VkBuffer;
112
113	/// Flush staging buffer data to GPU
114	fn flush(&mut self, _cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
115		Ok(())
116	}
117
118	/// Discard staging buffer if the buffer's staging buffer is discardable
119	fn discard_staging_buffer(&mut self) {}
120
121	/// Get the number of the items in the buffer
122	fn len(&self) -> usize;
123
124	/// Check if the buffer is empty
125	fn is_empty(&self) -> bool {
126		self.len() == 0
127	}
128
129	/// Convert to `BufferVec<T>`
130	fn convert_to_buffer_vec(self) -> BufferVec<T>;
131
132	/// Convert to `BufferWithType<T>`
133	fn convert_to_buffer_with_type(self) -> BufferWithType<T>;
134}
135
136impl<T> BufferForDraw<T> for BufferVec<T>
137where
138	T: BufferVecItem {
139	fn get_vk_buffer(&self) -> VkBuffer {
140		self.get_vk_buffer()
141	}
142
143	fn flush(&mut self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
144		self.flush(cmdbuf)
145	}
146
147	fn len(&self) -> usize {
148		self.len()
149	}
150
151	fn convert_to_buffer_vec(self) -> BufferVec<T> {
152		self
153	}
154
155	fn convert_to_buffer_with_type(self) -> BufferWithType<T> {
156		BufferWithType::new_from_buffer(self.into_inner())
157	}
158}
159
160impl<T> BufferForDraw<T> for BufferWithType<T>
161where
162	T: BufferVecItem {
163	fn get_vk_buffer(&self) -> VkBuffer {
164		self.buffer.get_vk_buffer()
165	}
166
167	fn flush(&mut self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
168		self.upload_staging_buffer(cmdbuf)?;
169		Ok(())
170	}
171
172	fn discard_staging_buffer(&mut self) {
173		self.discard_staging_buffer()
174	}
175
176	fn len(&self) -> usize {
177		self.len()
178	}
179
180	fn convert_to_buffer_vec(self) -> BufferVec<T> {
181		let len = self.len();
182		unsafe {BufferVec::from_raw_parts(self.into_inner(), len).unwrap()}
183	}
184
185	fn convert_to_buffer_with_type(self) -> BufferWithType<T> {
186		self
187	}
188}
189
190#[derive(Debug, Clone)]
191pub struct Mesh<BV, V, BE, E, BI, I, BC, C>
192where
193	BV: BufferForDraw<V>,
194	BE: BufferForDraw<E>,
195	BI: BufferForDraw<I>,
196	BC: BufferForDraw<C>,
197	V: BufferVecStructItem,
198	E: BufferVecItem + 'static,
199	I: BufferVecStructItem,
200	C: BufferVecStructItem {
201	pub primitive_type: VkPrimitiveTopology,
202	pub vertices: BV,
203	pub indices: Option<BE>,
204	pub instances: Option<BI>,
205	pub commands: Option<BC>,
206	vertex_type: V,
207	element_type: E,
208	instance_type: I,
209	command_type: C,
210}
211
212/// If a buffer you don't need, use this for your buffer item type
213#[derive(Default, Debug, Clone, Copy, Iterable)]
214pub struct UnusedBufferItem {}
215
216/// If a buffer you don't need, use this for your buffer type
217pub type UnusedBufferType = BufferWithType<UnusedBufferItem>;
218
219/// Use this function to create an unused buffer type
220pub fn buffer_unused() -> Option<UnusedBufferType> {
221	None
222}
223
224impl<BV, V, BE, E, BI, I, BC, C> Mesh<BV, V, BE, E, BI, I, BC, C>
225where
226	BV: BufferForDraw<V>,
227	BE: BufferForDraw<E>,
228	BI: BufferForDraw<I>,
229	BC: BufferForDraw<C>,
230	V: BufferVecStructItem,
231	E: BufferVecItem + 'static,
232	I: BufferVecStructItem,
233	C: BufferVecStructItem {
234	/// Create the mesh from the buffers
235	pub fn new(primitive_type: VkPrimitiveTopology, vertices: BV, indices: Option<BE>, instances: Option<BI>, commands: Option<BC>) -> Self {
236		Self {
237			primitive_type,
238			vertices,
239			indices,
240			instances,
241			commands,
242			vertex_type: V::default(),
243			element_type: E::default(),
244			instance_type: I::default(),
245			command_type: C::default(),
246		}
247	}
248
249	/// Upload staging buffers to GPU
250	pub fn flush(&mut self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
251		filter_no_staging_buffer(self.vertices.flush(cmdbuf))?;
252		if let Some(ref mut indices) = self.indices {filter_no_staging_buffer(indices.flush(cmdbuf))?;}
253		if let Some(ref mut instances) = self.instances {filter_no_staging_buffer(instances.flush(cmdbuf))?;}
254		if let Some(ref mut commands) = self.commands {filter_no_staging_buffer(commands.flush(cmdbuf))?;}
255		Ok(())
256	}
257
258	/// Discard staging buffers if the data will never be modified.
259	pub fn discard_staging_buffers(&mut self) {
260		self.vertices.discard_staging_buffer();
261		if let Some(ref mut indices) = self.indices {indices.discard_staging_buffer();}
262		if let Some(ref mut instances) = self.instances {instances.discard_staging_buffer();}
263		if let Some(ref mut commands) = self.commands {commands.discard_staging_buffer();}
264	}
265}
266
267/// The most typical static mesh type: use `BufferWithType` for vertices and elements(indices), use `BufferVec` for instances and draw commands
268pub type StaticMesh<V, E, I, C> = Mesh<BufferWithType<V>, V, BufferWithType<E>, E, BufferVec<I>, I, BufferVec<C>, C>;
269
270/// The dynamic mesh type: use `BufferVec` for all buffers
271pub type DynamicMesh<V, E, I, C> = Mesh<BufferVec<V>, V, BufferVec<E>, E, BufferVec<I>, I, BufferVec<C>, C>;
272
273/// The trait for a mesh
274pub trait GenericMesh: Debug {
275	/// Get the vertex buffer
276	fn get_vk_vertex_buffer(&self) -> VkBuffer;
277
278	/// Get the index buffer
279	fn get_vk_index_buffer(&self) -> Option<VkBuffer>;
280
281	/// Get the instance buffer
282	fn get_vk_instance_buffer(&self) -> Option<VkBuffer>;
283
284	/// Get the command buffer
285	fn get_vk_command_buffer(&self) -> Option<VkBuffer>;
286
287	/// Get the primitive type
288	fn get_primitive_type(&self) -> VkPrimitiveTopology;
289
290	/// Get vertex count
291	fn get_vertex_count(&self) -> usize;
292
293	/// Get index count
294	fn get_index_count(&self) -> usize;
295
296	/// Get instance count
297	fn get_instance_count(&self) -> usize;
298
299	/// Get command count
300	fn get_command_count(&self) -> usize;
301
302	/// Get the iterator for the vertex buffer item structure
303	fn iter_vertex_buffer_struct_members(&self) -> IntoIter<(&'static str, &(dyn Any + 'static))>;
304
305	/// Get the TypeId of the index buffer item
306	fn get_index_type_id(&self) -> Option<TypeId>;
307
308	/// Get the iterator for the vertex buffer item structure
309	fn iter_instance_buffer_struct_members(&self) -> Option<IntoIter<(&'static str, &(dyn Any + 'static))>>;
310
311	/// Get the iterator for the vertex buffer item structure
312	fn iter_command_buffer_struct_members(&self) -> Option<IntoIter<(&'static str, &(dyn Any + 'static))>>;
313
314	/// Get the stride of the vertex buffer
315	fn get_vertex_type_name(&self) -> &'static str;
316
317	/// Get the stride of the index buffer
318	fn get_index_type_name(&self) -> &'static str;
319
320	/// Get the stride of the instance buffer
321	fn get_instance_type_name(&self) -> &'static str;
322
323	/// Get the stride of the command buffer
324	fn get_command_type_name(&self) -> &'static str;
325
326	/// Get the stride of the vertex buffer
327	fn get_vertex_stride(&self) -> usize;
328
329	/// Get the stride of the index buffer
330	fn get_index_stride(&self) -> usize;
331
332	/// Get the stride of the instance buffer
333	fn get_instance_stride(&self) -> usize;
334
335	/// Get the stride of the command buffer
336	fn get_command_stride(&self) -> usize;
337
338	/// Flush all buffers that needs to be flushed to use
339	fn flush(&mut self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError>;
340
341	/// Discard staging buffers if the data will never be modified.
342	fn discard_staging_buffers(&mut self);
343
344	/// Get the index type
345	fn get_index_type(&self) -> Option<VkIndexType> {
346		match self.get_index_stride() {
347			0 => None,
348			1 => Some(VkIndexType::VK_INDEX_TYPE_UINT8),
349			2 => Some(VkIndexType::VK_INDEX_TYPE_UINT16),
350			4 => Some(VkIndexType::VK_INDEX_TYPE_UINT32),
351			_ => panic!("Unsupported index type: {}", self.get_index_type_name()),
352		}
353	}
354}
355
356impl<BV, V, BE, E, BI, I, BC, C> GenericMesh for Mesh<BV, V, BE, E, BI, I, BC, C>
357where
358	BV: BufferForDraw<V>,
359	BE: BufferForDraw<E>,
360	BI: BufferForDraw<I>,
361	BC: BufferForDraw<C>,
362	V: BufferVecStructItem,
363	E: BufferVecItem + 'static,
364	I: BufferVecStructItem,
365	C: BufferVecStructItem {
366	fn get_vk_vertex_buffer(&self) -> VkBuffer {
367		self.vertices.get_vk_buffer()
368	}
369
370	fn get_vk_index_buffer(&self) -> Option<VkBuffer> {
371		self.indices.as_ref().map(|b|b.get_vk_buffer())
372	}
373
374	fn get_vk_instance_buffer(&self) -> Option<VkBuffer> {
375		self.instances.as_ref().map(|b|b.get_vk_buffer())
376	}
377
378	fn get_vk_command_buffer(&self) -> Option<VkBuffer> {
379		self.commands.as_ref().map(|b|b.get_vk_buffer())
380	}
381
382	fn get_primitive_type(&self) -> VkPrimitiveTopology {
383		self.primitive_type
384	}
385
386	fn get_vertex_count(&self) -> usize {
387		self.vertices.len()
388	}
389
390	fn get_index_count(&self) -> usize {
391		if let Some(indices) = &self.indices {
392			indices.len()
393		} else {
394			0
395		}
396	}
397
398	fn get_instance_count(&self) -> usize {
399		if let Some(instances) = &self.instances {
400			instances.len()
401		} else {
402			1
403		}
404	}
405
406	fn get_command_count(&self) -> usize {
407		if let Some(commands) = &self.commands {
408			commands.len()
409		} else {
410			0
411		}
412	}
413
414	fn iter_vertex_buffer_struct_members(&self) -> IntoIter<(&'static str, &(dyn Any + 'static))> {
415		self.vertex_type.iter()
416	}
417
418	fn get_index_type_id(&self) -> Option<TypeId> {
419		self.indices.as_ref().map(|_|self.element_type.type_id())
420	}
421
422	fn iter_instance_buffer_struct_members(&self) -> Option<IntoIter<(&'static str, &(dyn Any + 'static))>> {
423		self.instances.as_ref().map(|_|self.instance_type.iter())
424	}
425
426	fn iter_command_buffer_struct_members(&self) -> Option<IntoIter<(&'static str, &(dyn Any + 'static))>> {
427		self.commands.as_ref().map(|_|self.command_type.iter())
428	}
429
430	fn get_vertex_type_name(&self) -> &'static str {
431		type_name::<V>()
432	}
433
434	fn get_index_type_name(&self) -> &'static str {
435		type_name::<E>()
436	}
437
438	fn get_instance_type_name(&self) -> &'static str {
439		type_name::<I>()
440	}
441
442	fn get_command_type_name(&self) -> &'static str {
443		type_name::<C>()
444	}
445
446	fn get_vertex_stride(&self) -> usize {
447		size_of::<V>()
448	}
449
450	fn get_index_stride(&self) -> usize {
451		size_of::<E>()
452	}
453
454	fn get_instance_stride(&self) -> usize {
455		size_of::<I>()
456	}
457
458	fn get_command_stride(&self) -> usize {
459		size_of::<C>()
460	}
461
462	fn flush(&mut self, cmdbuf: VkCommandBuffer) -> Result<(), VulkanError> {
463		self.flush(cmdbuf)
464	}
465
466	fn discard_staging_buffers(&mut self) {
467		self.discard_staging_buffers()
468	}
469}
470
471/// A Mesh with a material
472#[derive(Debug)]
473pub struct GenericMeshWithMaterial {
474	/// The mesh
475	pub mesh: Box<dyn GenericMesh>,
476
477	/// The material
478	pub material: Option<Box<dyn Material>>,
479}
480
481impl GenericMeshWithMaterial {
482	/// Create an instance for the `GenericMeshWithMaterial`
483	pub fn new(mesh: Box<dyn GenericMesh>, material: Option<Box<dyn Material>>) -> Self {
484		Self {
485			mesh,
486			material,
487		}
488	}
489}
490