Add options to lower precision/compressed vertex buffer#21926
Add options to lower precision/compressed vertex buffer#21926beicause wants to merge 42 commits intobevyengine:mainfrom
Conversation
|
This will need some thinking on how it interacts with Virtual Geometry and Solari, which rely on hardcoded vertex formats. |
|
For the octahedral normals and tangents, encoding as UNORM16 or SNORM16 should give better accuracy? Unless there's some compatibility or performance reason to prefer floats. For joint weights, I'd similarly suggest UNORM16. Unless Bevy wants to support joints weights greater than one - I don't know of any engine that does this. For bonus points it should also adjusted the encoded weights to make sure they sum to one. |
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
2 similar comments
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
|
@beicause, I noticed that you also changed the UVs from FLOAT16 to UNORM16. That might be a problem for some assets since it's legitimate for UVs to be outside the [0, 1] range. I'm not sure what the best option is for UVs, so maybe worth seeing if someone else has an opinion. From a glance it seems like Unreal supports FLOAT16/32. Godot does use UNORM16 but scales them to fit the maximum value if they're outside of [0, 1] (ref 1, ref 2). |
|
Also, could the PR description say whether compression is enabled by default? The description currently sounds like it's disabled by default, but the code seems like it's enabled by default. I can't speak for anyone else, but I'm guessing most people would prefer it to be disabled by default. |
|
I think using float16 for UVs is worthwhile because the benefits of unorm16 may be limited after thought. I would probably like to enable compression by default, as other engines seem to do this by default as well. Enabling compression generally provides a net benefit, and users can opt-out if issues arise. |
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
|
Added |
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
|
Some quick drive by thoughts:
|
|
For positions, I'd suggest an AABB-relative unorm16 instead of f16. It's a faff to set up but the worst case error is much lower. I've seen both tried for moderate to high poly characters, and the f16 version had noticeable artifacts. |
|
The reason I suggest f16 is that it's one of the few supported BLAS formats for raytracing https://github.com/Vecvec/wgpu/blob/3e9ede6c38012d6c134e1ced689ded2f58dec49f/wgpu-types/src/features.rs#L1497-L1501, and it has pretty significant improvements over f32 https://zeux.io/2025/03/31/measuring-acceleration-structures/ |
5999291 to
8b85876
Compare
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
|
I've added snorm16 positions relative to AABB. Its precision should be as good as unorm16. And it seems that the BLAS supports it? |
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
1 similar comment
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
|
This deserves a thorough review by me, but I unfortunately won't have time for the next while due to work. Apologies - it's something I'm definitely excited to land though! |
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
greeble-dev
left a comment
There was a problem hiding this comment.
Requesting one small change following updates.
|
Oops, and just noticed solari is broken if cargo run --example solari --features "bevy_solari https free_camera http"Sometimes: Sometimes: |
|
For what it's worth, Solari is the only issue I could find. Tested by screenshot comparison between compression off and everything enabled. Native/Win10/Nvidia: Chrome/WIn10/Nvidia/WebGL+WebGPU |
|
I don't think solari support the compressed Mesh in this PR yet. But I'm not planning to implement it myself as I'm unfamiliar with solari and I don't the hardware to run it. Currently the vertex formats check in solari and meshlet is wrong because the formats of written buffer differs from the formats in |
|
For what it's worth, I've raised on Discord whether the PR could land even though Solari isn't working: https://discord.com/channels/691052431525675048/743663924229963868/1467852870975230054
|
|
Update: I changed Mesh to always write the vertex buffer as is and you need to use the This seems more robust for me - attributes are consistent with the actual vertex buffer, and users can directly create and save the compressed Mesh.
I don't think this a blocker. Solari and meshlet processor inherently have strict requirements for vertex formats and don't support custom vertex attributes. |
|
Your PR caused a change in the graphical output of an example or rendering test. This might be intentional, but it could also mean that something broke! If it's expected, please add the M-Deliberate-Rendering-Change label. If this change seems unrelated to your PR, you can consider updating your PR to target the latest main branch, either by rebasing or merging main into it. |
|
Adding this to 0.19 |
Objective
Resolves #21902.
Solution
This PR adopts a relatively transparent approach to reduce the GPU vertex buffer size. On CPU-side mesh can still use uncompressed Float32 data, and users are not required to insert compressed vertex formats. The vertex data is automatically processed into lower-precision/octahedral encoded data when uploading to the GPU.
To enable vertex attribute compression, just set the
attribute_compressionfield of Mesh, or setmesh_attribute_compressionof GltfLoaderSettings. If enabled, normal and tangent will be octahedral encoded Unorm16x2, uv0, uv1, joint weight and color will be corresponding Unorm16 or Float16. I also provide Unorm8x4 for vertex color if hdr isn't needed.Update 2026-2-16
Removed previous approach that automatically compresses vertex buffer according to flags when uploading to GPU. Instead, I added
compressed_meshmethod to Mesh to construct compressed Mesh ahead of time. GltfLoader can also opt-in mesh compressing when loading. I also add an option to convert indices to u16, though I believe blender gltf exporter already uses u16 indices when possible.Testing
I tested with several 2d and 3d examples and it seems to work.