HLSL常量缓冲区中阵列的意外大小

时间:2014-06-18 03:03:45

标签: c++ directx direct3d hlsl

我还没有在这里使用更复杂的CB,但据我所知,我的C ++对齐和打包必须与HLSL所期望的相匹配。所以我尝试figure out the rules,因此我可以预测C++ struct来匹配HLSL期望的内容。

我正在Vertex Shader v5进行一些测试,以查看输出中产生的包装,并在vs.hlsl中使用此结构:

cbuffer conbuf {
    float m0;
    float m1;
    float4 m2;
    bool m3[1];
    bool m4[4];
    float4 m5;
    float m6;
    float4 m7;
    matrix m8;
    float m9;
    float m10;
    float4 m11[2];
    float m12[8];
    float m13;
};

产生以下输出(在Header File Name VC ++项目HLSL设置中):

cbuffer conbuf {
    float m0; // Offset: 0 Size: 4
    float m1; // Offset: 4 Size: 4
    float4 m2; // Offset: 16 Size: 16
    bool m3; // Offset: 32 Size: 4
    bool m4[4]; // Offset: 48 Size: 52
    float4 m5; // Offset: 112 Size: 16
    float m6; // Offset: 128 Size: 4
    float4 m7; // Offset: 144 Size: 16
    float4x4 m8; // Offset: 160 Size: 64
    float m9; // Offset: 224 Size: 4
    float m10; // Offset: 228 Size: 4
    float4 m11[2]; // Offset: 240 Size: 32
    float m12[8]; // Offset: 272 Size: 116
    float m13; // Offset: 388 Size: 4
};

我几乎想出了偏移如何工作(基于尺寸)但我无法理解数组大小。

这里的一些数组大小似乎是随机的。 我无法弄清bool m4[4]数组的大小:52。float m12[8]的大小相同:116。 HLSL编译器如何设法生成这些的大小?

有任何帮助吗?我已经查看了MSDN packing page,但他们对数组没有太多了解。

1 个答案:

答案 0 :(得分:9)

我会稍微简化你的例子,因为你已经得到了填充。

根据包装规则(您提到的链接),数组的一个重要部分是:

  

默认情况下,数组未在HLSL中打包。为了避免强制着色器为偏移计算承担ALU开销,数组中的每个元素都存储在一个四分量向量中。

所以,让我们来看看这个简单的cbuffer:

cbuffer cbPerObj : register( b0 )
{
     float Alpha[4];
};

根据上述规则(每个浮点数存储在四个向量中),这将(几乎)等效于:

cbuffer cbPerObj : register( b0 )
{
     float4 Alpha[4];
};

或(扩展)

 cbuffer cbPerObj : register( b0 )
{
     float Alpha1;
     float3 Dummy1;
     float Alpha2;
     float3 Dummy2;
     float Alpha3;
     float3 Dummy3;
     float Alpha4;
};

你可以注意到,你的最后一个元素没有填充,这就是为什么你可以注意到你的情况:

bool m4[4]; // Offset: 48 Size: 52
float4 m5; // Offset: 112 Size: 16

m4是16 * 4 = 64(减去最后3),64-12 = 52

您还可以注意到,当然,48 + 52 = 100(因为m5不需要跨越边界,您可以找到偏移的12个丢失字节)

如果你有,

bool m4[4]; // Offset: 48 Size: 52
float m5;

m5的偏移量为100,因为它可以适合边界。

希望这是有道理的。