HLSL 5.0 float1x3 与 float3x1 常量缓冲区打包规则
HLSL 5.0 float1x3 vs float3x1 constant buffer packing rule
我目前正在努力了解 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 字节的槽中,因为之前的变量大小为 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 字节槽,这是相当浪费的。我用谷歌搜索了很多以了解这种行为,但找不到任何东西。我希望你们中的一些人能给我解释一下,因为这种行为真的让我很困惑。
这个答案是根据我对HLSL的理解猜想的,它默认使用列主矩阵打包。 HLSL 中的寄存器由四个 4 字节部分组成,每个寄存器总共 16 个字节。然后每个寄存器充当具有四列的单行。
当您声明一个 float3x1 时,您就是在声明一个具有 3 列和 1 行的矩阵。这非常适合 HLSL 的寄存器打包方法,其中单行可以包含 16 个字节。
当您声明一个 float1x3 时,您就是在声明一个具有一列三行的矩阵。由于 HLSL 处理寄存器打包的方式,它必须将数据分布在 3 组寄存器中并保留 3x3 矩阵的 space。
如果您需要一个 1xX 矩阵,您最好声明一个向量,而不是声明一个向量,它会自动适合单个寄存器,并且可以在任何情况下使用 1x3 或 3x1 矩阵。
我目前正在努力了解 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 字节的槽中,因为之前的变量大小为 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 字节槽,这是相当浪费的。我用谷歌搜索了很多以了解这种行为,但找不到任何东西。我希望你们中的一些人能给我解释一下,因为这种行为真的让我很困惑。
这个答案是根据我对HLSL的理解猜想的,它默认使用列主矩阵打包。 HLSL 中的寄存器由四个 4 字节部分组成,每个寄存器总共 16 个字节。然后每个寄存器充当具有四列的单行。
当您声明一个 float3x1 时,您就是在声明一个具有 3 列和 1 行的矩阵。这非常适合 HLSL 的寄存器打包方法,其中单行可以包含 16 个字节。
当您声明一个 float1x3 时,您就是在声明一个具有一列三行的矩阵。由于 HLSL 处理寄存器打包的方式,它必须将数据分布在 3 组寄存器中并保留 3x3 矩阵的 space。
如果您需要一个 1xX 矩阵,您最好声明一个向量,而不是声明一个向量,它会自动适合单个寄存器,并且可以在任何情况下使用 1x3 或 3x1 矩阵。