在重新排列一些 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 命令队列上添加完成让我摆脱了这些错误。
与其他错误一样,我发现错误代码具有误导性,并且通知功能没有添加任何有价值的信息(它说的相同)。