关于 OpenGL 布局 std140 统一块中的数组

Posted

技术标签:

【中文标题】关于 OpenGL 布局 std140 统一块中的数组【英文标题】:Regarding arrays in layout std140 uniform block for OpenGL 【发布时间】:2013-03-15 00:54:14 【问题描述】:

根据specification:

如果成员是标量或向量数组,则基对齐 + * 和数组步幅设置为匹配单个的基本对齐方式 + * 数组元素,根据规则(1)、(2)和(3),向上取整 + * 到 vec4 的基本对齐。数组可能在 + * 结束;数组后面成员的基本偏移量向上取整 + * 到基本对齐的下一个倍数。

这是否意味着如果我有一个大小为 3 的 (float)vec3 数组,会是这样吗

vec3,vec3,vec3,(12个空字节达到vec4倍数),(16个空字节因为最后一句)

vec3,(4个空字节),vec3,(4个空字节)vec3,(4个空字节),(因为最后一句是16个空字节)

【问题讨论】:

【参考方案1】:

来自实际OpenGL Specification, version 4.3 (PDF):

3:如果成员是一个三分量向量,其分量消耗 N 基本机器单元,基本对齐为4N。

4:如果成员是标量或向量数组,则基对齐和数组 步幅设置为匹配单个数组元素的基本对齐方式,根据 符合规则 (1)、(2) 和 (3),并向上舍入到 vec4 的基本对齐方式。这 数组末尾可能有填充;以下成员的基本偏移量 数组向上舍入到基本对齐的下一个倍数。

所以vec3 的基本对齐方式为 4*4。因此,vec3 数组的基本对齐方式和数组步长为 4*4。步幅是从一个元素到下一个元素的字节数。所以每个元素的大小为 16 个字节,前 12 个是实际的vec3 数据。

最后,最后有等于基本对齐方式的填充,因此有空白空间。

或者,在图表形式中,vec3[3] 看起来像这样:

|#|#|#|0|#|#|#|0|#|#|#|0| 

其中每个单元格为 4 个字节,# 是实际数据,0 是未使用的数据。

【讨论】:

那么这句话是什么意思呢? “数组后面的成员的基本偏移量向上舍入到基本对齐的下一个倍数。”如果块中有第二个成员,您会在示例中添加额外的 [0][0][0][0] 还是下一个成员的基本偏移量只是您的示例? @DanWebster:基本偏移量四舍五入。因此,如果下一个成员的基本偏移量是 4,它会向上取整为 16。因此,无论下一个成员是什么,它的基本偏移量总是至少为 16。这就是上面最后一个 0 所代表的含义;数组末尾未使用的字节,它将下一个成员与基本对齐对齐。【参考方案2】:

都没有。

红皮书中的appendix L 指出:

标量或向量数组 -> 数组中的每个元素都是底层类型的大小(sizeof(vec4) for vec3),任何元素的偏移量都是它的索引(使用从零开始的索引)乘以元素大小(再次 sizeof(vec4))。整个数组被填充为 vec4 大小的倍数。

所以正确答案是 vec3, (4 empty), vec3, (4 empty),vec3, (4 empty) -> 48 bytes

【讨论】:

以上是关于关于 OpenGL 布局 std140 统一块中的数组的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL中的统一块

GLSL统一布局绑定和纹理

opengl:将数组类型加载到统一缓冲区对象

OpenGL GLSL 统一缓冲区对象

OpenGL使用统一缓冲区作为数组

OpenGL / GLSL - 统一块数据值不正确