GL_UNIFORM_BLOCK_DATA_SIZE的glGetActiveUniform BlockParam背后的逻辑是什么?

时间:2014-03-27 10:19:11

标签: opengl glsl

我的着色器源是这一个:

#version 330

uniform mat4 camera;

struct S {
  vec2 v;
  mat2 m;
};

layout(std140) uniform SS {
 S s[2];
};

in vec2 v;

void main () {
  gl_Position = camera * vec4(v.x + s[0].m[0][0], v.y, 0.0, 1.0);
}

当我问我的制服块有多大时,GL回答96。但是,如果我假设mat2是4个浮点数,vec2是2个浮点数,我有两个浮点数,而float是4个字节,那么:

(4 + 2) * 2 * 4 = 48

我发现48个字节......为什么这么多?

也许它来自我的结构的对齐到4个字节。在我的vec2

之后,让我们添加2个字节的填充以说明对齐
(4 + 2 + 2) * 2 * 4 = 64

这是64不是 96。那我在哪里错了?事实上,我非常确定我的浮点数是4个字节,因为我可以在它们相互跟随时检索它们......

1 个答案:

答案 0 :(得分:3)

信不信由你,这对于std140布局来说是正常的。要了解原因,您需要阅读下面列出的对齐规则:

OpenGL 4.4 Core Profile Specification - 7.6.2.2标准统一区块布局 - 第131页

  

规则(4):

     
    

如果成员是标量或向量的数组,则根据规则(1)将基本对齐和数组步幅设置为与单个数组元素的基本对齐匹配(2)(3) 向上舍入到vec4 的基本对齐方式。阵列末端可能有填充;数组后面的成员的基本偏移量向上舍入到基本对齐的下一个倍数。

  
     

规则(5):

     
    

如果成员是具有 C 列和 R 行的列主矩阵,则矩阵与 C 数组的存储方式相同根据规则(4),每个 R 组件的列向量。

  

我已经重新编写了您的数据结构,以便从std140对齐的角度说明它的外观:

struct S {
  vec2 v;
  vec2 v_padding;  // NEW (satisfies rule 4 -- mat2 has base alignment 4N)

  //mat2 m;        // ORIGINAL (re-written below for alignment -- see rule 5)

  vec2 m0;
  vec2 m0_padding; // NEW (satisfies rule 4 -- column vectors are aligned to 4N)
  vec2 m1;
  vec2 m1_padding; // NEW (satisfies rule 4 -- column vectors are aligned to 4N)
};
  • vec2 v - > 2N + 2N
  • mat2 m - > 2N + 2N + 2N + 2N

总结构尺寸(以机器为单位):4N + 8N = 12N

数组的大小(以字节为单位):S s [2]

12N * 2 = 24N * 4 / N = 96


这里最大的问题是使用mat类型。

矩阵被视为向量数组,这会增加额外的对齐奇数。在某些情况下,你可以通过使用行主矩阵解决这些奇怪的问题,但是因为这是一个方形矩阵,不会有任何帮助。

我建议您将数据打包到mat2,而不是vec4

struct S {
  vec2 v; // 2N + 2N (padding)
  vec4 m; // 4N
};        // 8N

2N + 2N + 4N = 8N * 2 * 4 / N = 64字节

如果您的着色器中确实需要vec4,则可以编写一些额外的代码将mat2解压缩到mat2变量中。