我正在尝试通过 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 的东西都会给我同样的“存储错误”</p>
3)如果我使用“共享”或“打包”,一切都像怀疑的那样工作
在咨询了 std140 的 GLSL 3.3 规范后,我假设对齐/填充存在问题:
“1) 如果成员是一个消耗 N 个基本机器单元的标量,则基本对齐是 N。
...
4) 如果成员是标量或向量数组,则根据规则 (1)、(2) 和 (3) 设置基对齐和数组跨度以匹配单个数组元素的基对齐,并四舍五入直到 vec4 的基本对齐。数组末尾可能有填充;数组后面成员的基本偏移量向上舍入到基本对齐的下一个倍数。”</p>
我的问题:
1)“myblock”占用的空间是 7102*4=28408 字节的 4 倍,这是真的吗?即std140将myarray的每个成员扩展为vec4,实际内存使用量为7102*4*4=113632字节,这是问题的原因吗?
2)它与“共享”或“打包”一起工作的原因是由于优化消除了这些差距?
3)也许这是一个驱动程序错误?所有事实都表明“......并向上舍入到 vec4 的基本对齐”是原因,但很难接受像 int 数组这样简单的东西在内存限制方面的效率降低了 4 倍。
4)如果它不是一个错误,那么在std140的情况下我应该如何组织和访问一个数组?我可以使用“ivec4”来优化数据分布,但是我不得不牺牲性能来代替简单的 x=myarray[i/4][i%4] 来引用每个 ivec4 的各个元素? 还是我错过了什么并且有明显的解决方案?