-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
What problem does this solve or what need does it fill?
There are a few reasons you might want to explicitly store vertices once but have multiple mesh handles with different sets of indices. The most-common one is probably simply that the format that you're using stores the mesh in that way. My specific use-case, though, is that I'm loading a format that has frame-by-frame (i.e. not morphing) mesh animations, so I want all frames for all animations to be in a single buffer but for the indices to be stored at runtime. Currently, I am just creating an entirely new mesh for each frame, but it would be good to indicate to the GPU that the vertices are intended to be allocated in a single block since sometimes frames get reused between animations.
What solution would you like?
It could be useful for Mesh.attributes
to be an Arc<BTreeMap<..>>
, with mutating methods using Arc::make_mut
. This means that meshes with precisely the same vertices, but different indices, will share a single buffer. As this is, essentially, just an optimisation for when meshes are cloned and modified, the GPU should only do minimal bookkeeping - a first implementation could simply only change the attributes
field and all code that interacts with the GPU could act exactly the same as before (this would, at least, reduce CPU-side memory consumption).
Future extensions
- Of course, the main motivation of this proposal is to allow the GPU to share vertex buffers between meshes with identical vertices. This could be done with a mechanism similar to
MeshVertexBufferLayouts
- although, since vertex buffers have orders of magnitude more data than layouts, it would be beneficial if pointer hashing/equality could be used instead of comparing the inner data. Since this is an optimisation anyway, if there are any platforms that don't support casting pointers to integers (or if, somehow, equal pointers can compare not-equal) then using the previous behaviour of all meshes having a unique buffer is still correct. Only false positives need to be accounted for, not false negatives. - If meshes have a subset of another's attributes, they could reuse the same vertex buffer. In theory, a completely new buffer only needs to be made if an attribute is changed, but insertions and removals wouldn't require any changes. This would be a lot more complex to implement, though, and it's not completely clear to me if there are any cases where this would be useful.
What alternative(s) have you considered?
- As previously mentioned, simply creating many meshes already works, it just requires a lot of unnecessary cloning.
- A smaller optimisation that could address the same usecase would be for meshes to truncate the vertex buffer to the minimum/maximum indices when transferring to the GPU. This would result in the same total number of buffers being created, but would result in fewer unused vertices per mesh. This can be done by the loading code too, although it would be slower than if it was implemented in Bevy since it requires reallocation. This would also require the aforementioned change of making
attributes
anArc
in order to have any benefits. - Smarter deduplication could be done, although this would likely be very expensive