2

假设我有以下顶点着色器代码:

#version 330
uniform mat4 ProjectionMatrix, CameraMatrix, SingleModelMatrix;
uniform uint SingleModel;
layout (std140) uniform ModelBlock {
  mat4 ModelMatrices[128];
};

void main(void) {
  ... something that uses ModelMatrices
}

如果在我的程序中,我为代表上述着色器的程序对象发出以下 OpenGL 调用:

getUniformBlockParameter(GL_UNIFORM_BLOCK_DATA_SIZE)

我使用 Intel HD Graphics 4000 卡发现以下内容:

GLUniformBlock[
  name: ModelBlock, 
  blockSize: 8192,
  buffer: java.nio.HeapByteBuffer[pos=0 lim=8192 cap=8192], 
  metadata: {
    ModelMatrices=GLUniformBlockAttributeMetadata[
      name: ModelMatrices, 
      offset: 0, 
      arrayStride: 64,
      matrixStride: 16,
      matrixOrder: 0
  ]},
  uniforms: GLUniformInterface[
    uniforms: {
      ModelMatrices=GLUFloatMat4 [
        name:ModelMatrices, 
        idx:2, 
        loc:-1, 
        size:128, 
        glType:8b5c]
    }
  ]
]

我应该如何解释blockSize参数?OpenGL 3 sdk 文档 指出:

如果 pname 是GL_UNIFORM_BLOCK_DATA_SIZE,则返回与实现相关的最小总缓冲区对象大小(以基本机器单位为单位),用于保存由 uniformBlockIndex 标识的统一块中的所有活动统一。既不保证也不期望给定的实现会将统一值安排为紧密包装在缓冲区对象中。对此的例外是 std140 统一块布局,它保证特定的打包行为并且不需要应用程序查询偏移量和步幅。在这种情况下,仍然可以查询最小大小,即使它只是基于统一块声明预先确定的。

那么在这种情况下,我应该如何测量 8192 中的数字blockSize?在floats? 在bytes?

如果我计算数字,一个 4x4 矩阵mat4制服共有 16 个float分量,适合 64 bytes,所以至少我需要大约16 x 4 x 128字节来存储 128 个矩阵,这确实是8192.

那么为什么硬件还要求数组步长为 64( ? ),矩阵步长bytes为 16( ?),但只请求 8192 个字节?bytes不应该getUniformBlockParameter(GL_UNIFORM_BLOCK_DATA_SIZE)为对齐/填充目的请求更多空间吗?

4

1 回答 1

5

数组步幅是从一个数组元素的开头到下一个数组元素的开头的字节偏移量。本例中的数组元素为mat4s,大小为64 字节。所以数组步幅尽可能小。

矩阵步幅是从矩阵数据的一列/行到下一列/行的字节偏移量。每个都mat4具有 a 的列或行大小vec4,这意味着它的大小为16 个字节。同样,矩阵列/行是紧密排列的。

所以 8KiB 是这种存储的预期大小。

话虽如此,这完全无关紧要。你根本不应该费心去查询这些东西。通过使用std140布局,您已经强制OpenGL 采用特定的布局。一个特别要求mat4s 具有 64 字节的数组跨度和 16 字节的矩阵跨度。您不必为此询问实施;这是标准要求的。

您只需要询问您是否正在使用sharedor packed

于 2013-08-12T03:25:44.260 回答