OpenGL和GLSL内存对齐,适用于制服和变化

时间:2017-12-03 06:47:22

标签: c++ opengl alignment glsl shader

我遇到了困扰我的事情,我无法找到答案。当我写这样的着色器时:

layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inTexCoords;

我知道vec3不是16字节对齐的,因为很多vec4都是,或SIMD兼容的数据类型。我知道这个(我想),因为我的C ++代码中的数据是:

struct Vertex
{
    vec3 position;
    vec3 normal;
    vec2 texCoords;
};

每个向量彼此紧密相连,没有填充,大小为8 * sizeof(float),32个字节。我将它传递给制服,着色器读得很好,所以我知道它们都是对齐的。

但是当谈到GLSL中的统一块时,例如std140标准,在添加另一个vec3或vec4之前,必须用额外的四个字节填充vec3:

  
      
  1. 如果该成员是一个三分量向量,其组件消耗N个基本机器单位,则基本对齐为4N
  2.   

但是,你也可以在vec3和下一个vec3之间存储一个四字节的int或四字节bool来压缩大小。那么这是否意味着顶点布局的attrib指针值不遵循std140布局?另外,如果我在我的C ++代码中使用SIMD 16字节对齐的向量,这是否意味着我将不再能够将attrib指针值设置为vec3,vec3,vec2,而是将所有vec4设置为?

此外,我在文档中看到以下警告:

  

警告:实现有时会导致std140布局错误   vec3组件。建议您手动填写   结构/数组输出并完全避免使用vec3。

这里说它完全避免使用vec3,但我认为这是一种智能节省空间的技术,可以在vec3之后打包一个四字节的int或bool。

1 个答案:

答案 0 :(得分:5)

std140布局仅适用于interface blocks,而不适用于缓冲区的内容或接口块之外的属性。由于接口块不能用作顶点着色器的输入或片段着色器的输出,因此std140不会以任何方式影响glVertexAttribPointer的设置方式或顶点数据的存储方式。

关于警告:是的,在vec3存储和int / float / bool之后使用空格是一种聪明的技巧。但正如警告所述,驱动程序实现有时会出错。因此,如果您想确保您的代码在任何地方都可靠运行,您必须进行大量测试或根本不使用vec3。再次注意,这仅适用于接口块。这件事不会触及正常的vec3制服。

你可以做的是打包以在C ++端存储3个浮点数和一个int,但是通过接口块中的vec4访问它。您可以使用floatBitsToInt(myBlock.myVec4.w)来检索整数。