logo资料库

CUDA和OpenGL互操作的实现及分析.pdf

第1页 / 共3页
第2页 / 共3页
第3页 / 共3页
资料共3页,全文预览结束
CUDA和和OpenGL互操作的实现及分析 互操作的实现及分析 CUDA和OpenGL互操作的基本方式是使用CUDA生成数据,再利用OpenGL在屏幕上绘制出数据所表示的图 形。两者的结合可以通过使用OpenGL的PBO(像素缓冲区对象)或VBO(顶点缓冲区对象)两种方式来实现。描述 了CUDA和OpenGL互操作的步骤并展示了一个使用PBO的实例。该实例运行结果表明,互操作的方式比单纯使 用OpenGL方式快了7~8倍。 摘摘 要:要: 关键词: CUDA;OpenGL;像素缓冲区对象;顶点缓冲区对象 关键词: 互操作的过程[4] 1 CUDA与与OpenGL概述概述  OpenGL是图形硬件的  OpenGL不是一种编程语言,而是一种API(应用程序编程接口)。程序员可以使用某种编程语言(如C或C++)编写绘图软 件,其中调用了一个或多个OpenGL库函数。作为一种API,OpenGL遵循C语言的调用约定。OpenGL开发资料可参考文献[1] 和参考文献[2]。  图形处理器(GPU)原本是处理计算机图形的专用设备,近十年来,由于高清晰度复杂图形实时处理的需求,GPU发展成为高 并行度、多线程、多核的处理器。目前,主流GPU的运算能力已超过主流通用CPU,从发展趋势上来看将来差距会越拉越 大。为了合理地利用GPU 资源,CUDA(统一计算设备架构)应运而生。CUDA是一种由NVIDIA推出的通用并行计算架构[3], 该架构使GPU能够解决复杂的计算问题,并且由于CUDA编程语言基于标准的C语言,从而大大提高了可编程性。 CUDA和OpenGL互操作的基本方式是使用CUDA生成数据,然后使用OpenGL在屏幕上绘制出数据所表示的图形。两者的结 合可以通过两种方式来实现:  (1)使用OpenGL的PBO(像素缓冲区对象)。在该方式下,CUDA直接生成像素数据,OpenGL显示这些像素;  (2)使用OpenGL的VBO(顶点缓冲区对象)。在该方式下,CUDA生成顶点网格数据,OpenGL可以根据需要绘制出平滑的表 面图或线框图或一系列顶点。 这两种方式的核心都是利用cudaGLMapBufferObject函数将OpenGL的缓冲区映射到CUDA的内存空间上,这样,程序员就可 以充分利用CUDA的优点写出性能高的程序在该内存空间上生成数据,这些数据不需要传送,OpenGL可以直接使用。如果不 使用CUDA,这些数据需要由CPU来计算产生。一方面,CPU的计算速度通常比GPU慢;另一方面,这些数据需要传送到 GPU上以供OpenGL显示使用。鉴于此,当数据量很大时,CUDA和OpenGL的混合使用效果明显。 2 CUDA和和OpenGL互操作的过程  CUDA和OpenGL互操作具体步骤如下:  (1)创建窗口及OpenGL运行环境。  (2)设置OpenGL视口和坐标系。要根据绘制的图形是2D还是3D等具体情况设置。(1)和(2)是所有OpenGL程序必需的,这里 也没什么特殊之处,需要注意的是,后面的一些功能需要OpenGL 2.0及以上版本支持,所以在这里需要进行版本检查。  (3)创建CUDA环境。可以使用cuGLCtxCreate或cudaGLSetGLDevice来设置CUDA环境。该设置一定要放在其他CUDA的 API调用之前。  (4)产生一个或多个OpenGL缓冲区用以和CUDA共享。使用PBO和使用VBO差不多,只是有些函数调用参数不同。以下是 具体过程。  GLuint bufferID;  glGenBuffers(1,&bufferID);//产生一个buffer ID  glBindBuffer(parameter1,bufferID);  //将其设置为当前非压缩缓冲区,如果是PBO方式,parameter1设置为GL_PIXEL_UNPACK_BUFFER,如果  是VBO方式,parameter1设置为GL_ARRAY_BUFFER  glBufferData(parameter1,parameter2,NULL,GL_DYNAMIC _COPY);  //给该缓冲区分配数据,PBO方式下,parameter1设置为GL_PIXEL_UNPACK_BUFFER,parameter1设置为图像的长度* 宽度*4。VBO方式下,parameter1设置为GL_ARRAY_BUFFER,parameter2设置为顶点数*16,因为每个顶点包含3个浮点 坐标(x,y,z)和4个颜色字节(RGBA),这样一个顶点包含16 B  (5)用CUDA登记缓冲区。登记可以使用cuGLRegisterBufferObject或cudaGLRegisterBufferObject,该命令告诉OpenGL和 CUDA 驱动程序该缓冲区为二者共同使用。  (6)将OpenGL缓冲区映射到CUDA内存。可以使用cuGLMapBufferObject或cudaGLMapBufferObject,它实际是将CUDA内 存的指针指向OpenGL的缓冲区,这样如果只有一个GPU,就不需要数据传递。当映射完成后,OpenGL不能再使用该缓冲 区。  (7)使用CUDA往该映射的内存写图像数据。前面的准备工作在这里真正发挥作用了,此时可以调用CUDA的kernel,像使用 全局内存一样使用映射了的缓冲区,向其中写数据。  (8)取消OpenGL缓冲区映射。要等前面CUDA的活动完成以后,使用cuGLUnmapBufferObject或 cudaGLUnmapBufferObject函数取消映射。  (9)前面的步骤完成以后就可以真正开始绘图了, OpenGL的PBO和VBO的绘图方式不同,分别为以下两个过程。  ①如果只是绘制平面图形,需要使用OpenGL的PBO及纹理。  glEnable(GL_TEXTURE_2D); //使纹理可用  glGenTextures(1,&textureID); //生成一个textureID  glBindTexture(GL_TEXTURE_2D,textureID);  //使该纹理成为当前可用纹理  glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width, Height,0,GL_BGRA,GL_UNSIGNED_BYTE,NULL);  //分配纹理内存。最后的参数设置数据来源,这里设置为NULL,表示数据来自PBO,不是来自主机内存  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN _FILTER,GL_LINEAR);  glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_ FILTER,GL_LINEAR);//必须设置滤波模式,GL_LINEAR 允许图形伸缩时线性差值。如果不需要线性差值,可以用GL_TEXTURE_RECTANGLE_ARB代替GL_TEXTURE_2D以提高
性能,同时在glTexParameteri()调用里使用GL_NEAREST替换GL_LINEAR  然后就可以指定4个角的纹理坐标,绘制长方形了。  ②绘制3D场景,需要使用VBO。 glEnableClientState(GL_VERTEX_ARRAY); //使顶点和颜色数组可用 glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3,GL_FLOAT,16,0); //设置顶点和颜色指针 glColorPointer(4,GL_UNSIGNED_BYTE,16,12); glDrawArrays(GL_POINTS,0,numVerticies); //根据顶点数据绘图,参数可以使用GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS,GL_QUAD_STRIP,GL_POLYGON (10)前后缓存区来回切换,实现动画显示效果。调用SwapBuffers(),缓冲区切换通常会在垂直刷新间隙来处理,因此,可以 在控制面板上关掉垂直同步,使得缓冲区切换立刻进行。 3 CUDA和和OpenGL互操作性能实例分析 互操作性能实例分析 3.1 测试实例 测试实例
 这是一个相对简单的实例,其主要功能是不断地动态改变一个纹理图案中每个像素的颜色并显示。该实例使用了OpenGL的 PBO并利用了OpenGL与CUDA互操作方式,纹理图案数据的生成主要由CUDA的kernel函数完成,完整程序及CUDA的kernel 函数请参看参考文献[5]。 如果不使用CUDA,整个程序结构变化不大,主要差别是生成该纹理图案的函数在CPU上运行,因而该函数及其调用方式要重 写,具体函数如下: void kernel(uchar4*pos,unsigned int width,unsigned int height,float time) { unsigned int index,x,y; for(x=0;x
分享到:
收藏