Packing vertex attributes

Started by
4 comments, last by Adam Miles 8 years, 4 months ago

While looking at skinned mesh shaders one idea struck me. Bone indices and weights are sent per vertex as 4-byte floats, such as below:


struct VSIn
{
    float3 mPosition : POSITION;
    float3 mNormal : NORMAL;
    // ...
    float4 mBoneIndices : BONEINDICES;
    float4 mBoneWeights : BONEWEIGHTS;
};

It seems awfully wasteful to send bone indices as full 4-byte floats when in reality each value is probably up for 4 and would thus all easily fit into one float.

Same (probably?) applies to weights which i don't *think* needs all the fractions provided by 4-byte float?

When looking at MSDN docs it seems the smallest scalar type is 4 bytes, there is a half-float but only for backwards compatability? Likewise there dosn't seem to be any bitwise operators in HLSL.

If bandwidth is such a precious resource is there some clever trick to pack the vertex attributes tighter and ultimately is it worth the effort?

Advertisement

Vertex attributes are usually already compressed/quantized to much smaller data types. The fact that an attribute is marked as "float" in HLSL doesn't mean that it's stored as 32bit IEEE floats in the vertex buffer.

A vertex colour (for example) will usually be declared in the input layout and stored in the vertex buffer as DXGI_FORMAT_R8G8B8A8_UNORM. Which is to say that each channel is 8 bits, unsigned and normalized to 0-1.

Bone indices should be "uint4" for a start, but also declared as DXGI_FORMAT_R8G8B8A8_UINT in the input layout and stored as such in the vertex buffer.

Bone weights will probably want more than 8 bit values, so DXGI_FORMAT_R16G16B16A16_UNORM would perhaps be appropriate. 16 bits per bone weight and again normalised to 0-1 so you aren't wasting bits on negative numbers and values greater than 1.

Are you currently storing everything as full-fat 32 bit floats in your vertex buffer, because if so, that is indeed very wasteful?

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Sorry, I totally forgot about input layout and formats. :) Never mind the question!


Likewise there dosn't seem to be any bitwise operators in HLSL
SM4+ has full integer support with bitwise operators, so you can do this kind of fancy stuff manually... but yeah, as above, even on SM2/3, you'd use the input assembler to store indices and weights inside bytes.

On the last game I shipped, the animators actually noticed annoying errors when using 8bit weights, so we actually went with 10bits though!

On the last game I shipped, the animators actually noticed annoying errors when using 8bit weights, so we actually went with 10bits though!

I am assuming you calculated 4th weight implicitily?

Wrong topic. Mods can delete this post.

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

This topic is closed to new replies.

Advertisement