OpenGL Uniform Buffer std140布局

时间:2012-05-28 08:18:33

标签: opengl shader uniform

我正试图在GeForce 8600 GT上通过统一块(一切都是根据GLSL“#version 330”)将一个int数组传递给片段着色器。

在应用程序的一侧,我有:

int MyArray[7102];
…
//filling, binding, etc
…
glBufferData(GL_UNIFORM_BUFFER, sizeof(MyArray), MyArray, GL_DYNAMIC_DRAW);

在我的片段着色器中,我按照以下方式声明了块:

layout (std140) uniform myblock
{
int myarray[7102];
};

问题是glCompileShader成功后,glLinkProgram会返回一个错误,说明它无法绑定适当的存储资源。

其他几个事实:

1)GL_MAX_UNIFORM_BLOCK_SIZE返回值65536

2)如果我将元素数量减少到4096,它可以正常工作,无论我使用“int”还是“ivec4”作为数组类型都没有区别。任何高于4096的东西都会给我相同的“存储错误”

3)如果我使用“共享”或“打包”,一切都可以怀疑

在咨询了std140的GLSL 3.3规范之后,我假设对齐/填充存在问题,根据:

“1)如果该成员是一个消耗N个基本机器单元的标量,则基本对齐 是N。

...

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

我的问题:

1)“myblock”是否比仅7102 * 4 = 28408字节大4倍?即std140将myarray的每个成员扩展为vec4,真正的内存使用量是7102 * 4 * 4 = 113632字节,这是问题的原因?

2)它与“共享”或“打包”一起使用的原因是由于优化消除了这些差距?

3)也许这是一个驱动程序错误?所有事实都指向“......并且向上舍入到vec4的基本对齐”是原因,但是很难接受像内存数组一样简单的内容最终在内存约束方面的效率低4倍。 / p>

4)如果它不是bug,那么在std140的情况下我该如何组织和访问数组呢?我可以使用“ivec4”进行最佳的数据分配,但是然后我不得不牺牲性能,比如x = myarray [i / 4] [i%4]来引用每个ivec4的各个元素?或者我错过了什么,有明显的解决方案?

1 个答案:

答案 0 :(得分:4)

  

1)(...)向上舍入到vec4的基线对齐? (...)

  

2)它与“共享”或“打包”一起使用的原因是由于优化消除了这些差距?

是;只是这不是优化性能。

  

3)也许这是一个驱动程序错误?

编辑没有。 GPU本身可以使用矢量化类型。打包类型需要添加进一步的指令来解复用/复用向量。从写这个答案开始,GPU架构发生了重大变化。目前制造的GPU都是单标量架构,其设计强调强大的超标量矢量化。

  

4)如果它不是bug,那么在std140的情况下我该如何组织和访问数组呢?

不要对这么大的数据使用统一的缓冲区对象。将数据放入一维纹理并使用texelFetch对其进行索引。