如何用GL_UNIFORM_BLOCK_DATA_SIZE解释glGetActiveUniformBlockiv的含义

Jes*_*eta 2 opengl glsl opengl-3

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

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

void main(void) {
  ... something that uses ModelMatrices
}
Run Code Online (Sandbox Code Playgroud)

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

getUniformBlockParameter(GL_UNIFORM_BLOCK_DATA_SIZE)
Run Code Online (Sandbox Code Playgroud)

我通过 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]
    }
  ]
]
Run Code Online (Sandbox Code Playgroud)

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

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

那么在这种情况下,我应该如何测量 8192 数字blockSize?在float? 在byte?

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

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

Nic*_*las 5

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

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

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

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

您只需要询问您是否使用sharedpacked