首页 文章

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

提问于
浏览
3

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

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

我知道vec3不是像许多vec4那样对齐16字节,或者是SIMD兼容的数据类型 . 我知道这个(我想),因为我的C代码中的数据是:

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

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

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

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

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

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

警告:实现有时会使vec3组件的std140布局错误 . 建议您手动填充结构/阵列,避免使用vec3 .

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

1 回答

  • 5

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

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

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

相关问题