我做一个计算着色器并行减少。我递归计算片段的组块的边界框(从来自场景产生的G-缓冲器开始渲染),然后包围盒组块的边界框,依此类推,直到我结束了一个单一边界框。
起初我用深度纹理和一个vec2
保持最小和最大深度这样做,我被存储层次结构,像这样的SSBO:
// Each tile holds the min and max depth of the subtiles in the level under it.
// Each tile holds 32 items and is 8*4 or 4*8 depending on the level. Conceptually,
// the texDepth texture is level 4.
layout(std430, binding = 5) buffer aabbHierarchy
{
vec2 level0[8 * 4], // one 8*4 tile
level1[32 * 32], // 8*4 4*8 tiles
level2[256 * 128], // 32*32 8*4 tiles
level3[1024 * 1024]; // 256*128 4*8 tiles
};
最后,我遇到了问题,并决定以切换到全屏的AABB。结构和SSBO改变,像这样:
struct AABB
{
vec4 low, high;
};
layout(std430, binding = 5) buffer aabbHierarchy
{
AABB level0[8 * 4],
level1[32 * 32],
level2[256 * 128],
level3[1024 * 1024];
};
当然,我改变了与相应的执行实际计算的一切。
但现在,事实证明,在GL背景下,当我发出这个程序的glUseProgram
之后的任何电话冻结。在本身glUseProgram
通话有没有任何问题,但任何GL的呼叫后,我做我的挂起申请。这显然最初使用时vec2
没有发生。
我也做了数学,我的SSBO是34636800个字节(带AABB
),远低于128 MB的SSBO块大小限制小。在我的应用程序没有点glCheckError
返回0以外的任何东西,我所有的着色器编译,缓冲区分配和纹理创作的所有工作(至少他们不会返回错误)。作为额外的奖励,分配SSBO相同尺寸与AABB
但使用它作为vec2
着色器不会使应用程序冻结。
我使用一个OpenGL 4.4上下文中的计算着色器#version 430
,不带扩展名。这是上华硕ROG fx553vd在它的Nvidia公司的GeForce GTX 1050上运行。
编辑:因为我无法在MCVE复制,它必须是与它周围的代码。不过,完全没有错误报告是很奇怪的。我能找到非常线挑起了错误,并重现的事实,在这种情况下,任何GL电话(甚至简单glGetIntegerv
)将冻结的申请。
这是一个非常大的项目,因为这很遗憾。该问题的行是there,而项目的根是there。请注意,这是aabbHierarchy
分支,而不是主人。我加了广泛的跟踪只是要清楚何时何地程序崩溃。
编辑2:我添加了一个OpenGL调试上下文,以及所有它确实对我来说是打印出的“缓冲详细信息”不帮助一对夫妇行。
原来这是一个驱动程序问题。我能提供的最小工作例子冻结我的Nvidia,但完美的作品对我的英特尔集成GPU。
以供将来参考,如2019年2月6日的Nvidia驱动正在年龄使用计算着色其声明结构阵列在缓冲器接口块。这工作正常:
layout(std430, binding = 0) buffer bleh
{
vec2 array[100000];
};
但是这将需要5秒钟的实际完成执行glUseProgram
:
struct AABB
{
vec2 a;
};
layout(std430, binding = 0) buffer bleh
{
AABB array[100000];
};
矿山看起来像冻结,因为我通过一个结构,这是做一个完全没有问题的事情拨款超过30 MB缓存,支持着色器存储的,但看到Nvidia驱动是如何发生5秒钟处理100 KB,我只能想一想,要采取多少时间。
在我的英特尔GPU,该glUseProgram
呼吁双方立即执行。我会尽快将此情况报告给Nvidia的。