我还没有在这里使用更复杂的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,但他们对数组没有太多了解。
答案 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,因为它可以适合边界。
希望这是有道理的。