Max size of Matrix4x4 Array in HLSL

Started by
17 comments, last by unbird 9 years, 1 month ago

Hi all I use ID3DX::Effect of DX9 for my shaders.

I have a skinned mesh and coded my own .fx shader but I have this problem where some of my models have 64+ bones and if I declare a Matrix4x4 array of 64 indices or more, the shader doesn't work.

There's no error loading the .fx file, my models just won't appear on screen.

Doesn't work:


float4x4 Bones[64] : WORLDMATRIXARRAY;

Works:


float4x4 Bones[59] : WORLDMATRIXARRAY;

I declare some other variables in the shader aswell. But not many.

I declare VS_2_0 and PS_2_0 in the Technique part of the .fx file. (Maybe there's a limit of .fx size because of this lower version the Vertex Shader?)

Anyone has a suggestion on how to resolve this problem?

Advertisement

If I recall correctly, vs_2_0 only guarantees a minimum of 256 constant registers. So if each float4x4 uses 4 constant registers, then you would be able to safely use a maximum of 64 bone matrices if you have no other constants in your shader. But since you mentioned that you have some other variables, I'm guessing you do have some other constants and that's why you need to use less than 64 matrices.

FYI, the reason that the compiler doesn't complain about you going over the limit is because it's actually a runtime issue. D3D9 lets the driver specify the actual maximum number of vertex shader constants, which you can query via D3DCAPS9.MaxVertexShaderConst. However in practice, I'm pretty sure that almost every driver just sets that to 256.

If you want to get around that limit and you're targeting semi-recent (DX10 era or newer) hardware, then you can read your bone matrices from a texture instead of using shader constants.

Hi thanks for your reply.

Can I use the texture trick in D3D9 though?

Yes, you can use it on D3D9 as long as the GPU supports vertex texture fetch.

By the way, the matrices used for skinning are actually 4x3 ones, so you can fit more like 80 of them in if you rearrange how the data is stored.

Do most GPU support texture fetch? That just means tex2D support right?

As MJP said, Any GPU that's DX10 capable will support vertex texture fetch (which is simply using tex2d in the vertex shader).

These days that's pretty much everything. You have to go back to something like a http://en.wikipedia.org/wiki/Radeon_X1000_Series to find a card that doesn't support it.

Ah ok.

Isnt it a performance hit to update a texture buffer every frame with bone data?

And is it a good idea to keep a texture for each model with bones?

Try compiling for vs_2_x or vs_3_0 instead. I don't remember if they'll give you higher register counts but it's worth a shot.

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

Isnt it a performance hit to update a texture buffer every frame with bone data?

You can request a dynamic texture from the driver, which will be optimized for the case where the CPU frequently updates the contents of the texture.


And is it a good idea to keep a texture for each model with bones?

It should be fine if you do it that way. There will definitely be some driver overhead every time that you need to update a texture, since internally the driver will use buffer renaming techniques which will require allocating you a new region of memory.

I thought I'd use this thread to ask a relevant question, but for DX11.

HLSL:


tbuffer SkinnedMatrices : register(t2)
{
	float4x4 Matrices[2097152];
};

When trying to compile (SM4.0) this the compiler gives the following error:

"vertexshader.hlsl(33,11-27): error X3059: array dimension must be between 1 and 65536"

So the maximum tbuffer size is 65536 x 16 x 4 = 4194304 Bytes, or 4MB.

But a 2048x2048 texture using 4 bytes per pixel is 16 MB large. So why can't tbuffers be as large as textures?

This topic is closed to new replies.

Advertisement