Fix Mesh allocator bug and reduce Mesh data copies by two (#15566)

# Objective

- First step towards #15558

## Solution

- Rename `get_vertex_buffer_data` to `create_packed_vertex_buffer_data`
to make it clear that it is not "free" and actually allocates
- Compute length analytically for preallocation instead of creating the
buffer to get its length and immediately discard it
- Use existing vertex attribute size calculation method to reduce code
duplication
- Fix a bug where mesh index data was being replaced by unnecessarily
newly created mesh vertex data in some cases
- Overall reduces mesh copies by two. We still have plenty to go, but
these were the easy ones.

## Testing

- I ran 3d_scene, lighting, and many_cubes, they look fine.
- Benchmarks would be nice, but this is very obviously a win in perf and
correctness.

---

## Migration Guide

- `Mesh::create_packed_vertex_buffer_data` has been renamed
`Mesh::create_packed_vertex_buffer_data` to reflect the fact that it
copies data and allocates.

## Showcase

- look mom, less copies
This commit is contained in:
vero 2024-10-01 13:15:57 -04:00 committed by GitHub
parent 1df8238e8d
commit 6465e3bd9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 6 additions and 14 deletions

View File

@ -30,7 +30,7 @@ impl MeshletMesh {
let indices = validate_input_mesh(mesh)?; let indices = validate_input_mesh(mesh)?;
// Split the mesh into an initial list of meshlets (LOD 0) // Split the mesh into an initial list of meshlets (LOD 0)
let vertex_buffer = mesh.get_vertex_buffer_data(); let vertex_buffer = mesh.create_packed_vertex_buffer_data();
let vertex_stride = mesh.get_vertex_size() as usize; let vertex_stride = mesh.get_vertex_size() as usize;
let vertices = VertexDataAdapter::new(&vertex_buffer, vertex_stride, 0).unwrap(); let vertices = VertexDataAdapter::new(&vertex_buffer, vertex_stride, 0).unwrap();
let mut meshlets = compute_meshlets(&indices, &vertices); let mut meshlets = compute_meshlets(&indices, &vertices);

View File

@ -427,7 +427,7 @@ impl MeshAllocator {
if self.general_vertex_slabs_supported { if self.general_vertex_slabs_supported {
self.allocate( self.allocate(
mesh_id, mesh_id,
mesh.get_vertex_buffer_data().len() as u64, mesh.get_vertex_size() * mesh.count_vertices() as u64,
vertex_element_layout, vertex_element_layout,
&mut slabs_to_grow, &mut slabs_to_grow,
mesh_allocator_settings, mesh_allocator_settings,
@ -474,12 +474,11 @@ impl MeshAllocator {
let Some(&slab_id) = self.mesh_id_to_vertex_slab.get(mesh_id) else { let Some(&slab_id) = self.mesh_id_to_vertex_slab.get(mesh_id) else {
return; return;
}; };
let vertex_data = mesh.get_vertex_buffer_data(); let vertex_data = mesh.create_packed_vertex_buffer_data();
// Call the generic function. // Call the generic function.
self.copy_element_data( self.copy_element_data(
mesh_id, mesh_id,
mesh,
&vertex_data, &vertex_data,
BufferUsages::VERTEX, BufferUsages::VERTEX,
slab_id, slab_id,
@ -507,7 +506,6 @@ impl MeshAllocator {
// Call the generic function. // Call the generic function.
self.copy_element_data( self.copy_element_data(
mesh_id, mesh_id,
mesh,
index_data, index_data,
BufferUsages::INDEX, BufferUsages::INDEX,
slab_id, slab_id,
@ -521,7 +519,6 @@ impl MeshAllocator {
fn copy_element_data( fn copy_element_data(
&mut self, &mut self,
mesh_id: &AssetId<Mesh>, mesh_id: &AssetId<Mesh>,
mesh: &Mesh,
data: &[u8], data: &[u8],
buffer_usages: BufferUsages, buffer_usages: BufferUsages,
slab_id: SlabId, slab_id: SlabId,
@ -567,7 +564,7 @@ impl MeshAllocator {
slab_id, slab_id,
buffer_usages_to_str(buffer_usages) buffer_usages_to_str(buffer_usages)
)), )),
contents: &mesh.get_vertex_buffer_data(), contents: data,
usage: buffer_usages | BufferUsages::COPY_DST, usage: buffer_usages | BufferUsages::COPY_DST,
}, },
)); ));

View File

@ -458,13 +458,8 @@ impl Mesh {
/// ///
/// If the vertex attributes have different lengths, they are all truncated to /// If the vertex attributes have different lengths, they are all truncated to
/// the length of the smallest. /// the length of the smallest.
pub fn get_vertex_buffer_data(&self) -> Vec<u8> { pub fn create_packed_vertex_buffer_data(&self) -> Vec<u8> {
let mut vertex_size = 0; let vertex_size = self.get_vertex_size() as usize;
for attribute_data in self.attributes.values() {
let vertex_format = attribute_data.attribute.format;
vertex_size += vertex_format.get_size() as usize;
}
let vertex_count = self.count_vertices(); let vertex_count = self.count_vertices();
let mut attributes_interleaved_buffer = vec![0; vertex_count * vertex_size]; let mut attributes_interleaved_buffer = vec![0; vertex_count * vertex_size];
// bundle into interleaved buffers // bundle into interleaved buffers