-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Faster MeshletMesh deserialization #14193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
crates/bevy_pbr/src/meshlet/asset.rs
Outdated
| reader.read_to_end(&mut compressed_asset_data).await?; | ||
|
|
||
| // Convert compressed data back to an asset | ||
| let reader = &mut FrameDecoder::new(Cursor::new(compressed_asset_data)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does LZ4 compression actually help? You might have to use delta encoding (i.e. instead of storing indices you'd store the wrapping difference from the previous index) if you want it to have much impact
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It did when I used bincode, I should probably double check again.
Nanite has a whole bunch of tricks they use for compressing disk and in-memory asset data, but they're low priority for me vs runtime performance at the moment, and I don't really have much experience with this field https://advances.realtimerendering.com/s2021/Karis_Nanite_SIGGRAPH_Advances_2021_final.pdf.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
9.73mb without compression, 4.97mb with.
crates/bevy_pbr/src/meshlet/asset.rs
Outdated
| let compressed_asset_data_len = async_read_u64(reader).await? as usize; | ||
|
|
||
| // Load compressed asset data | ||
| let mut compressed_asset_data = Vec::with_capacity(compressed_asset_data_len); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish I could directly wrap Bevy's &mut dyn Reader in a FrameDecoder, rather than read to a Vec first, but it's not possible as Reader doesn't implement the typical std::io::Read sync trait - only Bevy's custom async traits :(
@cart any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can make adapters like so:
struct AsyncWriteSyncAdapter<'a>(&'a mut Writer);
impl Write for AsyncWriteSyncAdapter<'_> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
block_on(self.0.write(buf))
}
fn flush(&mut self) -> std::io::Result<()> {
block_on(self.0.flush())
}
}
struct AsyncReadSyncAdapter<'a>(&'a mut dyn Reader);
impl Read for AsyncReadSyncAdapter<'_> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
block_on(self.0.read(buf))
}
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not having to allocate an intermediate vec was a nice perf/memory win.
pcwalton
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine, just a couple of suggestions.
# Objective - #14193 changed the bunny meshlet url but didn't update example metadata ## Solution - Also update the url there
Objective
Solution
Testing
Changelog
MeshletMeshloading speedMeshletMeshdisk format has changed, andMESHLET_MESH_ASSET_VERSIONhas been bumpedMeshletMeshfields are now privateMeshletMeshSaverLoadtoMeshletMeshSaverLoaderMeshlet,MeshletBoundingSpheres, andMeshletBoundingSpheretypes are now privateMeshletMeshSaveOrLoadError::SerializationOrDeserializationMeshletMeshSaveOrLoadError::WrongFileTypeMigration Guide
MeshletMeshassets, as the disk format has changed, andMESHLET_MESH_ASSET_VERSIONhas been bumpedMeshletMeshfields are now privateMeshletMeshSaverLoadis now namedMeshletMeshSaverLoaderMeshlet,MeshletBoundingSpheres, andMeshletBoundingSpheretypes are now privateMeshletMeshSaveOrLoadError::SerializationOrDeserializationhas been removedMeshletMeshSaveOrLoadError::WrongFileType, match on this variant if you match onMeshletMeshSaveOrLoadError