统一缓冲区,glGetActiveUniformBlockiv报告大小

时间:2012-10-04 20:19:42

标签: opengl glsl

我发现GLSL统一块的大小错误。

这是着色器中的块:

uniform MaterialInfo {
    vec3 Ka;
    vec3 Ks;    
    vec3 Kd;
};

然后使用以下代码准备我的统一缓冲区对象:

blockIndex = glGetUniformBlockIndex(program, "MaterialInfo");
 if (blockIndex == -1) {
   fprintf(stderr, "Could not bind uniform block\n");
}

printf("Found blockindex materialinfo: %d\n", blockIndex);

 glGetActiveUniformBlockiv(program, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE, &blockSize);
 blockBuffer = (GLubyte *) malloc(blockSize);
 cout << "GLSL blocksize: " << blockSize << endl;
 cout << "sizeof glm::vec3 type: " << sizeof(mesh->Ka) << endl;
 cout << "sizeof 3 x glm::vec3 type: " << 3 * sizeof(mesh->Ka) << endl;

报告如下:

GLSL blocksize: 48
sizeof glm::vec3 type: 12
sizeof 3 x glm::vec3 type: 36

总之,我期待GLSL块大小为36,而不是48.GLSL中的vec3应该像我的glm :: vec3类型一样浮动。

另请注意,我使用的是HD4000 beta驱动程序:OpenGL 4.0.0 Build 9.17.10.2792。我没有机会在另一台计算机上进行测试。 这是我误解了什么吗?

回复后的跟进:

所以在这种情况下提交我的glm :: vec3浮动的正确方法如下?

glGetUniformIndices(program, 3, namesMaterial, indices);
glGetActiveUniformsiv(program, 3, indices, GL_UNIFORM_OFFSET, offset);

memcpy(blockBuffer + offset[0], glm::value_ptr(mesh->Ka), 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[1], glm::value_ptr(mesh->Ks), 4 * sizeof(GLfloat));
memcpy(blockBuffer + offset[2], glm::value_ptr(mesh->Kd), 4 * sizeof(GLfloat));

2 个答案:

答案 0 :(得分:3)

许多GPU将每个制服填充为vec4的大小:

从OpenGL wiki(强调我的)看到这个implementation note

  

实施说明:由于实现原因,允许OpenGL实现拒绝着色器。因此,通过计算,您可以减少活动的统一组件,但由于统一限制,仍然无法链接。这通常是硬件上的矢量硬件。 Pre GeForce 8xxx硬件和所有ATi硬件都可以做到这一点。在这种情况下,您应该假设每个单独的制服占用4个组件,就像在D3D中一样。这意味着“均匀浮动”是4个组件,mat2x4是16个组件(每行是4个组件),但是mat4x2是8个组件。

答案 1 :(得分:3)

  

总之,我期待GLSL块大小为36,而不是48.GLSL中的vec3应该像我的glm :: vec3类型一样浮动。

为什么呢? OpenGL规范中没有任何内容可以保证块大小。

或者至少,不是 统一块的定义。

如果不提供proper memory layout qualifier,则默认使用shared。这允许实现在元素之间放置任何感觉舒适的填充。所以你不能只假设3 vec3 s将连续12个float s大小。每个vec3将是3个连续的float,但不能保证不会有填充。

如果您需要统一块的固定,已知和一致布局,则需要使用std140布局。否则,您将获得实现为您提供的功能。 OpenGL规范详细说明了std140元素布局的规则。

当然,使用std140布局时,此块的大小为48,因为它会将所有vec3元素填充到vec4 s。< / p>


  

所以在这种情况下提交我的glm :: vec3浮动的正确方法如下?

这是正确的,假设:

  1. memoryBlock是映射的缓冲区对象指针或您使用glBufferSubData
  2. 上传的内容
  3. 您将其上传到缓冲区的前面或其中一个适当的偏移量(glBindBufferRange的统一块的偏移量必须与GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT对齐)。
  4. mesh->Ka及其同类实际上有4个花车。否则你将从未分配的内存中复制。
  5. 同样,我敦促你停止查询这些内容并使用std140布局。当你这样做时,你不必查询偏移量或任何东西;您可以设计与所有硬件上的GLSL定义完美布局兼容的结构。