1

在重新排列一些 OpenCL/GL 互操作代码后,它停止工作并在标题中给出错误。

我已经阅读了许多讨论这个问题的线程,并将其归咎于 (nvidia) 驱动程序。但是因为在此之前运行的代码不应该是我的问题。

代码

正如我已经说过的,我有太多代码无法发布所有内容。此外,到目前为止,我还无法在最少的示例中重现该行为,因此我将用伪代码描述大部分程序,并从我的真实代码中摘录部分内容。

我使用 Qt,因此以下函数都是我的 QGLWidget 子类的所有成员:

void initializeGL()
{
    glewInit();

    cl::Platform::get(&clPlatforms);
    cl_context_properties props[] = {
        CL_GL_CONTEXT_KHR, (cl_context_properties)glXGetCurrentContext(),
        CL_GLX_DISPLAY_KHR, (cl_context_properties)glXGetCurrentDisplay(),
        CL_CONTEXT_PLATFORM, (cl_context_properties)clPlatforms[0](),
        0
    };
    clContext = cl::Context(CL_DEVICE_TYPE_GPU, props, cl_notify, &err);
    std::vector<cl::Device> devices = clContext.getInfo<CL_CONTEXT_DEVICES>();
    clDevice = devices[0];
    clQueue = cl::CommandQueue(clContext, clDevice, 0, 0);
    clProgram = cl::Program(context, sources);
    clProgram.build();    
    clKernel = cl::Kernel(clProgram, "main");
    glGenBuffers(1, &vbo);
    glBindBuffers(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_DYNAMIC_DRAW);
    glBindBuffers(GL_ARRAY_BUFFER, 0);
    vboBuffer = cl::BufferGL(clContext, CL_MEM_READ_WRITE, vbo);
    clKernel.setArg(0, vboBuffer);
}

void paintGL()
{
    simulate();
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //camera transformations ...
    glEnable(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glVertexPointer(3, GL_FLOAT, sizeof(cl_float3), 0);
    glDrawElements(GL_TRIANGLES, 3 * numTriangles, GL_UNSIGNED_INT, triangleIdicesArray);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void simulate()
{
    std::vector<cl::Memory> sharedObjects;
    sharedObjects.push_back(vboBuffer);
    clQueue.enqueueAcquireGLObjects(&sharedObjects); //this triggers the error
    clQueue.enqueNDRangKernel(clKernel, cl::NullRange, cl::NDRangle(numVertices), cl::NullRange);
    clQueue.enqueueReleaseGLObjects(&sharedObjects);
}

关于glEnqueueAcquireGLObjects的一些进一步调查出现了(在注释部分):

在调用 clEnqueueAcquireGLObjects 之前,应用程序必须确保访问 mem_objects 中指定的对象的任何挂起的 GL 操作都已完成。这可以通过在所有具有对这些对象的未决引用的 GL 上下文上发出并等待完成 glFinish 命令来实现。

在获取/释放之前和之后在 OpenCL 命令队列上添加完成让我摆脱了这些错误。

与其他错误一样,我发现错误代码具有误导性,并且通知功能没有添加任何有价值的信息(它说的相同)。

4

0 回答 0