3

我正在尝试通过 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 的各个元素? 还是我错过了什么并且有明显的解决方案?

4

1 回答 1

4

1) (...) 四舍五入到 vec4 的基本对齐?(……)

是的。

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

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

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

编辑不。GPU 自然地与矢量化类型一起工作。打包类型需要添加进一步的指令来解/复用向量。自从写下这个答案以来,GPU 架构发生了重大变化。如今制造的 GPU 都是单标量架构,其设计强调强大的超标量矢量化。

4)如果它不是一个错误,那么在std140的情况下我应该如何组织和访问一个数组?

不要对如此大的数据使用统一的缓冲区对象。将数据放入 1D 纹理并用于texelFetch对其进行索引。

于 2012-05-28T08:56:26.900 回答