pass matrix to shader problem

Started by
0 comments, last by zeo4 9 years, 2 months ago

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.

Advertisement

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}

This topic is closed to new replies.

Advertisement