在使用计算着色器生成一组数据并将其存储在Shader Storage缓冲区中之后,我尝试从该缓冲区读取以使用以下代码打印出数据:

#define INDEX_AT(x,y,z,i)   (xyzToId(Vec3i((x), (y), (z)),\
                                     Vec3i(NUM_RAYS_X,\
                                           NUM_RAYS_Y,\
                                           POINTS_ON_RAY))\
                             * 3 + (i))
PRINT_GL_ERRORS();
glBindBuffer(GL_SHADER_STORAGE_BUFFER, dPositionBuffer);
float* data_ptr = NULL;
for (int ray_i = 0; ray_i < POINTS_ON_RAY; ray_i++)
{
    for (int y = 0; y < NUM_RAYS_Y; y++)
    {
        int x = 0;
        data_ptr = NULL;
        data_ptr = (float*)glMapBufferRange(
            GL_SHADER_STORAGE_BUFFER,
            INDEX_AT(x, y, ray_i, 0) * sizeof(float),
            3 * (NUM_RAYS_X) * sizeof(float),
            GL_MAP_READ_BIT);
        if (data_ptr == NULL)
        {
            PRINT_GL_ERRORS();
            return false;
        }
        else
        {
            for (int x = 0; x < NUM_RAYS_X; x++)
            {
                std::cout << "("
                    << data_ptr[x * 3 + 0] << ","
                    << data_ptr[x * 3 + 1] << ","
                    << data_ptr[x * 3 + 2] << ") , ";
            }
        }

        glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
        PRINT_GL_ERRORS();
        std::cout << std::endl;
    }

    std::cout << "\n" << std::endl;
}

其中函数xyzToId将三维坐标转换为一维索引。

但是,当我尝试运行此命令时,程序在调用glMapBufferRange时崩溃,并显示错误消息:
The NVIDIA OpenGL driver lost connection with the display driver due to exceeding the Windows Time-Out limit and is unable to continue.
The application must close.

Error code: 7
Would you like to visit
http://nvidia.custhelp.com/cgi-bin/nvidia.cfg/php/enduser/std_adp.php?p_faqid=3007
for help?

我要映射的缓冲区根本不是很大,只有768个浮点数,并且先前在另一个着色器存储缓冲区(只有两个浮点数)上对glMapBuffer的调用没有问题。我似乎无法在线找到与此错误相关的任何信息,而且我所读到的有关glMapBufferRange速度的所有信息都表明,这种大小的缓冲区仅需花费数十毫秒的时间即可映射,而不是两秒程序崩溃的超时时间。

我是否缺少应如何使用glMapBufferRange的内容?

最佳答案

这是一个无关的错误。今天,我了解到OpenGL有时会缓冲命令,并且一些 Action (例如映射缓冲区)会强制OpenGL完成其队列中的所有命令。在这种情况下,这实际上是分派(dispatch)计算着色器本身的 Action 。

今天,我还了解到,对着色器存储缓冲区进行索引超出范围将导致OpenGL驱动程序冻结,就像需要很长时间才能完成一样。

总而言之,这主要是因为错误被伪装成不同的错误并突然出现在错误的位置。

关于c++ - glMapBufferRange卡住OpenGL驱动程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44853881/

10-13 04:01