我正在尝试通过 GeForce 8600 GT 上的统一块将整数数组传递给片段着色器(一切均根据 GLSL“#version 330”)。
在应用程序方面我有:
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 倍吗? IE。 std140 将 myarray 的每个成员扩展为 vec4 ,实际内存使用量为 7102*4*4=113632 字节,这是问题的原因?
2)它与“共享”或“打包”一起工作的原因是由于优化消除了这些差距?
3)也许这是一个驱动程序错误?所有事实都表明“......并四舍五入到 vec4 的基本对齐”是原因,但很难接受像整数数组这样简单的东西最终在内存限制方面效率降低了 4 倍。
4)如果这不是一个错误,那么在 std140 的情况下我应该如何组织和访问数组?我可以使用“ivec4”来实现最佳数据分布,但我必须牺牲性能,而不是简单的 x=myarray[i] 来执行 x=myarray[i/4][i%4] 之类的操作来引用每个 ivec4 的各个元素?或者我错过了什么并且有明显的解决方案?