OpenCL中clEnqueueMapBuffer的问题

时间:2016-08-19 11:13:21

标签: opencl nvidia

我正在开发一个在OpenCL中实现递归光线跟踪的程序。 要运行内核,我必须选择设备:与系统集成的Intel和Nvidia GeForce图形卡。

当我使用第一台设备运行项目时没有问题;它正确运行并显示算法的结果就好了。

但是当我尝试使用Nvidia设备运行它时,它会在具有同步缓冲区映射的回调函数中崩溃。

崩溃的代码部分如下:

clEnqueueNDRangeKernel(   queue, kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);

// 7. Look at the results via synchronous buffer map.
cl_float4 *ptr = (cl_float4 *) clEnqueueMapBuffer( queue, buffer, CL_TRUE, CL_MAP_READ, 0, kWidth * kHeight * sizeof(cl_float4), 0, NULL, NULL, NULL ); 
cl_float *viewTransformPtr = (cl_float *) clEnqueueMapBuffer( queue, viewTransform, CL_TRUE, CL_MAP_WRITE, 0, 16 * sizeof(cl_float), 0, NULL, NULL, NULL ); 
cl_float *worldTransformsPtr = (cl_float *) clEnqueueMapBuffer( queue, worldTransforms, CL_TRUE, CL_MAP_WRITE, 0, 16 * sizeof(cl_float), 0, NULL, NULL, NULL ); 

memcpy(viewTransformPtr, viewMatrix, sizeof(float)*16);
memcpy(worldTransformsPtr, sphereTransforms, sizeof(float)*16);

clEnqueueUnmapMemObject(queue, viewTransform, viewTransformPtr, 0, 0, 0);
clEnqueueUnmapMemObject(queue, worldTransforms, worldTransformsPtr, 0, 0, 0);

unsigned char* pixels = new unsigned char[kWidth*kHeight*4];
for(int i=0; i <  kWidth * kHeight; i++){
    pixels[i*4] = ptr[i].s[0]*255;
    pixels[i*4+1] = ptr[i].s[1]*255;
    pixels[i*4+2] = ptr[i].s[2]*255;
    pixels[i*4+3] = 1;
}

glBindTexture(GL_TEXTURE_2D, 1);
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexImage2D(GL_TEXTURE_2D, 0, 4, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
delete [] pixels;

最后两次调用clEnqueueMapBuffer会返回与CL_OUT_OF_RESOURCES匹配的错误-5,但我相信缓冲区的大小是正确的。

1 个答案:

答案 0 :(得分:0)

根据CL规范,调用来自回调的CL阻塞调用是未定义的。您的代码可能是正确的,但您无法从回调中使用它。在具有集成内存的英特尔平台中,地图是无操作的,因此不会失败。

CL spec: clSetEventCallbacks

  

调用昂贵的系统例程,OpenCL API调用的行为   创建上下文或命令队列,或阻止OpenCL操作   以下列表中,回调中未定义。

clFinish
clWaitForEvents
blocking calls to clEnqueueReadBuffer, clEnqueueReadBufferRect, clEnqueueWriteBuffer, and clEnqueueWriteBufferRect
blocking calls to clEnqueueReadImage and clEnqueueWriteImage
blocking calls to clEnqueueMapBuffer and clEnqueueMapImage
blocking calls to clBuildProgram
     

如果应用程序需要等待完成例程   以上l ist在回调中,请使用非阻塞形式   函数,并为其分配完成回调以执行其余操作   你的工作请注意,当回调(或其他代码)排队时   命令到命令队列,不需要开始命令   执行直到队列被刷新。在标准用法中,阻止   enqueue calls通过隐式刷新队列来提供此角色。以来   在回调中不允许阻塞调用,那些回调就是这样   命令队列上的enqueue命令应该调用clFlush   返回之前排队或安排稍后调用clFlush   另一个线程。