关于openGl与CUDA协作的具体实现

来源:互联网 发布:mac共享文件夹在哪 编辑:程序博客网 时间:2024/06/06 15:08

   

                                          关于openGl与CUDA协作的具体实现

共享缓冲区的使用:

 

一个在空白openGL屏幕中绘制的例子:

 

先声明两个全局变量:

//缓冲区对象的ID, 另一个用于保存GL_PIXEL_UNPACK_BUFFER(传递给openGL的)数据

GLuintbuffer;

//接下来是CUDA对共享缓冲区的“名字”

cudaGraphicsResource*resource;

 

在初始化时的操作:

//为CUDA运行时使用OpenGL驱动程序做准备

cudaGLSetGLDevice(设备标识符);

//接下分配cuda的设备内存,用于启动kernel函数,执行你自己的操作

cudaMalloc((void**)&src,bitmap_width*bitmap_height*3);

cudaMemcpy(src,bitmap.buffer,bitmap_width*bitmap_height*3,cudaMemcpyHostToDevice);

注意:分配cuda设备内存时,要在openGL创建了窗口之后才进行,我就因为这个问题纠结了很久。

 

 

接下来要产生openGl的缓冲区对象

glewInit();

 

glGenBuffers(1,buffer);

glBindBuffer(GL_PIXEL_UNPACK_BUFFER,buffer);

glBufferData(GL_PIXEL_UNPACK_BUFFER,bitmap_height*bitmap_width*3,0,GL_DYNAMIC_DRAW);

//为openGL缓冲区buffer注册一个图形资源

cudaGraphicsGLRegisterBuffer(&resource,buffer,cudaGraphicsMapFlagsNone);

PS: 在随后的openGL调用中我们将通过buffer来引用这个共享缓冲区,而在CUDA运行时调用中,则通过resource指针来引用这个缓冲区。

//告诉CUDA运行时映射这个共享资源

cudaGraphicsMapResources(1,&resource,NULL);

//请求一个指向被映射资源的指针,devptr是你自己声明定义的指针

cudaGraphicsResourceGetMappedPointer((void**)&devptr,&size,resource);

 

接下来调用kernel<<<grid,block>>>( devptr,……)利用CUDA处理

注意:在openGL中使用gldrawpixels绘制时,要先取消映射的调用:

cudaGraphicsUnmapResources(1,&resource,NULL);

最后在openGL中绘制:  glBindBuffer(GL_PIXEL_UNPACK_BUFFER,buffer);

                        glDrawPixels();

程序结束时,别忘了释放:

cudaGraphicsUnregisterResource(resource);

glbindbuffer(GL_PIXEL_UNPACK_BUFFER)

glDeleteBuffers(1,&buffer);

 

一个在openGl屏幕截取矩形像素来操作后,再次绘制的例子:

//缓冲区对象的ID, 另一个用于保存GL_PIXEL_PACK_BUFFER(从openGL获取的)数据

GLuintbuffer;

 

 

初始化的操作:

//为CUDA运行时使用OpenGL驱动程序做准备

cudaGLSetGLDevice(设备标识符);

glBindBuffer(GL_PIXEL_PACK_BUFFER,buffer);

glBufferData(GL_PIXEL_PACK_BUFFER,分配的大小(字节),0,GL_DYNAMIC_DRAW);

//将openGl缓冲对象注册到CUDA

cudaGLRegisterBufferObject(buffer);

 

 

在openGl中:

glBindBuffer(GL_PIXEL_PACK_BUFFER,buffer);

//读取屏幕上的像素矩形

glReadPixels(RecordX,RecordY,width,height,format,type,0);

//映射缓冲对象

cudaGLMapBufferObject((void**)&temp,buffer);  

ps:temp是你自己定义的指针,用来操作从openGl屏幕截取的矩形像素

kernel<<<grid,block>>>(temp,……);

//解除映射,绘制到屏幕之前要先解除映射,不然,后果将……(你自己试试)

cudaGLUnmapBufferObject(buffer);

glBindBuffer(GL_PIXEL_UNPACK_BUFFER,buffer);

glDrawPixels();

 

 

最后,释放:

cudaGLUnregisterBufferObject(buffer);

glDeleteBuffers(1,&buffer);

 

 后记:

        感觉自己尝试写openGl和CUDA的协作时,由于接触openGl不多,然后CUDA也是刚学不久,所以都是懵懵懂懂,到处试试,最后还是试出来了,写这篇文章是因为很难找到一篇能有比较完整的openGL和CUDA的实现过程的文章,所以我想写出来和大家分享一下,也能让大家少些调试改错的时间(你知道调试动不动就是几个小时的活),最后那些openGl的函数我假设大家已经对openGL的缓冲区对象有了解了,理解起来不难,如果有什么错误或写错的地方,欢迎提出。好吧,就说到这里。