我目前正在努力了解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搜索来了解这种行为,但找不到任何东西。我希望你们中的一些人可以向我解释这一点,因为这种行为确实使我感到困惑。
答案 0 :(得分:2)
这个答案是基于我对HLSL的理解而得出的猜测,HLSL默认情况下使用列主矩阵填充。 HLSL中的寄存器由四个4字节节的集合组成,每个寄存器总共16字节。然后,每个寄存器将作为一行包含四列。
声明float3x1时,是在声明具有三列和一行的矩阵。这完全适合HLSL的寄存器打包方法,其中单行可以包含16个字节。
声明float1x3时,是在声明具有一列和三行的矩阵。由于HLSL处理寄存器打包的方式,它必须将数据分布在3套寄存器中并保留3x3矩阵的空间。
如果需要1xX矩阵,最好声明一个向量,该向量将自动适合单个寄存器,并且可以在任何情况下使用1x3或3x1矩阵。