将结构与std140,CPU端对齐

Rob*_*son 6 c++ opengl uniform

我想这是纯C ++问题和OpenGL问题之间的一种交叉。我有一个统一的缓冲区,正在其中分配sizeof(ShaderData)字节的空间。我在着色器的GPU端使用std140布局。

根据std140规则,我需要在结构的各个位置添加填充以确保矢量正确对齐。下面的结构是一个示例(针对我的观点):

struct ShaderData {

    float Light_Intensity;  
    float _pad1[3];    // align following vec3 on 4N boundary
    Math::Vec3f Light_Position;
    float _pad2;       // align following vec4 on 4N boundary
    Math::Colour4f Light_Ambient;
    Math::Colour4f Light_Diffuse;
    Math::Colour4f Light_Specular;    
    float Light_AttenuationMin;
    float Light_AttenuationMax;

} MyShaderData;
Run Code Online (Sandbox Code Playgroud)

这是人们通常用C ++进行操作的方式吗?还是有一些特殊的关键字或实用说明来使结构CPU端的各个元素对齐?

Jac*_*ack 5

不,这样只会浪费空间。您必须根据std140规则找到优化的布局。

  • 一个float需要4个字节,它对齐了4个字节
  • a vec3需要12个字节,并且对齐16个字节
  • a vec4需要16个字节,并且对齐16个字节

这意味着您可以为您的结构找到更好的布局:

float Light_Intensity;          X
float _pad1[3];                  XXX
Math::Vec3f Light_Position;         XXX
float _pad2;                           X
Run Code Online (Sandbox Code Playgroud)

如您所见,您浪费了4个字节,更糟糕的是,您只能执行以下操作:

Math::Vec3f Light_Position      XXX
float Light_Intensity;             X
Run Code Online (Sandbox Code Playgroud)

使其对齐并且无需浪费字节。之所以有效,是因为vec3它将与16个字节的边界对齐,而float仍然与4个字节的边界对齐。

  • @Robinson除了特定于编译器的东西(例如MSVC上的__declspec(align(16))),gcc的__attribute __((aligned(16)))之外,C ++ 11还具有可扩展的alignas(16)。 (尽管并非所有编译器都支持),只需在相应的成员声明之前添加它们:`alignas(16)Math :: Vec3f Light_Position`。对于不需要float的`float`来说,将struct包装更改为16可能有点太严格了。 (3认同)