HLSL 5.0 float1x3与float3x1常量缓冲区打包规则

时间:2018-11-17 16:17:04

标签: directx directx-11 hlsl

我目前正在努力了解HLSL 5.0和D3D11中的恒定缓冲区打包规则。所以我玩了一点fxc.exe:

// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.18773
//
//
// Buffer Definitions:
//
// cbuffer testbuffer
// {
//
//   float foo;                         // Offset:    0 Size:     4
//   float3x1 bar;                      // Offset:    4 Size:    12 [unused]
//
// }
//
//
// Resource Bindings:
//
// Name                                 Type  Format         Dim Slot Elements
// ------------------------------ ---------- ------- ----------- ---- --------
// testbuffer                        cbuffer      NA          NA    0        1

到目前为止,一切都按照我的预期进行。 float3x1的大小为12个字节,因此可以放置在前16个字节的插槽中,因为before变量的大小为4个字节。 将float3x1更改为float1x3之后,编译器输出现在如下所示:

// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.18773
//
//
// Buffer Definitions:
//
// cbuffer testbuffer
// {
//
//   float foo;                         // Offset:    0 Size:     4
//   float1x3 bar;                      // Offset:   16 Size:    36 [unused]
//
// }
//
//
// Resource Bindings:
//
// Name                                 Type  Format         Dim Slot Elements
// ------------------------------ ---------- ------- ----------- ---- --------
// testbuffer                        cbuffer      NA          NA    0        1

因此,似乎HLSL编译器突然将float1x3中的每个浮点数赋予了自己的16字节槽,这非常浪费。我用大量的Google搜索来了解这种行为,但找不到任何东西。我希望你们中的一些人可以向我解释这一点,因为这种行为确实使我感到困惑。

1 个答案:

答案 0 :(得分:2)

这个答案是基于我对HLSL的理解而得出的猜测,HLSL默认情况下使用列主矩阵填充。 HLSL中的寄存器由四个4字节节的集合组成,每个寄存器总共16字节。然后,每个寄存器将作为一行包含四列。

声明float3x1时,是在声明具有三列和一行的矩阵。这完全适合HLSL的寄存器打包方法,其中单行可以包含16个字节。

声明float1x3时,是在声明具有一列和三行的矩阵。由于HLSL处理寄存器打包的方式,它必须将数据分布在3套寄存器中并保留3x3矩阵的空间。

如果需要1xX矩阵,最好声明一个向量,该向量将自动适合单个寄存器,并且可以在任何情况下使用1x3或3x1矩阵。