Skip to content

meshletcodec: Revise vertex reference encoding for more compression#1012

Merged
zeux merged 4 commits intomasterfrom
mlc-vtxrev
Feb 3, 2026
Merged

meshletcodec: Revise vertex reference encoding for more compression#1012
zeux merged 4 commits intomasterfrom
mlc-vtxrev

Conversation

@zeux
Copy link
Owner

@zeux zeux commented Feb 3, 2026

Warning

The data format continues to be highly experimental. Until a library point release, data compatibility is not guaranteed.

Vertex reference deltas should almost never need 32 bits; even if source references are 32-bits, any reasonable locality preprocessing will rarely result in long distance jumps. However, for some types of preprocessing, deltas that don't fit into 16 bits can be more common. We adjust the encoding to use 3-byte references in a group, unless all 4 references need the full width, in which case they are upgraded to 4 bytes to allow arbitrary data to still be represented.

Also, the vertex control byte now encodes low control bits separately from high control bits. On typical data that reduces the integer range (most bytes have zero high nibble) which improves entropy compression when compressing the encoded output with a general purpose compressor. Together, the changes get ~0.1 bits/triangle back both pre- and post-deflate on average.

The demo code is now also using a slightly smaller header for the stream, however this part is always up to the application and isn't always required.

This contribution is sponsored by Valve.

zeux added 3 commits February 2, 2026 18:27
Instead of encoding the vertex reference codes as 0/1/2/4 bytes, we
encode them as 0/1/2/3 bytes. 4 byte reference encoding is very
wasteful; even on very large meshes it's almost never seen, especially
if the applications follow the best practice of rebasing the meshlet
vertex references (which is usually free because the offset can be
folded into the rest of the packing).

Because we need the encoding to be fully general, we need to be able to
encode 4-byte deltas if we encounter them. For that, we limit the
encoding such that if one delta requires 4 bytes (or all 4 deltas
require 3 bytes), we encode all deltas in this group using 4 bytes.

While this could result in larger encodings in rare cases, usually the
savings make up for it.
Instead of packing two-bit codes sequentially into the control byte, we
pack the low bits into low nibble, and high bits into high nibble.

This does not affect the encoded size, but it improves the statistics
for general purpose compressors when meshletcodec output is compressed
further, resulting in ~0.1 bits/triangle gains for free.
While this is not fully general and won't support meshlets above 128v/t,
practically speaking it's sufficient, and saves a byte in the meshlet
stream encoding - making packed data size a little closer to raw data
size.

Of course, applications can choose any framing or none at all depending
on what works best.
@zeux zeux changed the title meshlet: Revise vertex reference encoding for more compression meshletcodec: Revise vertex reference encoding for more compression Feb 3, 2026
Change the code to be more aligned with table building: the code is
always 2-bit, but the length that's recovered from it is 0-4;
additionally, with this we don't need kLengths lookup because it's an
identity.
@zeux zeux merged commit 63b36ed into master Feb 3, 2026
13 checks passed
@zeux zeux deleted the mlc-vtxrev branch February 3, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant