【问题标题】:Uniform buffers, glGetActiveUniformBlockiv reporting of size统一缓冲区,glGetActiveUniformBlockiv 报告大小
【发布时间】:2012-10-05 06:07:40
【问题描述】:

我发现 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 测试版驱动程序: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));

【问题讨论】:

  • 对齐?我敢打赌那些 vec3 正在被 vec4 填充。

标签: opengl glsl


【解决方案1】:

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

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

或者至少,没有那个统一块的定义。

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

如果您想要统一块的固定、已知和一致布局,那么您需要使用std140 布局。否则,您将得到实现所提供的东西。 OpenGL 规范详细说明了std140 元素布局的规则。

当然,使用std140 布局,该块的大小也为48,因为它将所有vec3 元素填充到vec4s。


那么在这种情况下,提交我的 glm::vec3 浮点数的正确方法如下?

这是正确的,假设:

  1. memoryBlock 要么是映射的缓冲区对象指针,要么是您使用 glBufferSubData 上传的东西
  2. 您正在将其上传到缓冲区的前面或适当的偏移量之一(glBindBufferRange 的统一块偏移量必须与GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 对齐)。
  3. mesh-&gt;Ka 和它的同类实际上做了 4 个浮点数。否则,您将从未分配的内存中复制。

再次,我敦促您停止查询这些内容并使用std140 布局。当你这样做时,你不必查询偏移量或任何东西;您可以设计在所有硬件上与 GLSL 定义完美布局兼容的结构。

【讨论】:

  • 感谢您的回复。更新我的问题,跟进如何创建 blockBuffer。这是正确的方法吗?我问的原因是,这在有一个统一块时有效,但是一旦我添加第二个统一块,我就会崩溃。
  • @toeplitz:Stack Overflow 不会很快耗尽数据库空间。询问有关不同(即使有些相关)问题的后续问题的方法是再次按下“”按钮。但是,我更新了我的答案以评论您的问题。如果您需要有关崩溃问题的帮助,您需要提出一个新问题来展示该代码。
【解决方案2】:

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

请参阅来自 OpenGL wiki 的 implementation note(重点是我的):

实现说明:允许 OpenGL 实现基于实现相关的原因拒绝着色器。因此,根据您的估算,您可以拥有更少的活动统一组件,并且由于统一限制仍然无法链接。这通常发生在完全是矢量硬件的硬件上。 GeForce 8xxx 之前的硬件和所有 ATi 硬件都这样做。在这种情况下,您应该假设每个单独的制服占用 4 个组件,就像在 D3D 中一样。这意味着一个“统一浮点”是 4 个组件,一个 mat2x4 是 16 个组件(每行是 4 个组件),但一个 mat4x2 是 8 个组件。

【讨论】:

    猜你喜欢
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 2013-07-15
    • 1970-01-01
    • 2020-09-05
    • 2014-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多