Sign in to follow this  
zeo4

pass matrix to shader problem

Recommended Posts

Can anyone explain the below behavior?

 

having:

D3D11_INPUT_ELEMENT_DESC _desc[] = {
    {"VERT_COORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"WVP", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
    {"WVP", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
    {"WVP", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
    {"WVP", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1},
};

when I:

// (vertex shader)
float4 main(float4 _vert : VERT_COORD, float4x4 _wvp : WVP) : SV_Position {...}

"_wvp" matrix is transposed (I do it on the CPU side). But if I:

// (vertex shader)
float4 main(float4 _vert : VERT_COORD, float4 _wvp0 : WVP0, float4 _wvp1 : WVP1, float4 _wvp2 : WVP2, float4 _wvp3 : WVP3) : SV_Position {
    float4x4 _wvp = float4x4(_wvp0, _wvp1, _wvp2, _wvp3);
    
    // or
    
    float4x4 _wvp = float4x4(
        _wvp0.x, _wvp0.y, _wvp0.z, _wvp0.w,
        _wvp1.x, _wvp1.y, _wvp1.z, _wvp1.w,
        _wvp2.x, _wvp2.y, _wvp2.z, _wvp2.w,
        _wvp3.x, _wvp3.y, _wvp3.z, _wvp3.w
    );
    ...
}

"_wvp" is now not transposed.

Edited by zeo4

Share this post


Link to post
Share on other sites

Ok, I've got it.

The problem lies within operations on float4x4 when column-majority packing is on. Simply all the float4x4 operations then assume that columns (not rows) are stored next to each other in memory. Therefore:

 

this

#pragma pack_matrix(column_major)
float4x4 mtx = float4x4(val0, val1, val2, val3);

is stored in memory like that

mtx
val0.x  val1.x  val2.x  val3.x  val0.y  val1.y  val2.y  val3.y  val0.z  val1.z  val2.z  val3.z  val0.w  val1.w  val2.w  val3.w

and this

#pragma pack_matrix(row_major)
float4x4 mtx = float4x4(val0, val1, val2, val3);

is stored in memory like that

mtx
val0.x  val0.y  val0.z  val0.w  val1.x  val1.y  val1.z  val1.w  val2.x  val2.y  val2.z  val2.w  val3.x  val3.y  val3.z  val3.w

Another example of an operation that takes into account the above rule is operator[].

// mtx (float4x4)
// 00 01 02 03
// 10 11 12 13
// 20 21 22 23
// 30 31 32 33
// memory
// 00 01 02 03 10 11 12 13 20 21 22 23 30 31 32 33

#pragma pack_matrix(row_major)
// get third row in a row-major configuration
mtx[2]; // row-major is on, so it's instructed that row values are next to each other in memory, so it takes {20 21 22 23}

#pragma pack_matrix(column_major)
// get third row in a column-major configuration
mtx[2]; // column-major is on, so it's instructed that row values are every 4th value in memory, so it takes {02 12 22 32}
Edited by zeo4

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this