使用足够大的SSBO时,着色器程序上的操作会冻结GL上下文

时间:2019-02-05 00:54:00

标签: opengl gpgpu opengl-4 compute-shader

我正在使用计算着色器进行并行约简。我递归计算片段的边界框(从场景渲染产生的G缓冲区开始),然后是边界框的边界框,依此类推,直到最终得到单个边界框。 / p>

最初,我是使用深度纹理和一个包含最小和最大深度的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];
};

当然,我更改了与执行实际计算有关的所有内容。

但是,事实证明,当我在该程序上glUseProgram之后发出任何调用时,GL上下文将冻结。 glUseProgram调用本身没有任何问题,但是在挂起应用程序之后我执行的任何GL调用都没有问题。最初使用vec2时,显然没有发生这种情况。

我已经完成了数学运算,我的SSBO是34,636,800字节(带有AABB),这远远小于128 MB的SSBO块大小限制。 glCheckError在我的应用程序中绝不会返回0以外的任何东西,并且我所有的着色器编译,缓冲区分配和纹理创建均有效(至少它们不返回错误)。另外,分配与AABB相同的SSBO大小,但在着色器中将其用作vec2不会使应用程序冻结。

我在计算着色器中使用带有#version 430的OpenGL 4.4上下文,没有扩展名。它运行在装有Nvidia GeForce GTX 1050的ASUS RoG fx553vd上。

编辑:由于我无法在MCVE中进行复制,因此这一定与周围的代码有关。但是,完全没有错误报告确实很奇怪。我能够找到引发该错误的那一行,并重现一个事实,在这种情况下,任何GL调用(甚至像glGetIntegerv一样简单)都将冻结应用程序。

这是一个很大的项目,对此感到抱歉。有问题的行是there,而项目的根目录是there。请注意,这是aabbHierarchy分支,不是主分支。我添加了广泛的跟踪功能,目的只是为了弄清楚程序何时何地崩溃。

编辑2:我添加了一个OpenGL调试上下文,它为我所做的只是打印了几行无用的“缓冲区详细信息”。

1 个答案:

答案 0 :(得分:0)

原来是驱动程序问题。我能够提供一个最小的工作示例,该示例可以冻结在我的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,我只想知道要花多少时间。

在我的Intel GPU上,两者的glUseProgram调用会立即执行。我将尽快向Nvidia报告。